blob: 4228c2babda7cc72f27407634ebfd26ba3fbc7f9 [file] [log] [blame]
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -08001/*
2 * t_cose_util.c
3 *
4 * Copyright 2019, Laurence Lundblade
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 * See BSD-3-Clause license in README.mdE.
9 */
10
11#include "t_cose_util.h"
12#include "qcbor.h"
13#include "t_cose_defines.h"
14#include "t_cose_common.h"
15#include "t_cose_crypto.h"
16
17
18/**
19 * \file t_cose_util.c
20 *
21 * \brief Implementation of t_cose utility functions.
22 *
23 */
24
25
26/*
27 * Public function. See t_cose_util.h
28 */
29int32_t hash_alg_id_from_sig_alg_id(int32_t cose_sig_alg_id)
30{
31 /* if other hashes, particularly those that output bigger hashes
32 * are added here, various other parts of this code have to be
33 * changed to have larger buffers.
34 */
35 switch(cose_sig_alg_id) {
36
37 case COSE_ALGORITHM_ES256:
38 return COSE_ALG_SHA256_PROPRIETARY;
39
40 default:
41 return INT32_MAX;
42 }
43}
44
45
46/*
47 * Format of to-be-signed bytes used by create_tbs_hash().
48 * This is defined in COSE (RFC 8152). It is the input
49 * to the hash.
50 *
51 * Sig_structure = [
52 * context : "Signature" / "Signature1" / "CounterSignature",
53 * body_protected : empty_or_serialized_map,
54 * ? sign_protected : empty_or_serialized_map,
55 * external_aad : bstr,
56 * payload : bstr
57 * ]
58 */
59
60
61/**
62 * This is the size of the first part of the CBOR encoded TBS
63 * bytes. It is around 20 bytes. See create_tbs_hash().
64 */
65#define T_COSE_SIZE_OF_TBS \
66 1 + /* For opening the array */ \
67 sizeof(COSE_SIG_CONTEXT_STRING_SIGNATURE1) + /* "Signature1" */ \
68 2 + /* Overhead for encoding string */ \
69 T_COSE_SIGN1_MAX_PROT_HEADER + /* entire protected headers */ \
70 3 * ( /* 3 NULL bstrs for fields not used */ \
71 1 /* size of a NULL bstr */ \
72 )
73
74
75/*
76 * Public function. See t_cose_util.h
77 */
78enum t_cose_err_t create_tbs_hash(int32_t cose_alg_id,
Laurence Lundbladee1610ad2019-02-20 13:53:20 -080079 struct q_useful_buf buffer_for_hash,
80 struct q_useful_buf_c *hash,
81 struct q_useful_buf_c protected_headers,
82 struct q_useful_buf_c payload)
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -080083{
84 /* approximate stack use on 32-bit machine:
85 * local use: 320
86 * with calls: 360
87 */
88 enum t_cose_err_t return_value;
89 QCBOREncodeContext cbor_encode_ctx;
90 UsefulBuf_MAKE_STACK_UB( buffer_for_TBS_first_part, T_COSE_SIZE_OF_TBS);
Laurence Lundbladee1610ad2019-02-20 13:53:20 -080091 struct q_useful_buf_c tbs_first_part;
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -080092 QCBORError qcbor_result;
93 struct t_cose_crypto_hash hash_ctx;
94 int32_t hash_alg_id;
95
96 /* This builds the CBOR-format to-be-signed bytes */
97 QCBOREncode_Init(&cbor_encode_ctx, buffer_for_TBS_first_part);
98 QCBOREncode_OpenArray(&cbor_encode_ctx);
99 /* context */
100 QCBOREncode_AddSZString(&cbor_encode_ctx,
101 COSE_SIG_CONTEXT_STRING_SIGNATURE1);
102 /* body_protected */
103 QCBOREncode_AddBytes(&cbor_encode_ctx,
104 protected_headers);
105 /* sign_protected */
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800106 QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_Q_USEFUL_BUF_C);
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800107 /* external_aad */
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800108 QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_Q_USEFUL_BUF_C);
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800109 /* fake payload */
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800110 QCBOREncode_AddBytes(&cbor_encode_ctx, NULL_Q_USEFUL_BUF_C);
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800111 QCBOREncode_CloseArray(&cbor_encode_ctx);
112
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800113 /* get the result and convert it to struct q_useful_buf_c representation */
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800114 qcbor_result = QCBOREncode_Finish(&cbor_encode_ctx, &tbs_first_part);
115 if(qcbor_result) {
116 /* Mainly means that the protected_headers were too big
117 (which should never happen) */
118 return_value = T_COSE_ERR_SIG_STRUCT;
119 goto Done;
120 }
121
122 /* Start the hashing */
123 hash_alg_id = hash_alg_id_from_sig_alg_id(cose_alg_id);
124 /* Don't check hash_alg_id for failure. t_cose_crypto_hash_start()
125 will handle it properly
126 */
127 return_value = t_cose_crypto_hash_start(&hash_ctx, hash_alg_id);
128 if(return_value) {
129 goto Done;
130 }
131
132 /* Hash the first part of the TBS. Take all but the last two
133 * bytes. The last two bytes are the fake payload from above. It
134 * is replaced by the real payload which is hashed next. The fake
135 * payload is needed so the array count is right. This is one of
136 * the main things that make it possible to implement with one
137 * buffer for the whole cose sign1.
138 */
139 t_cose_crypto_hash_update(&hash_ctx,
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800140 q_useful_buf_head(tbs_first_part,
141 tbs_first_part.len - 2));
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800142
143 /* Hash the payload */
144 t_cose_crypto_hash_update(&hash_ctx, payload);
145
146 /* Finish the hash and set up to return it */
147 return_value = t_cose_crypto_hash_finish(&hash_ctx,
148 buffer_for_hash,
149 hash);
150
151Done:
152 return return_value;
153}
154
155
156/*
157 * Public function. See t_cose_util.h
158 */
159enum t_cose_err_t
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800160get_short_circuit_kid(struct q_useful_buf buffer_for_kid,
161 struct q_useful_buf_c *kid)
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800162{
163 /* This is a random hard coded key ID that is used to indicate
164 * short-circuit signing. It is OK to hard code this as the
165 * probability of collision with this ID is very low and the same
166 * as for collision between any two key IDs of any sort.
167 */
168 uint8_t defined_short_circuit_kid[] = {
169 0xef, 0x95, 0x4b, 0x4b, 0xd9, 0xbd, 0xf6, 0x70,
170 0xd0, 0x33, 0x60, 0x82, 0xf5, 0xef, 0x15, 0x2a,
171 0xf8, 0xf3, 0x5b, 0x6a, 0x6c, 0x00, 0xef, 0xa6,
172 0xa9, 0xa7, 0x1f, 0x49, 0x51, 0x7e, 0x18, 0xc6};
173
174 /* Prevent a dumb error where the size constant in the header is
175 * wrong.This check will be evaluated at compile time and optimize
176 * out when all is correct.
177 */
178 if(sizeof(defined_short_circuit_kid) != T_COSE_SHORT_CIRCUIT_KID_SIZE) {
179 return T_COSE_ERR_BAD_SHORT_CIRCUIT_KID;
180 }
181
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800182 *kid = q_useful_buf_copy(buffer_for_kid,
183 Q_USEFUL_BUF_FROM_BYTE_ARRAY_LITERAL(
184 defined_short_circuit_kid));
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800185
Laurence Lundbladee1610ad2019-02-20 13:53:20 -0800186 return q_useful_buf_c_is_null(*kid) ?
Laurence Lundbladeaffd65a2018-12-18 10:50:48 -0800187 T_COSE_ERR_KEY_BUFFER_SIZE :
188 T_COSE_SUCCESS;
189}