1 /*
2  * t_cose_make_test_messages.c
3  *
4  * Copyright (c) 2019-2020, Laurence Lundblade. All rights reserved.
5  *
6  * SPDX-License-Identifier: BSD-3-Clause
7  *
8  * See BSD-3-Clause license in README.md
9  */
10 
11 #include "t_cose_make_test_messages.h"
12 #include "qcbor/qcbor.h"
13 #include "t_cose_crypto.h"
14 #include "t_cose_util.h"
15 
16 
17 /**
18  * \file t_cose_make_test_messages.c
19  *
20  * This makes \c COSE_Sign1 messages of various sorts for testing
21  * verification. Some of them are badly formed to test various
22  * verification failures.
23  *
24  * This is essentially a hacked-up version of t_cose_sign1_sign.c.
25  */
26 
27 
28 #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
29 /**
30  * \brief Create a short-circuit signature
31  *
32  * \param[in] cose_algorithm_id Algorithm ID. This is used only to make
33  *                              the short-circuit signature the same size
34  *                              as the real signature would be for the
35  *                              particular algorithm.
36  * \param[in] hash_to_sign      The bytes to sign. Typically, a hash of
37  *                              a payload.
38  * \param[in] signature_buffer  Pointer and length of buffer into which
39  *                              the resulting signature is put.
40  * \param[in] signature         Pointer and length of the signature
41  *                              returned.
42  *
43  * \return This returns one of the error codes defined by \ref t_cose_err_t.
44  *
45  * This creates the short-circuit signature that is a concatenation of
46  * hashes up to the expected size of the signature. This is a test
47  * mode only has it has no security value. This is retained in
48  * commercial production code as a useful test or demo that can run
49  * even if key material is not set up or accessible.
50  */
51 static inline enum t_cose_err_t
short_circuit_sign(int32_t cose_algorithm_id,struct q_useful_buf_c hash_to_sign,struct q_useful_buf signature_buffer,struct q_useful_buf_c * signature)52 short_circuit_sign(int32_t               cose_algorithm_id,
53                    struct q_useful_buf_c hash_to_sign,
54                    struct q_useful_buf   signature_buffer,
55                    struct q_useful_buf_c *signature)
56 {
57     /* approximate stack use on 32-bit machine: local use: 16 bytes
58      */
59     enum t_cose_err_t return_value;
60     size_t            array_index;
61     size_t            amount_to_copy;
62     size_t            sig_size;
63 
64     sig_size = cose_algorithm_id == COSE_ALGORITHM_ES256 ? T_COSE_EC_P256_SIG_SIZE :
65                cose_algorithm_id == COSE_ALGORITHM_ES384 ? T_COSE_EC_P384_SIG_SIZE :
66                cose_algorithm_id == COSE_ALGORITHM_ES512 ? T_COSE_EC_P512_SIG_SIZE :
67                                                            0;
68 
69     /* Check the signature length against buffer size*/
70     if(sig_size == 0) {
71         return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
72         goto Done;
73     }
74 
75     if(sig_size > signature_buffer.len) {
76         /* Buffer too small for this signature type */
77         return_value = T_COSE_ERR_SIG_BUFFER_SIZE;
78         goto Done;
79     }
80 
81     /* Loop concatening copies of the hash to fill out to signature size */
82     for(array_index = 0; array_index < sig_size; array_index += hash_to_sign.len) {
83         amount_to_copy = sig_size - array_index;
84         if(amount_to_copy > hash_to_sign.len) {
85             amount_to_copy = hash_to_sign.len;
86         }
87         memcpy((uint8_t *)signature_buffer.ptr + array_index,
88                hash_to_sign.ptr,
89                amount_to_copy);
90     }
91     signature->ptr = signature_buffer.ptr;
92     signature->len = sig_size;
93     return_value   = T_COSE_SUCCESS;
94 
95 Done:
96     return return_value;
97 }
98 #endif /* T_COSE_DISABLE_SHORT_CIRCUIT_SIGN */
99 
100 
101 /**
102  * \brief  Makes various protected parameters for various tests
103  *
104  * \param[in] test_message_options  Flags to select test modes.
105  * \param[in] cose_algorithm_id  The COSE algorithm ID to put in the parameters.
106  * \param[in] buffer_for_protected_parameters  Pointer and length into which
107  *                               the resulting encoded protected
108  *                               parameters is put.
109  *
110  * \return The pointer and length of the protected parameters is
111  * returned, or \c NULL_Q_USEFUL_BUF_C if this fails.
112  *
113  * The protected parameters are returned in fully encoded CBOR format as
114  * they are added to the \c COSE_Sign1 as a binary string. This is
115  * different from the unprotected parameters which are not handled this
116  * way.
117  *
118  * This returns \c NULL_Q_USEFUL_BUF_C if buffer_for_protected_parameters was
119  * too small. See also definition of
120  * \c T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS.
121  */
122 static inline struct q_useful_buf_c
encode_protected_parameters(uint32_t test_message_options,int32_t cose_algorithm_id,struct q_useful_buf buffer_for_protected_parameters)123 encode_protected_parameters(uint32_t             test_message_options,
124                             int32_t             cose_algorithm_id,
125                             struct q_useful_buf buffer_for_protected_parameters)
126 {
127     /* approximate stack use on 32-bit machine:
128      * local use: 170
129      * with calls: 210
130      */
131     struct q_useful_buf_c protected_parameters;
132     QCBORError            qcbor_result;
133     QCBOREncodeContext    cbor_encode_ctx;
134     struct q_useful_buf_c return_value;
135 
136     if(test_message_options & T_COSE_TEST_EMPTY_PROTECTED_PARAMETERS) {
137         /* An empty q_useful_buf_c */
138         return (struct q_useful_buf_c){buffer_for_protected_parameters.ptr, 0};
139     }
140 
141 
142     if(test_message_options & T_COSE_TEST_UNCLOSED_PROTECTED) {
143         *(uint8_t *)(buffer_for_protected_parameters.ptr) = 0xa1;
144         return (struct q_useful_buf_c){buffer_for_protected_parameters.ptr, 1};
145     }
146 
147     QCBOREncode_Init(&cbor_encode_ctx, buffer_for_protected_parameters);
148 
149     if(test_message_options & T_COSE_TEST_BAD_PROTECTED) {
150         QCBOREncode_OpenArray(&cbor_encode_ctx);
151         QCBOREncode_AddInt64(&cbor_encode_ctx, 42);
152         QCBOREncode_CloseArray(&cbor_encode_ctx);
153         goto Finish;
154     }
155 
156     QCBOREncode_OpenMap(&cbor_encode_ctx);
157     QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx,
158                                COSE_HEADER_PARAM_ALG,
159                                cose_algorithm_id);
160 
161     if(test_message_options & T_COSE_TEST_UNKNOWN_CRIT_UINT_PARAMETER) {
162         /* This is the parameter that will be unknown */
163         QCBOREncode_AddInt64ToMapN(&cbor_encode_ctx, 42, 43);
164         /* This is the critical labels parameter */
165         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
166         QCBOREncode_AddInt64(&cbor_encode_ctx, 42);
167         QCBOREncode_AddInt64(&cbor_encode_ctx, 43);
168         QCBOREncode_AddInt64(&cbor_encode_ctx, 44);
169         QCBOREncode_CloseArray(&cbor_encode_ctx);
170     }
171 
172     if(test_message_options & T_COSE_TEST_UNKNOWN_CRIT_TSTR_PARAMETER) {
173         /* This is the parameter that will be unknown */
174         QCBOREncode_AddInt64ToMap(&cbor_encode_ctx, "hh", 43);
175         /* This is the critical labels parameter */
176         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
177         QCBOREncode_AddSZString(&cbor_encode_ctx, "hh");
178         QCBOREncode_AddSZString(&cbor_encode_ctx, "h");
179         QCBOREncode_AddSZString(&cbor_encode_ctx, "hhh");
180         QCBOREncode_CloseArray(&cbor_encode_ctx);
181     }
182 
183     if(test_message_options & T_COSE_TEST_BAD_CRIT_LABEL) {
184         /* This is the critical labels parameter */
185         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
186         QCBOREncode_AddBool(&cbor_encode_ctx, true);
187         QCBOREncode_CloseArray(&cbor_encode_ctx);
188     }
189 
190     if(test_message_options & T_COSE_TEST_CRIT_PARAMETER_EXIST) {
191         /* This is the critical labels parameter */
192         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
193         int i;
194         /* Add the maxium */
195         for(i = 0; i < T_COSE_PARAMETER_LIST_MAX; i++) {
196             QCBOREncode_AddInt64(&cbor_encode_ctx, i + 10);
197         }
198         QCBOREncode_CloseArray(&cbor_encode_ctx);
199     }
200 
201     if(test_message_options & T_COSE_TEST_TOO_MANY_CRIT_PARAMETER_EXIST) {
202         /* This is the critical labels parameter */
203         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
204         int i;
205         /* One more than the maximum */
206         for(i = 0; i < T_COSE_PARAMETER_LIST_MAX+1; i++) {
207             QCBOREncode_AddInt64(&cbor_encode_ctx, i + 10);
208         }
209         QCBOREncode_CloseArray(&cbor_encode_ctx);
210     }
211 
212     if(test_message_options & T_COSE_TEST_TOO_MANY_TSTR_CRIT_LABLELS) {
213         /* This is the critical labels parameter */
214         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
215         int i;
216         /* One more than the maximum */
217         for(i = 0; i < T_COSE_PARAMETER_LIST_MAX+1; i++) {
218             QCBOREncode_AddSZString(&cbor_encode_ctx, "");
219         }
220         QCBOREncode_CloseArray(&cbor_encode_ctx);
221     }
222 
223     if(test_message_options & T_COSE_TEST_EMPTY_CRIT_PARAMETER) {
224         QCBOREncode_OpenArrayInMapN(&cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
225         QCBOREncode_CloseArray(&cbor_encode_ctx);
226     }
227 
228     if(test_message_options & T_COSE_TEST_KID_IN_PROTECTED) {
229         QCBOREncode_AddBytesToMapN(&cbor_encode_ctx,
230                                    COSE_HEADER_PARAM_KID,
231                                    Q_USEFUL_BUF_FROM_SZ_LITERAL("kid"));
232     }
233 
234     if(test_message_options & T_COSE_TEST_DUP_CONTENT_ID) {
235         QCBOREncode_AddUInt64ToMapN(&cbor_encode_ctx,
236                                     COSE_HEADER_PARAM_CONTENT_TYPE,
237                                     3);
238     }
239 
240 
241     QCBOREncode_CloseMap(&cbor_encode_ctx);
242 
243 Finish:
244     qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &protected_parameters);
245 
246     if(qcbor_result == QCBOR_SUCCESS) {
247         return_value = protected_parameters;
248     } else {
249         return_value = NULL_Q_USEFUL_BUF_C;
250     }
251 
252     return return_value;
253 }
254 
255 
256 /**
257  * \brief Add the unprotected parameters to a CBOR encoding context
258  *
259  * \param[in] test_message_options  Flags to select test modes.
260  * \param[in] cbor_encode_ctx       CBOR encoding context to output to.
261  * \param[in] kid                   The key ID to go into the kid parameter.
262  *
263  * No error is returned. If an error occurred it will be returned when
264  * \c QCBOR_Finish() is called on \c cbor_encode_ctx.
265  *
266  * The unprotected parameters added by this are the key ID plus
267  * lots of different test parameters.
268  */
269 static inline void
add_unprotected_parameters(uint32_t test_message_options,QCBOREncodeContext * cbor_encode_ctx,struct q_useful_buf_c kid)270 add_unprotected_parameters(uint32_t              test_message_options,
271                            QCBOREncodeContext   *cbor_encode_ctx,
272                            struct q_useful_buf_c kid)
273 {
274     if(test_message_options & T_COSE_TEST_UNPROTECTED_NOT_MAP) {
275         QCBOREncode_OpenArray(cbor_encode_ctx);
276         QCBOREncode_AddBytes(cbor_encode_ctx, kid);
277         QCBOREncode_CloseArray(cbor_encode_ctx);
278         return; /* skip the rest for this degenerate test */
279     }
280 
281     QCBOREncode_OpenMap(cbor_encode_ctx);
282 
283     if(test_message_options & T_COSE_TEST_NOT_WELL_FORMED_1) {
284         QCBOREncode_AddEncoded(cbor_encode_ctx, Q_USEFUL_BUF_FROM_SZ_LITERAL("xxxxxx"));
285     }
286 
287     /* Put in a byte string (not a text string) for the parameter label */
288     if(test_message_options & T_COSE_TEST_PARAMETER_LABEL) {
289         QCBOREncode_AddBytes(cbor_encode_ctx, kid);
290         QCBOREncode_AddBytes(cbor_encode_ctx, kid);
291     }
292 
293     if(test_message_options & T_COSE_TEST_BAD_CRIT_PARAMETER) {
294         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx,
295                                       COSE_HEADER_PARAM_CRIT, "hi");
296     }
297 
298     if(test_message_options & T_COSE_TEST_EXTRA_PARAMETER) {
299         QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
300         QCBOREncode_OpenMap(cbor_encode_ctx);
301         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
302         QCBOREncode_CloseMap(cbor_encode_ctx);
303         QCBOREncode_CloseArray(cbor_encode_ctx);
304     }
305 
306 
307     if(test_message_options & T_COSE_TEST_NOT_WELL_FORMED_2) {
308         QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
309         QCBOREncode_OpenMap(cbor_encode_ctx);
310         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
311         /* '=' is 0x3d a reserved initial byte and thus not-well-formed */
312         QCBOREncode_AddEncoded(cbor_encode_ctx,
313                                Q_USEFUL_BUF_FROM_SZ_LITERAL("="));
314         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 67, "bye");
315 
316         QCBOREncode_CloseMap(cbor_encode_ctx);
317         QCBOREncode_CloseArray(cbor_encode_ctx);
318     }
319 
320     if(test_message_options & T_COSE_TEST_CRIT_NOT_PROTECTED) {
321         /* This is the critical labels parameter */
322         QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, COSE_HEADER_PARAM_CRIT);
323         int i;
324         /* Add the maxium */
325         for(i = 0; i < T_COSE_PARAMETER_LIST_MAX; i++) {
326             QCBOREncode_AddInt64(cbor_encode_ctx, i + 100);
327             QCBOREncode_AddSZString(cbor_encode_ctx, "xxxx");
328         }
329         QCBOREncode_CloseArray(cbor_encode_ctx);
330     }
331 
332     if(test_message_options & T_COSE_TEST_TOO_MANY_UNKNOWN) {
333         int i;
334         for(i = 0; i < T_COSE_PARAMETER_LIST_MAX + 1; i++ ) {
335             QCBOREncode_AddBoolToMapN(cbor_encode_ctx, i+10, true);
336         }
337     }
338 
339     if(!q_useful_buf_c_is_null_or_empty(kid)) {
340         QCBOREncode_AddBytesToMapN(cbor_encode_ctx, COSE_HEADER_PARAM_KID, kid);
341     }
342 
343     if(test_message_options & T_COSE_TEST_ALL_PARAMETERS) {
344         QCBOREncode_AddBytesToMapN(cbor_encode_ctx,
345                                    COSE_HEADER_PARAM_IV,
346                                    Q_USEFUL_BUF_FROM_SZ_LITERAL("iv"));
347         QCBOREncode_AddBytesToMapN(cbor_encode_ctx,
348                                    COSE_HEADER_PARAM_PARTIAL_IV,
349                                    Q_USEFUL_BUF_FROM_SZ_LITERAL("partial_iv"));
350         QCBOREncode_AddInt64ToMapN(cbor_encode_ctx,
351                                    COSE_HEADER_PARAM_CONTENT_TYPE,
352                                    1);
353         /* A slighly complex unknown header parameter */
354         QCBOREncode_OpenArrayInMapN(cbor_encode_ctx, 55);
355         QCBOREncode_OpenMap(cbor_encode_ctx);
356         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 66, "hi");
357         QCBOREncode_AddSZStringToMapN(cbor_encode_ctx, 67, "bye");
358         QCBOREncode_CloseMap(cbor_encode_ctx);
359         QCBOREncode_OpenArray(cbor_encode_ctx);
360         QCBOREncode_OpenMap(cbor_encode_ctx);
361         QCBOREncode_CloseMap(cbor_encode_ctx);
362         QCBOREncode_CloseArray(cbor_encode_ctx);
363         QCBOREncode_CloseArray(cbor_encode_ctx);
364     }
365 
366     if(test_message_options & T_COSE_TEST_TOO_LARGE_CONTENT_TYPE) {
367         QCBOREncode_AddInt64ToMapN(cbor_encode_ctx,
368                                    COSE_HEADER_PARAM_CONTENT_TYPE,
369                                    UINT16_MAX+1);
370     }
371 
372     if(test_message_options & T_COSE_TEST_DUP_CONTENT_ID) {
373         QCBOREncode_AddUInt64ToMapN(cbor_encode_ctx,
374                                     COSE_HEADER_PARAM_CONTENT_TYPE,
375                                     3);
376     }
377 
378     QCBOREncode_CloseMap(cbor_encode_ctx);
379 }
380 
381 
382 /**
383  * Replica of t_cose_sign1_encode_parameters() with modifications to
384  * output various good and bad messages for testing verification.
385  */
386 static enum t_cose_err_t
t_cose_sign1_test_message_encode_parameters(struct t_cose_sign1_sign_ctx * me,uint32_t test_mess_options,QCBOREncodeContext * cbor_encode_ctx)387 t_cose_sign1_test_message_encode_parameters(struct t_cose_sign1_sign_ctx *me,
388                                             uint32_t                       test_mess_options,
389                                             QCBOREncodeContext           *cbor_encode_ctx)
390 {
391     enum t_cose_err_t      return_value;
392     struct q_useful_buf    buffer_for_protected_parameters;
393     struct q_useful_buf_c  kid;
394     int32_t                hash_alg_id;
395 
396     /* Check the cose_algorithm_id now by getting the hash alg as an early
397      * error check even though it is not used until later.
398      */
399     hash_alg_id = hash_alg_id_from_sig_alg_id(me->cose_algorithm_id);
400     if(hash_alg_id == T_COSE_INVALID_ALGORITHM_ID) {
401         return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
402     }
403 
404     /* Add the CBOR tag indicating COSE_Sign1 */
405     if(!(me->option_flags & T_COSE_OPT_OMIT_CBOR_TAG)) {
406         QCBOREncode_AddTag(cbor_encode_ctx, CBOR_TAG_COSE_SIGN1);
407     }
408 
409     /* Get started with the tagged array that holds the four parts of
410      * a cose single signed message */
411     QCBOREncode_OpenArray(cbor_encode_ctx);
412 
413     /* The protected parameters, which are added as a wrapped bstr  */
414     buffer_for_protected_parameters = Q_USEFUL_BUF_FROM_BYTE_ARRAY(me->protected_parameters_buffer);
415     me->protected_parameters = encode_protected_parameters(test_mess_options,
416                                                            me->cose_algorithm_id,
417                                                            buffer_for_protected_parameters);
418     if(q_useful_buf_c_is_null(me->protected_parameters)) {
419         /* The sizing of storage for protected parameters is
420          off (should never happen in tested, released code) */
421         return_value = T_COSE_ERR_MAKING_PROTECTED;
422         goto Done;
423     }
424     if( ! (test_mess_options & T_COSE_TEST_NO_PROTECTED_PARAMETERS)) {
425         /* The use of _AddBytes here achieves the bstr wrapping */
426         QCBOREncode_AddBytes(cbor_encode_ctx, me->protected_parameters);
427     }
428 
429     /* The Unprotected parameters */
430     /* Get the key id because it goes into the parameters that are about
431      to be made. */
432     if(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG) {
433 #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
434         kid = get_short_circuit_kid();
435 #else
436         return_value = T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED;
437         goto Done;
438 #endif
439     } else {
440         kid = me->kid;
441     }
442 
443     if( ! (test_mess_options & T_COSE_TEST_NO_UNPROTECTED_PARAMETERS)) {
444         add_unprotected_parameters(test_mess_options, cbor_encode_ctx, kid);
445     }
446 
447     QCBOREncode_BstrWrap(cbor_encode_ctx);
448 
449     /* Any failures in CBOR encoding will be caught in finish when the
450      * CBOR encoding is closed off. No need to track here as the CBOR
451      * encoder tracks it internally. */
452 
453     return_value = T_COSE_SUCCESS;
454 
455 Done:
456     return return_value;
457 }
458 
459 
460 /**
461  * Replica of t_cose_sign1_output_signature() with modifications to
462  * output various good and bad messages for testing verification.
463  */
464 static enum t_cose_err_t
t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx * me,QCBOREncodeContext * cbor_encode_ctx)465 t_cose_sign1_test_message_output_signature(struct t_cose_sign1_sign_ctx *me,
466                                            QCBOREncodeContext *cbor_encode_ctx)
467 {
468     /* approximate stack use on 32-bit machine:
469      *   32 bytes local use
470      *   220 to 434 for calls dependin on hash implementation
471      *   32 to 64 bytes depending on hash alg (SHA256, 384 or 512)
472      *   64 to 260 depending on EC alg
473      *   348 to 778 depending on hash and EC alg
474      *   Also add stack use by EC and hash functions
475      */
476     enum t_cose_err_t            return_value;
477     QCBORError                   cbor_err;
478     /* pointer and length of the completed tbs hash */
479     struct q_useful_buf_c        tbs_hash;
480     /* Pointer and length of the completed signature */
481     struct q_useful_buf_c        signature;
482     /* Buffer for the actual signature */
483     Q_USEFUL_BUF_MAKE_STACK_UB(  buffer_for_signature, T_COSE_MAX_SIG_SIZE);
484     /* Buffer for the tbs hash. */
485     Q_USEFUL_BUF_MAKE_STACK_UB(  buffer_for_tbs_hash, T_COSE_CRYPTO_MAX_HASH_SIZE);
486     struct q_useful_buf_c        signed_payload;
487 
488     QCBOREncode_CloseBstrWrap(cbor_encode_ctx, &signed_payload);
489 
490     /* Check there are no CBOR encoding errors before proceeding with
491      * hashing and signing. This is not actually necessary as the
492      * errors will be caught correctly later, but it does make it a
493      * bit easier for the caller to debug problems.
494      */
495     cbor_err = QCBOREncode_GetErrorState(cbor_encode_ctx);
496     if(cbor_err == QCBOR_ERR_BUFFER_TOO_SMALL) {
497         return_value = T_COSE_ERR_TOO_SMALL;
498         goto Done;
499     } else if(cbor_err != QCBOR_SUCCESS) {
500         return_value = T_COSE_ERR_CBOR_FORMATTING;
501         goto Done;
502     }
503 
504     /* Create the hash of the to-be-signed bytes. Inputs to the hash
505      * are the protected parameters, the payload that is getting signed, the
506      * cose signature alg from which the hash alg is determined. The
507      * cose_algorithm_id was checked in t_cose_sign1_init() so it
508      * doesn't need to be checked here.
509      */
510     return_value = create_tbs_hash(me->cose_algorithm_id,
511                                    me->protected_parameters,
512                                    T_COSE_TBS_PAYLOAD_IS_BSTR_WRAPPED,
513                                    signed_payload,
514                                    buffer_for_tbs_hash,
515                                    &tbs_hash);
516     if(return_value != T_COSE_SUCCESS) {
517         goto Done;
518     }
519 
520     /* Compute the signature using public key crypto. The key selector
521      * and algorithm ID are passed in to know how and what to sign
522      * with. The hash of the TBS bytes are what is signed. A buffer in
523      * which to place the signature is passed in and the signature is
524      * returned.
525      *
526      * Short-circuit signing is invoked if requested. It does no
527      * public key operation and requires no key. It is just a test
528      * mode that always works.
529      */
530     if(!(me->option_flags & T_COSE_OPT_SHORT_CIRCUIT_SIG)) {
531         /* Normal, non-short-circuit signing */
532         return_value = t_cose_crypto_pub_key_sign(me->cose_algorithm_id,
533                                                   me->signing_key,
534                                                   tbs_hash,
535                                                   buffer_for_signature,
536                                                   &signature);
537     } else {
538 #ifndef T_COSE_DISABLE_SHORT_CIRCUIT_SIGN
539         return_value = short_circuit_sign(me->cose_algorithm_id,
540                                           tbs_hash,
541                                           buffer_for_signature,
542                                           &signature);
543 #endif
544     }
545 
546     if(return_value) {
547         goto Done;
548     }
549 
550     /* Add signature to CBOR and close out the array */
551     QCBOREncode_AddBytes(cbor_encode_ctx, signature);
552     QCBOREncode_CloseArray(cbor_encode_ctx);
553 
554     /* The layer above this must check for and handle CBOR encoding
555      * errors CBOR encoding errors.  Some are detected at the start of
556      * this function, but they cannot all be deteced there.
557      */
558 Done:
559     return return_value;
560 }
561 
562 
563 /*
564  * Public function. See t_cose_make_test_messages.h
565  */
566 enum t_cose_err_t
t_cose_test_message_sign1_sign(struct t_cose_sign1_sign_ctx * me,uint32_t test_message_options,struct q_useful_buf_c payload,struct q_useful_buf out_buf,struct q_useful_buf_c * result)567 t_cose_test_message_sign1_sign(struct t_cose_sign1_sign_ctx *me,
568                                uint32_t                      test_message_options,
569                                struct q_useful_buf_c         payload,
570                                struct q_useful_buf           out_buf,
571                                struct q_useful_buf_c        *result)
572 {
573     QCBOREncodeContext  encode_context;
574     enum t_cose_err_t   return_value;
575 
576     /* -- Initialize CBOR encoder context with output buffer */
577     QCBOREncode_Init(&encode_context, out_buf);
578 
579     /* -- Output the header parameters into the encoder context -- */
580     return_value = t_cose_sign1_test_message_encode_parameters(me, test_message_options, &encode_context);
581     if(return_value != T_COSE_SUCCESS) {
582         goto Done;
583     }
584 
585     /* -- Output the payload into the encoder context -- */
586     /* Payload may or may not actually be CBOR format here. This
587      * function does the job just fine because it just adds bytes to
588      * the encoded output without anything extra.
589      */
590     QCBOREncode_AddEncoded(&encode_context, payload);
591 
592     /* -- Sign and put signature in the encoder context -- */
593     return_value = t_cose_sign1_test_message_output_signature(me,
594                                                               &encode_context);
595     if(return_value) {
596         goto Done;
597     }
598 
599     /* -- Close off and get the resulting encoded CBOR -- */
600     if(QCBOREncode_Finish(&encode_context, result)) {
601         return_value = T_COSE_ERR_CBOR_NOT_WELL_FORMED;
602         goto Done;
603     }
604 
605 Done:
606     return return_value;
607 }
608