1 /*
2  * t_cose_common.h
3  *
4  * Copyright 2019, Laurence Lundblade
5  * Copyright (c) 2020-2021, 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_COMMON_H__
14 #define __T_COSE_COMMON_H__
15 
16 #include <stdint.h>
17 #include "q_useful_buf.h"
18 
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22 
23 /**
24  * \file t_cose_common.h
25  *
26  * \brief This file contains definitions common to all public t_cose
27  * interfaces.
28  *
29  * t_cose_common.h contains the definitions common to all public
30  * t_cose interfaces, particularly the error codes, algorithm
31  * identification constants and the structure containing a key.
32  *
33  * **Compile Time Configuration Options**
34  *
35  * \c T_COSE_DISABLE_SHORT_CIRCUIT_SIGN -- This disables short-circuit
36  * signing test mode. This saves a small amount of object code
37  *
38  * \c T_COSE_DISABLE_ES512 -- Disables the COSE algorithm ES512
39  * algorithm. This saves a tiny amount of code and a few hundred bytes
40  * of stack. It saves more than \c T_COSE_DISABLE_ES384.
41  *
42  * \c T_COSE_DISABLE_ES384 -- Disables the COSE algorithm ES384
43  * algorithm. This saves a tiny amount of code and a few hundred bytes
44  * of stack. No stack will be saved if \c T_COSE_DISABLE_ES512 is not
45  * also defined.
46  *
47  * \c T_COSE_DISABLE_CONTENT_TYPE -- Disables the content type
48  * parameters for both signing and verifying.
49  */
50 
51 
52 
53 
54 /**
55  * \def T_COSE_ALGORITHM_ES256
56  *
57  * \brief Indicates ECDSA with SHA-256.
58  *
59  * This value comes from the
60  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
61  *
62  * The COSE standard recommends a key using the secp256r1 curve with
63  * this algorithm. This curve is also known as prime256v1 and P-256.
64  */
65 #define T_COSE_ALGORITHM_ES256 -7
66 
67 /**
68  * \def T_COSE_ALGORITHM_ES384
69  *
70  * \brief Indicates ECDSA with SHA-384.
71  *
72  * This value comes from the
73  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
74  *
75  * The COSE standard recommends a key using the secp384r1 curve with
76  * this algorithm. This curve is also known as P-384.
77  */
78 #define T_COSE_ALGORITHM_ES384 -35
79 
80 /**
81  * \def T_COSE_ALGORITHM_ES512
82  *
83  * \brief Indicates ECDSA with SHA-512.
84  *
85  * This value comes from the
86  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
87  *
88  * The COSE standard recommends a key using the secp521r1 curve with
89  * this algorithm. This curve is also known as P-521.
90  */
91 #define T_COSE_ALGORITHM_ES512 -36
92 
93 /**
94  * \def T_COSE_ALGORITHM_HMAC256
95  *
96  * \brief Indicates HMAC with SHA256
97  *
98  * This value comes from the
99  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
100  *
101  * Value for \ref COSE_HEADER_PARAM_ALG to indicate HMAC w/ SHA-256
102  */
103 #define T_COSE_ALGORITHM_HMAC256 5
104 
105 /**
106  * \def T_COSE_ALGORITHM_HMAC384
107  *
108  * \brief Indicates HMAC with SHA384
109  *
110  * This value comes from the
111  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
112  *
113  * Value for \ref COSE_HEADER_PARAM_ALG to indicate HMAC w/ SHA-384
114  */
115 #define T_COSE_ALGORITHM_HMAC384 6
116 
117 /**
118  * \def T_COSE_ALGORITHM_HMAC512
119  *
120  * \brief Indicates HMAC with SHA512
121  *
122  * This value comes from the
123  * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
124  *
125  * Value for \ref COSE_HEADER_PARAM_ALG to indicate HMAC w/ SHA-512
126  */
127 #define T_COSE_ALGORITHM_HMAC512 7
128 
129 
130 /**
131  * Indicates the cryptographic library the \ref t_cose_key is intended
132  * for. Usually only one cryptographic library is integrated so this
133  * serves as a cross-check.
134  */
135 enum t_cose_crypto_lib_t {
136     /** can be used for integrations
137      * that don't have or don't want to have any cross-check.
138      */
139     T_COSE_CRYPTO_LIB_UNIDENTIFIED = 0,
140     /** \c key_ptr points to a malloced OpenSSL EC_KEY. The caller
141      * needs to free it after the operation is done. */
142     T_COSE_CRYPTO_LIB_OPENSSL = 1,
143      /** \c key_handle is a \c psa_key_handle_t in Arm's Platform Security
144       * Architecture */
145     T_COSE_CRYPTO_LIB_PSA = 2
146 };
147 
148 
149 /**
150  * This structure is used to indicate or pass a key through the t_cose
151  * implementation to the underlying, platform-specific cryptography
152  * libraries for signing and verifying signature. You must know the
153  * cryptographic library that is integrated with t_cose to know how to
154  * fill in this data structure.
155  *
156  * For example, in the OpenSSL integration, \ref key_ptr should point
157  * to an OpenSSL \c EC_KEY type.
158  */
159 struct t_cose_key {
160     /** Identifies the crypto library this key was created for.  The
161      * crypto library knows if it uses the handle or the pointer so
162      * this indirectly selects the union member. */
163     enum t_cose_crypto_lib_t crypto_lib;
164     union {
165         /** For libraries that use a pointer to the key or key
166          * handle. \c NULL indicates empty. */
167         void *key_ptr;
168         /** For libraries that use an integer handle to the key */
169         uint64_t key_handle;
170     } k;
171 };
172 
173 /** An empty or \c NULL \c t_cose_key */
174 #define T_COSE_NULL_KEY \
175     ((struct t_cose_key){T_COSE_CRYPTO_LIB_UNIDENTIFIED, {0}})
176 
177 
178 /* Private value. Intentionally not documented for Doxygen.  This is
179  * the size allocated for the encoded protected header parameters.  It
180  * needs to be big enough for encode_protected_parameters() to
181  * succeed. It currently sized for one parameter with an algorithm ID
182  * up to 32 bits long -- one byte for the wrapping map, one byte for
183  * the label, 5 bytes for the ID. If this is made accidentially too
184  * small, QCBOR will only return an error, and not overrun any
185  * buffers.
186  *
187  * 17 extra bytes are added, rounding it up to 24 total, in case some
188  * other protected header parameter is to be added and so the test
189  * using T_COSE_TEST_CRIT_PARAMETER_EXIST can work.
190  */
191 #define T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS (1+1+5+17)
192 
193 /* Private value. Intentionally not documented for Doxygen.
194  * This is the size allocated for the encoded protected headers.  It
195  * needs to be big enough for make_protected_header() to succeed. It
196  * currently sized for one header with an algorithm ID up to 32 bits
197  * long -- one byte for the wrapping map, one byte for the label, 5
198  * bytes for the ID. If this is made accidentially too small, QCBOR will
199  * only return an error, and not overrun any buffers.
200  *
201  * 9 extra bytes are added, rounding it up to 16 total, in case some
202  * other protected header is to be added.
203  */
204 #define T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS (1 + 1 + 5 + 9)
205 
206 /**
207  * Error codes return by t_cose.
208  */
209 /*
210  * Do not reorder these. It is OK to add new ones at the end.
211  *
212  * Explicit values are included because some tools like debuggers show
213  * only the value, not the symbol, and it is hard to count up through
214  * 35 lines to figure out the actual value.
215  */
216 enum t_cose_err_t {
217     /** Operation completed successfully. */
218     T_COSE_SUCCESS = 0,
219 
220     /** The requested signing algorithm is not supported.  */
221     T_COSE_ERR_UNSUPPORTED_SIGNING_ALG = 1,
222 
223     /** Internal error when encoding protected parameters, usually
224      * because they are too big. It is internal because the caller
225      * can't really affect the size of the protected parameters. */
226     T_COSE_ERR_MAKING_PROTECTED = 2,
227 
228     /** The hash algorithm needed is not supported. Note that the
229      * signing algorithm identifier identifies the hash algorithm. */
230     T_COSE_ERR_UNSUPPORTED_HASH = 3,
231 
232     /** Some system failure when running the hash algorithm. */
233     T_COSE_ERR_HASH_GENERAL_FAIL = 4,
234 
235     /** The buffer to receive a hash result is too small. */
236     T_COSE_ERR_HASH_BUFFER_SIZE = 5,
237 
238     /** The buffer to receive result of a signing operation is too
239      * small. */
240     T_COSE_ERR_SIG_BUFFER_SIZE = 6,
241 
242     /** When verifying a \c COSE_Sign1, the CBOR is "well-formed", but
243      * something is wrong with the format of the CBOR outside of the
244      * header parameters. For example, it is missing something like
245      * the payload or something is of an unexpected type. */
246     T_COSE_ERR_SIGN1_FORMAT = 8,
247 
248     /** When decoding some CBOR like a \c COSE_Sign1, the CBOR was not
249      * "well-formed". Most likely what was supposed to be CBOR is
250      * either not or is corrupted. The CBOR is can't be decoded. */
251     T_COSE_ERR_CBOR_NOT_WELL_FORMED = 9,
252 
253     /** The CBOR is "well-formed", but something is wrong with format
254      * in the header parameters.  For example, a parameter is labeled
255      * with other than an integer or string or the value is an integer
256      * when a byte string is expected. */
257     T_COSE_ERR_PARAMETER_CBOR = 10,
258 
259     /** No algorithm ID was found when one is needed. For example,
260      * when verifying a \c COSE_Sign1. */
261     T_COSE_ERR_NO_ALG_ID = 11,
262 
263     /** No kid (key ID) was found when one is needed. For example,
264      * when verifying a \c COSE_Sign1. */
265     T_COSE_ERR_NO_KID = 12,
266 
267     /** Signature verification failed. For example, the cryptographic
268      * operations completed successfully but hash wasn't as
269      * expected. */
270     T_COSE_ERR_SIG_VERIFY = 13,
271 
272     /** Verification of a short-circuit signature failed. */
273     T_COSE_ERR_BAD_SHORT_CIRCUIT_KID = 14,
274 
275     /** Some (unspecified) argument was not valid. */
276     T_COSE_ERR_INVALID_ARGUMENT = 15,
277 
278     /** Out of heap memory. This originates in crypto library as
279      * t_cose does not use malloc. */
280     T_COSE_ERR_INSUFFICIENT_MEMORY = 16,
281 
282     /** General unspecific failure. */
283     T_COSE_ERR_FAIL = 17,
284 
285     /** Equivalent to \c PSA_ERROR_CORRUPTION_DETECTED. */
286     T_COSE_ERR_TAMPERING_DETECTED = 18,
287 
288     /** The key identified by a \ref t_cose_key or a key ID was not
289      * found. */
290     T_COSE_ERR_UNKNOWN_KEY = 19,
291 
292     /** The key was found, but it was the wrong type for the
293       * operation. */
294     T_COSE_ERR_WRONG_TYPE_OF_KEY = 20,
295 
296     /** Error constructing the COSE \c Sig_structure when signing or
297      *  verify. */
298     T_COSE_ERR_SIG_STRUCT = 21,
299 
300     /** Signature was short-circuit. The option \ref
301      * T_COSE_OPT_ALLOW_SHORT_CIRCUIT to allow verification of
302      * short-circuit signatures was not set.  */
303     T_COSE_ERR_SHORT_CIRCUIT_SIG = 22,
304 
305     /** Something generally went wrong in the crypto adaptor when
306       * signing or verifying. */
307     T_COSE_ERR_SIG_FAIL = 23,
308 
309     /** Something went wrong formatting the CBOR.  Possibly the
310      * payload has maps or arrays that are not closed when using
311      * t_cose_sign1_encode_parameters() and
312      * t_cose_sign1_encode_signature() to sign a \c COSE_Sign1. */
313     T_COSE_ERR_CBOR_FORMATTING = 24,
314 
315      /** The buffer passed in to receive the output is too small. */
316     T_COSE_ERR_TOO_SMALL = 25,
317 
318     /** More parameters (more than \ref T_COSE_PARAMETER_LIST_MAX)
319      * than this implementation can handle. Note that all parameters
320      * need to be checked for criticality so all parameters need to be
321      * examined. */
322     T_COSE_ERR_TOO_MANY_PARAMETERS = 26,
323 
324     /** A parameter was encountered that was unknown and also listed in
325       * the crit labels parameter. */
326     T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER = 27,
327 
328     /** A request was made to signed with a short-circuit sig, \ref
329      * T_COSE_OPT_SHORT_CIRCUIT_SIG, but short circuit signature are
330      * disabled (compiled out) for this implementation.  */
331     T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED = 28,
332 
333     /** The key type in a \ref t_cose_key is wrong for the
334      * cryptographic library used by this integration of t_cose.
335      */
336     T_COSE_ERR_INCORRECT_KEY_FOR_LIB = 29,
337     /** This implementation only handles integer COSE algorithm IDs with
338      * values less than \c INT32_MAX. */
339 
340     T_COSE_ERR_NON_INTEGER_ALG_ID = 30,
341     /** The content type parameter contains a content type that is
342      * neither integer or text string or it is an integer not in the
343      * range of 0 to \c UINT16_MAX. */
344     T_COSE_ERR_BAD_CONTENT_TYPE = 31,
345 
346     /** If the option \ref T_COSE_OPT_TAG_REQUIRED is set for
347      * t_cose_sign1_verify() and the tag is absent, this error is
348      * returned. */
349     T_COSE_ERR_INCORRECTLY_TAGGED = 32,
350 
351     /** The signing or verification key given is empty. */
352     T_COSE_ERR_EMPTY_KEY = 33,
353 
354     /** A header parameter occurs twice, perhaps once in protected and
355      * once in unprotected. Duplicate header parameters are not
356      * allowed in COSE.
357      */
358     T_COSE_ERR_DUPLICATE_PARAMETER = 34,
359 
360     /** A header parameter that should be protected (alg id or crit)
361      * is not. This occurs when verifying a \c COSE_Sign1 that is
362      * improperly constructed. */
363     T_COSE_ERR_PARAMETER_NOT_PROTECTED = 35,
364 
365     /** Something is wrong with the crit parameter. */
366     T_COSE_ERR_CRIT_PARAMETER = 36,
367 
368     /**
369      * When verifying a \c COSE_Mac0, something is wrong with the
370      * format of the CBOR. For example, it is missing something like
371      * the payload.
372      */
373     T_COSE_ERR_MAC0_FORMAT = 37,
374 };
375 
376 
377 
378 
379 /**
380  * The maximum number of header parameters that can be handled during
381  * verification of a \c COSE_Sign1 message. \ref
382  * T_COSE_ERR_TOO_MANY_PARAMETERS will be returned by
383  * t_cose_sign1_verify() if the input message has more.
384  *
385  * There can be both \ref T_COSE_PARAMETER_LIST_MAX integer-labeled
386  * parameters and \ref T_COSE_PARAMETER_LIST_MAX string-labeled
387  * parameters.
388  *
389  * This is a hard maximum so the implementation doesn't need
390  * malloc. This constant can be increased if needed. Doing so will
391  * increase stack usage.
392  */
393 #define T_COSE_PARAMETER_LIST_MAX 10
394 
395 
396 
397 /**
398  * The value of an unsigned integer content type indicating no content
399  * type.  See \ref t_cose_parameters.
400  */
401 #define T_COSE_EMPTY_UINT_CONTENT_TYPE UINT16_MAX+1
402 
403 /**
404  * The result of parsing a set of COSE header parameters. The pointers
405  * are all back into the COSE structure blob passed in.
406  *
407  * Approximate size on a 64-bit machine is 80 bytes and on a 32-bit
408  * machine is 40.
409  */
410 struct t_cose_parameters {
411     /** The algorithm ID. \ref T_COSE_UNSET_ALGORITHM_ID if the algorithm ID
412      * parameter is not present. String type algorithm IDs are not
413      * supported.  See the
414      * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml)
415      * for the algorithms corresponding to the integer values.
416      */
417     int32_t               cose_algorithm_id;
418     /** The COSE key ID. \c NULL_Q_USEFUL_BUF_C if parameter is not
419      * present */
420     struct q_useful_buf_c kid;
421     /** The initialization vector. \c NULL_Q_USEFUL_BUF_C if parameter
422      * is not present */
423     struct q_useful_buf_c iv;
424     /** The partial initialization vector. \c NULL_Q_USEFUL_BUF_C if
425      * parameter is not present */
426     struct q_useful_buf_c partial_iv;
427     /** The content type as a MIME type like
428      * "text/plain". \c NULL_Q_USEFUL_BUF_C if parameter is not present */
429 #ifndef T_COSE_DISABLE_CONTENT_TYPE
430     struct q_useful_buf_c content_type_tstr;
431     /** The content type as a CoAP Content-Format
432      * integer. \ref T_COSE_EMPTY_UINT_CONTENT_TYPE if parameter is not
433      * present. Allowed range is 0 to UINT16_MAX per RFC 7252. */
434     uint32_t              content_type_uint;
435 #endif /* T_COSE_DISABLE_CONTENT_TYPE */
436 };
437 
438 
439 
440 
441 /**
442  * An \c option_flag to not add the CBOR type 6 tag for a COSE message.
443  * Some uses of COSE may require this tag be absent because its COSE
444  * message type is known from surrounding context.
445  *
446  * Or said another way, per the COSE RFC, this code produces a \c
447  * COSE_Sign1_Tagged/ \c COSE_Mac0_Tagged by default and
448  * a \c COSE_Sign1/ \c COSE_Mac0 when this flag is set.
449  * The only difference between these two is the CBOR tag.
450  */
451 #define T_COSE_OPT_OMIT_CBOR_TAG 0x00000002
452 
453 
454 /**
455  * Pass this as \c option_flags to allow verification of short-circuit
456  * signatures. This should only be used as a test mode as
457  * short-circuit signatures are not secure.
458  *
459  * See also \ref T_COSE_OPT_SHORT_CIRCUIT_SIG.
460  */
461 #define T_COSE_OPT_ALLOW_SHORT_CIRCUIT 0x00000001
462 
463 
464 /**
465  * The error \ref T_COSE_ERR_NO_KID is returned if the kid parameter
466  * is missing. Note that the kid parameter is primarily passed on to
467  * the crypto layer so the crypto layer can look up the key. If the
468  * verification key is determined by other than the kid, then it is
469  * fine if there is no kid.
470  */
471 #define T_COSE_OPT_REQUIRE_KID 0x00000002
472 
473 
474 /**
475  * Normally this will decode the CBOR presented as a \c COSE_Sign1
476  * or a \c COSE_Mac0 message whether it is tagged using QCBOR tagging
477  * as such or not.
478  * If this option is set, then \ref T_COSE_ERR_INCORRECTLY_TAGGED is
479  * returned if it is not tagged.
480  */
481 #define T_COSE_OPT_TAG_REQUIRED  0x00000004
482 
483 
484 /**
485  * This option disables cryptographic signature verification.  With
486  * this option the \c verification_key is not needed.  This is useful
487  * to decode the a COSE message to get the kid (key ID).  The
488  * verification key can be looked up or otherwise obtained by the
489  * caller. Once the key in in hand, the verification function can be
490  * called again to perform the full verification.
491  *
492  * The payload will always be returned whether this is option is given
493  * or not, but it should not be considered secure when this option is
494  * given.
495  *
496  */
497 #define T_COSE_OPT_DECODE_ONLY  0x00000008
498 
499 
500 #ifdef __cplusplus
501 }
502 #endif
503 
504 
505 #endif /* __T_COSE_COMMON_H__ */
506