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