1 /*
2 * t_cose_sign1_sign.h
3 *
4 * Copyright (c) 2018-2019, 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 #ifndef __T_COSE_SIGN1_H__
12 #define __T_COSE_SIGN1_H__
13
14 #include <stdint.h>
15 #include <stdbool.h>
16 #include "qcbor/qcbor.h"
17 #include "t_cose_common.h"
18
19 #ifdef __cplusplus
20 extern "C" {
21 #endif
22
23
24 /**
25 * \file t_cose_sign1_sign.h
26 *
27 * \brief Create a \c COSE_Sign1 message, usually for EAT or CWT Token.
28 *
29 * This creates a \c COSE_Sign1 message in compliance with
30 * [COSE (RFC 8152)](https://tools.ietf.org/html/rfc8152).
31 * A \c COSE_Sign1 message is a CBOR encoded binary blob that contains
32 * header parameters, a payload and a signature. Usually the signature is made
33 * with an EC signing algorithm like ECDSA.
34 *
35 * This implementation is intended to be small and portable to
36 * different OS's and platforms. Its dependencies are:
37 * - [QCBOR](https://github.com/laurencelundblade/QCBOR)
38 * - <stdint.h>, <string.h>, <stddef.h>
39 * - Hash functions like SHA-256
40 * - Signing functions like ECDSA
41 *
42 * There is a cryptographic adaptation layer defined in
43 * t_cose_crypto.h. An implementation can be made of the functions in
44 * it for different cryptographic libraries. This means that different
45 * integrations with different cryptographic libraries may support
46 * only signing with a particular set of algorithms. Integration with
47 * [OpenSSL](https://www.openssl.org) is supported. Key ID look up
48 * also varies by different cryptographic library integrations.
49 *
50 * This implementation has a mode where a CBOR-format payload can be
51 * output directly into the output buffer. This saves having two
52 * copies of the payload in memory. For this mode use
53 * t_cose_sign1_encode_parameters() and
54 * t_cose_sign1_encode_signature(). For a simpler API that just takes
55 * the payload as an input buffer use t_cose_sign1_sign().
56 *
57 * See t_cose_common.h for preprocessor defines to reduce object code
58 * and stack use by disabling features.
59 */
60
61
62 /**
63 * This is the context for creating a \c COSE_Sign1 structure. The
64 * caller should allocate it and pass it to the functions here. This
65 * is about 100 bytes so it fits easily on the stack.
66 */
67 struct t_cose_sign1_sign_ctx {
68 /* Private data structure */
69 uint8_t protected_parameters_buffer[T_COSE_SIGN1_MAX_SIZE_PROTECTED_PARAMETERS];
70 struct q_useful_buf_c protected_parameters; /* The encoded protected parameters */
71 int32_t cose_algorithm_id;
72 struct t_cose_key signing_key;
73 int32_t option_flags;
74 struct q_useful_buf_c kid;
75 #ifndef T_COSE_DISABLE_CONTENT_TYPE
76 uint32_t content_type_uint;
77 const char * content_type_tstr;
78 #endif
79 };
80
81
82 /**
83 * This selects a signing test mode called _short_ _circuit_
84 * _signing_. This mode is useful when there is no signing key
85 * available, perhaps because it has not been provisioned or
86 * configured for the particular device. It may also be because the
87 * public key cryptographic functions have not been connected up in
88 * the cryptographic adaptation layer.
89 *
90 * It has no value for security at all. Data signed this way MUST NOT
91 * be trusted as anyone can sign like this.
92 *
93 * In this mode, the signature is the hash of that which would
94 * normally be signed by the public key algorithm. To make the
95 * signature the correct size for the particular algorithm, instances
96 * of the hash are concatenated to pad it out.
97 *
98 * This mode is very useful for testing because all the code except
99 * the actual signing algorithm is run exactly as it would if a proper
100 * signing algorithm was run. This can be used for end-end system
101 * testing all the way to a server or relying party, not just for
102 * testing device code as t_cose_sign1_verify() supports it too.
103 */
104 #define T_COSE_OPT_SHORT_CIRCUIT_SIG 0x00000001
105
106
107
108
109 /**
110 * \brief Initialize to start creating a \c COSE_Sign1.
111 *
112 * \param[in] context The t_cose signing context.
113 * \param[in] option_flags One of \c T_COSE_OPT_XXXX.
114 * \param[in] cose_algorithm_id The algorithm to sign with, for example
115 * \ref T_COSE_ALGORITHM_ES256.
116 *
117 * Initialize the \ref t_cose_sign1_ctx context. Typically, no
118 * \c option_flags are needed and 0 is passed. A \c cose_algorithm_id
119 * must always be given. See \ref T_COSE_OPT_SHORT_CIRCUIT_SIG and
120 * related for possible option flags.
121 *
122 * The algorithm ID space is from
123 * [COSE (RFC8152)](https://tools.ietf.org/html/rfc8152) and the
124 * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
125 * \ref T_COSE_ALGORITHM_ES256 and a few others are defined here for
126 * convenience. The signing algorithms supported depends on the
127 * cryptographic library that t_cose is integrated with.
128 *
129 * Errors such as the passing of an unsupported \c cose_algorithm_id
130 * are reported when t_cose_sign1_sign() or
131 * t_cose_sign1_encode_parameters() is called.
132 */
133 static void
134 t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx *context,
135 int32_t option_flags,
136 int32_t cose_algorithm_id);
137
138
139 /**
140 * \brief Set the key and kid (key ID) for signing.
141 *
142 * \param[in] context The t_cose signing context.
143 * \param[in] signing_key The signing key to use or \ref T_COSE_NULL_KEY.
144 * \param[in] kid COSE kid (key ID) parameter or \c NULL_Q_USEFUL_BUF_C.
145 *
146 * This needs to be called to set the signing key to use. The \c kid
147 * may be omitted by giving \c NULL_Q_USEFUL_BUF_C.
148 *
149 * If short-circuit signing is used,
150 * \ref T_COSE_OPT_SHORT_CIRCUIT_SIG, then this does not need to be
151 * called. If it is called the \c kid given will be used, but the \c
152 * signing_key is never used. When the \c kid is given with a
153 * short-circuit signature, the internally fixed kid for short circuit
154 * will not be used and this \c COSE_Sign1 message can not be verified
155 * by t_cose_sign1_verify().
156 */
157 static void
158 t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *context,
159 struct t_cose_key signing_key,
160 struct q_useful_buf_c kid);
161
162
163
164 #ifndef T_COSE_DISABLE_CONTENT_TYPE
165 /**
166 * \brief Set the payload content type using CoAP content types.
167 *
168 * \param[in] context The t_cose signing context.
169 * \param[in] content_type The content type of the payload as defined
170 * in the IANA CoAP Content-Formats registry.
171 *
172 * It is not allowed to have both a CoAP and MIME content type. This
173 * error will show up when t_cose_sign1_sign() or
174 * t_cose_sign1_encode_parameters() is called as no error is returned by
175 * this function.
176 *
177 * The IANA CoAP Content-Formats registry is found
178 * [here](https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats).
179 */
180 static inline void
181 t_cose_sign1_set_content_type_uint(struct t_cose_sign1_sign_ctx *context,
182 uint16_t content_type);
183
184 /**
185 * \brief Set the payload content type using MIME content types.
186 *
187 * \param[in] context The t_cose signing context.
188 * \param[in] content_type The content type of the payload as defined
189 * in the IANA Media Types registry.
190
191 *
192 * It is not allowed to have both a CoAP and MIME content type. This
193 * error will show up when t_cose_sign1_sign() or
194 * t_cose_sign1_encode_parameters() is called.
195 *
196 * The IANA Media Types registry can be found
197 * [here](https://www.iana.org/assignments/media-types/media-types.xhtml).
198 * These have been known as MIME types in the past.
199 */
200 static inline void
201 t_cose_sign1_set_content_type_tstr(struct t_cose_sign1_sign_ctx *context,
202 const char *content_type);
203 #endif /* T_COSE_DISABLE_CONTENT_TYPE */
204
205
206
207 /**
208 * \brief Create and sign a \c COSE_Sign1 message with a payload.
209 *
210 * \param[in] context The t_cose signing context.
211 * \param[in] payload Pointer and length of payload to sign.
212 * \param[in] out_buf Pointer and length of buffer to output to.
213 * \param[out] result Pointer and length of the resulting \c COSE_Sign1.
214 *
215 * The \c context must have been initialized with
216 * t_cose_sign1_sign_init() and the key set with
217 * t_cose_sign1_set_signing_key() before this is called.
218 *
219 * This creates the COSE header parameter, hashes and signs the
220 * payload and creates the signature. \c out_buf gives the pointer and
221 * length memory into which the output is written. The pointer and
222 * length of the actual \c COSE_Sign1 is returned in \c result.
223 *
224 * Typically, the required size of \c out_buf is about 30 bytes plus
225 * the size of the signature and the size of the key ID. This is about
226 * 150 bytes for ECDSA 256 with a 32-byte key ID.
227 *
228 * To compute the size of the buffer needed before it is allocated
229 * call this with \c out_buf containing a \c NULL pointer and large
230 * length like \c UINT32_MAX. The algorithm and key, kid and such
231 * must be set up just as if the real \c COSE_Sign1 were to be created
232 * as these values are needed to compute the size correctly. The
233 * contents of \c result will be a \c NULL pointer and the length of
234 * the \c COSE_Sign1. When this is run like this, the cryptographic
235 * functions will not actually run, but the size of their output will
236 * be taken into account to give an exact size.
237 *
238 * This function requires the payload be complete and formatted in a
239 * contiguous buffer. The resulting \c COSE_Sign1 message also
240 * contains the payload preceded by the header parameters and followed
241 * by the signature, all CBOR formatted. This function thus requires
242 * two copies of the payload to be in memory. Alternatively
243 * t_cose_sign1_encode_parameters() and
244 * t_cose_sign1_encode_signature() can be used. They are more complex
245 * to use, but avoid the two copies of the payload.
246 */
247 enum t_cose_err_t
248 t_cose_sign1_sign(struct t_cose_sign1_sign_ctx *context,
249 struct q_useful_buf_c payload,
250 struct q_useful_buf out_buf,
251 struct q_useful_buf_c *result);
252
253
254 /**
255 * \brief Output first part and parameters for a \c COSE_Sign1 message.
256 *
257 * \param[in] context The t_cose signing context.
258 * \param[in] cbor_encode_ctx Encoding context to output to.
259 *
260 * This is the more complex and more memory efficient alternative to
261 * t_cose_sign1_sign(). Like t_cose_sign1_sign(),
262 * t_cose_sign1_sign_init() and t_cose_sign1_set_signing_key() must be
263 * called before calling this.
264 *
265 * When this is called, the opening parts of the \c COSE_Sign1 message
266 * are output to the \c cbor_encode_ctx.
267 *
268 * After this is called, the CBOR-formatted payload must be written to
269 * the \c cbor_encode_ctx by calling all the various
270 * \c QCBOREncode_AddXxx calls. It can be as simple or complex as needed.
271 *
272 * To complete the \c COSE_Sign1 call t_cose_sign1_encode_signature().
273 *
274 * The \c cbor_encode_ctx must have been initialized with an output
275 * buffer to hold the \c COSE_Sign1 header parameters, the payload and the
276 * signature.
277 *
278 * This and t_cose_sign1_encode_signature() can be used to calculate
279 * the size of the \c COSE_Sign1 in the way \c QCBOREncode is usually
280 * used to calculate sizes. In this case the \c t_cose_sign1_ctx must
281 * be initialized with the options, algorithm, key and kid just as
282 * normal as these are needed to calculate the size. Then set up the
283 * QCBOR encoder context with a \c NULL pointer and large length like
284 * \c UINT32_MAX. Call t_cose_sign1_encode_parameters(), then format
285 * the payload into the encoder context, then call
286 * t_cose_sign1_encode_signature(). Finally call \c
287 * QCBOREncode_FinishGetSize() to get the length.
288 */
289 enum t_cose_err_t
290 t_cose_sign1_encode_parameters(struct t_cose_sign1_sign_ctx *context,
291 QCBOREncodeContext *cbor_encode_ctx);
292
293
294 /**
295 * \brief Finish a \c COSE_Sign1 message by outputting the signature.
296 *
297 * \param[in] context The t_cose signing context.
298 * \param[in] cbor_encode_ctx Encoding context to output to.
299 *
300 * \return This returns one of the error codes defined by \ref t_cose_err_t.
301 *
302 * Call this to complete creation of a signed \c COSE_Sign1 started
303 * with t_cose_sign1_encode_parameters().
304 *
305 * This is when the cryptographic signature algorithm is run.
306 *
307 * The completed \c COSE_Sign1 message is retrieved from the
308 * \c cbor_encode_ctx by calling \c QCBOREncode_Finish().
309 */
310 enum t_cose_err_t
311 t_cose_sign1_encode_signature(struct t_cose_sign1_sign_ctx *context,
312 QCBOREncodeContext *cbor_encode_ctx);
313
314
315
316
317
318
319 /* ------------------------------------------------------------------------
320 * Inline implementations of public functions defined above.
321 */
322 static inline void
t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx * me,int32_t option_flags,int32_t cose_algorithm_id)323 t_cose_sign1_sign_init(struct t_cose_sign1_sign_ctx *me,
324 int32_t option_flags,
325 int32_t cose_algorithm_id)
326 {
327 memset(me, 0, sizeof(*me));
328 #ifndef T_COSE_DISABLE_CONTENT_TYPE
329 /* Only member for which 0 is not the empty state */
330 me->content_type_uint = T_COSE_EMPTY_UINT_CONTENT_TYPE;
331 #endif
332
333 me->cose_algorithm_id = cose_algorithm_id;
334 me->option_flags = option_flags;
335 }
336
337
338 static inline void
t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx * me,struct t_cose_key signing_key,struct q_useful_buf_c kid)339 t_cose_sign1_set_signing_key(struct t_cose_sign1_sign_ctx *me,
340 struct t_cose_key signing_key,
341 struct q_useful_buf_c kid)
342 {
343 me->kid = kid;
344 me->signing_key = signing_key;
345 }
346
347
348 #ifndef T_COSE_DISABLE_CONTENT_TYPE
349 static inline void
t_cose_sign1_set_content_type_uint(struct t_cose_sign1_sign_ctx * me,uint16_t content_type)350 t_cose_sign1_set_content_type_uint(struct t_cose_sign1_sign_ctx *me,
351 uint16_t content_type)
352 {
353 me->content_type_uint = content_type;
354 }
355
356
357 static inline void
t_cose_sign1_set_content_type_tstr(struct t_cose_sign1_sign_ctx * me,const char * content_type)358 t_cose_sign1_set_content_type_tstr(struct t_cose_sign1_sign_ctx *me,
359 const char *content_type)
360 {
361 me->content_type_tstr = content_type;
362 }
363 #endif
364
365 #ifdef __cplusplus
366 }
367 #endif
368
369 #endif /* __T_COSE_SIGN1_H__ */
370