1 /*
2  *  t_cose_util.h
3  *
4  * Copyright 2019, Laurence Lundblade
5  * Copyright (c) 2020, Arm Limited. All rights reserved.
6  *
7  * SPDX-License-Identifier: BSD-3-Clause
8  *
9  * See BSD-3-Clause license in README.md
10  */
11 
12 
13 #ifndef __T_COSE_UTIL_H__
14 #define __T_COSE_UTIL_H__
15 
16 #include <stdint.h>
17 #include "q_useful_buf.h"
18 #include "t_cose_common.h"
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /**
25  * \file t_cose_util.h
26  *
27  * \brief Utility functions used internally by the t_cose implementation.
28  *
29  */
30 
31 
32 /**
33  * The modes in which the payload is passed to create_tbs_hash().
34  * This exists so the TBS bytes can be hashed in two separate chunks
35  * and avoids needing a second buffer the size of the payload in the
36  * t_cose implementation.
37  */
38 enum t_cose_tbs_hash_mode_t {
39     /** The bytes passed for the payload include a wrapping bstr so
40      * one does not need to be added.
41      */
42     T_COSE_TBS_PAYLOAD_IS_BSTR_WRAPPED,
43     /** The bytes passed for the payload do NOT have a wrapping bstr
44      * so one must be added.
45      */
46     T_COSE_TBS_BARE_PAYLOAD
47 };
48 
49 
50 /**
51  * The modes in which the payload is passed to create_tbm().  This
52  * exists so the ToBeMaced bytes can be hashed in two separate chunks and
53  * avoids needing a second buffer the size of the payload in the
54  * t_cose implementation.
55  */
56 enum t_cose_tbm_payload_mode_t {
57     /** The bytes passed for the payload include a wrapping bstr so
58      * one does not need to be added.
59      */
60     T_COSE_TBM_PAYLOAD_IS_BSTR_WRAPPED,
61     /** The bytes passed for the payload do NOT have a wrapping bstr
62      * so one must be added.
63      */
64     T_COSE_TBM_BARE_PAYLOAD
65 };
66 
67 /**
68  * This value represents an invalid or in-error algorithm ID.  The
69  * value selected is 0 as this is reserved in the IANA COSE algorithm
70  * registry and is very unlikely to ever be used.  (It would take am
71  * IETF standards-action to put it to use).
72  */
73 #define T_COSE_INVALID_ALGORITHM_ID COSE_ALGORITHM_RESERVED
74 
75 
76 /*
77  * Format of ToBeMaced bytes
78  * This is defined in COSE (RFC 8152) section 6.2. It is the input to the HMAC
79  * operation.
80  *
81  * MAC_structure = [
82  *      context : "MAC0",
83  *      protected : empty_or_serialized_map,
84  *      external_aad : bstr,
85  *      payload : bstr
86  * ]
87  */
88 
89 /**
90  * This is the size of the first part of the CBOR encoded ToBeMaced
91  * bytes. It is around 30 bytes.
92  */
93 #define T_COSE_SIZE_OF_TBM \
94     1 + /* For opening the array */ \
95     sizeof(COSE_MAC_CONTEXT_STRING_MAC0) + /* "MAC0" */ \
96     2 + /* Overhead for encoding string */ \
97     T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS + /* entire protected headers */ \
98     1 + /* Empty bstr for absent external_aad */ \
99     9 /* The max CBOR length encoding for start of payload */
100 
101 
102 /**
103  * \brief Return hash algorithm ID from a signature algorithm ID
104  *
105  * \param[in] cose_algorithm_id  A COSE signature algorithm identifier.
106  *
107  * \return \c T_COSE_INVALID_ALGORITHM_ID when the signature algorithm ID
108               is not known.
109  *
110  * This works off of algorithm identifiers defined in the
111  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
112  * Corresponding local integer constants are defined in
113  * t_cose_standard_constants.h.
114  *
115  * COSE signing algorithms are the combination of public key
116  * algorithm, hash algorithm and hash size and imply an appropriate
117  * key size.  They are simple integers making them convenient for
118  * direct use in code.
119  *
120  * This function returns an identifier for only the hash algorithm
121  * from the combined identifier.
122  *
123  * If the needed algorithm identifiers are not in the IANA registry,
124  * they can be added to it. This will take some time and work.  It is
125  * also fine to use algorithms in the COSE proprietary space.
126  */
127 int32_t hash_alg_id_from_sig_alg_id(int32_t cose_algorithm_id);
128 
129 /**
130  * \brief Create the ToBeMaced (TBM) structure bytes for COSE.
131  *
132  * \param[in] tbm_first_part_buf  The buffer to contain the first part
133  * \param[in] protected_headers   The CBOR encoded protected headers.
134  * \param[out] tbm_first_part     Pointer and length of buffer into which
135  *                                the resulting TBM is put.
136  * \param[in] payload_mode        See \ref t_cose_tbm_payload_mode_t.
137  * \param[in] payload             The CBOR encoded payload. It may or may
138  *                                not have a wrapping bstr per
139  *                                \c payload_mode.
140  *
141  * \return This returns one of the error codes defined by \ref t_cose_err_t.
142  *
143  * \retval T_COSE_ERR_SIG_STRUCT
144  *         Most likely this is because the protected_headers passed in
145  *         is larger than \ref T_COSE_MAC0_MAX_PROT_HEADER.
146  * \retval T_COSE_ERR_UNSUPPORTED_HASH
147  *         If the hash algorithm is not known.
148  * \retval T_COSE_ERR_HASH_GENERAL_FAIL
149  *         In case of some general hash failure.
150  */
151 enum t_cose_err_t create_tbm(UsefulBuf                       tbm_first_part_buf,
152                              struct q_useful_buf_c           protected_headers,
153                              struct q_useful_buf_c          *tbm_first_part,
154                              enum t_cose_tbm_payload_mode_t  payload_mode,
155                              struct q_useful_buf_c           payload);
156 
157 /**
158  * \brief Create the hash of the to-be-signed (TBS) bytes for COSE.
159  *
160  * \param[in] cose_algorithm_id     The COSE signing algorithm ID. Used to
161  *                                  determine which hash function to use.
162  * \param[in] protected_parameters  Full, CBOR encoded, protected parameters.
163  * \param[in] payload_mode          See \ref t_cose_tbs_hash_mode_t.
164  * \param[in] payload               The CBOR encoded payload. It may or may
165  *                                  not have a wrapping bstr per
166  *                                  \c payload_mode.
167  * \param[in] buffer_for_hash       Pointer and length of buffer into which
168  *                                  the resulting hash is put.
169  * \param[out] hash                 Pointer and length of the
170  *                                  resulting hash.
171  *
172  * \return This returns one of the error codes defined by \ref t_cose_err_t.
173  *
174  * \retval T_COSE_ERR_SIG_STRUCT
175  *         Most likely this is because the protected_parameters passed in
176  *         is larger than \c T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS.
177  * \retval T_COSE_ERR_UNSUPPORTED_HASH
178  *         If the hash algorithm is not known.
179  * \retval T_COSE_ERR_HASH_GENERAL_FAIL
180  *         In case of some general hash failure.
181  *
182  * The input to the public key signature algorithm in COSE is the hash
183  * of a CBOR encoded structure containing the protected parameters
184  * algorithm ID and a few other things. This formats that structure
185  * and computes the hash of it. These are known as the to-be-signed or
186  * "TBS" bytes. The exact specification is in
187  * [RFC 8152 section 4.4](https://tools.ietf.org/html/rfc8152#section-4.4).
188  */
189 enum t_cose_err_t create_tbs_hash(int32_t                     cose_algorithm_id,
190                                   struct q_useful_buf_c       protected_parameters,
191                                   enum t_cose_tbs_hash_mode_t payload_mode,
192                                   struct q_useful_buf_c       payload,
193                                   struct q_useful_buf         buffer_for_hash,
194                                   struct q_useful_buf_c      *hash);
195 
196 
197 
198 
199 #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
200 
201 /**
202  * Size of the key returned by get_short_circuit_kid(). It is always
203  * this size.
204  */
205 #define T_COSE_SHORT_CIRCUIT_KID_SIZE 32
206 
207 
208 /**
209  * \brief Get the special kid for short-circuit signing.
210  *
211  * \returns Buffer with the kid.
212  *
213  * This always returns the same kid. It always indicates short-circuit
214  * signing. It is OK to hard code this kid value as the probability of
215  * collision with this ID is extremely low and the same as for
216  * collision between any two key IDs (kids) of any sort.
217  *
218  * This always returns a pointer to the same memory as the result
219  * returned by this never changes.
220  *
221  * This is the value of the kid.
222  *
223  *        0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70,
224  *        0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a,
225  *        0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6,
226  *        0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6
227  *
228  */
229 struct q_useful_buf_c get_short_circuit_kid(void);
230 #endif
231 
232 #ifdef __cplusplus
233 }
234 #endif
235 
236 #endif /* __T_COSE_UTIL_H__ */
237