1 /*
2 * Copyright (c) 2018-2019, Laurence Lundblade. All rights reserved.
3 * Copyright (c) 2020-2023, Arm Limited. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 */
7
8 #ifndef __T_COSE_MAC0_SIGN_H_
9 #define __T_COSE_MAC0_SIGN_H_
10
11 #include <stdint.h>
12 #include "qcbor/qcbor.h"
13 #include "t_cose_common.h"
14
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18
19
20 /**
21 * This selects a test mode called _short_ _circuit_ _tagging_.
22 * This mode is useful when the symmetric key is unavailable
23 * or unable to be accessed, perhaps because it has not been provisioned or
24 * configured for the particular device.
25 *
26 * It has no value for security at all. Data signed this way MUST NOT
27 * be trusted as anyone can sign like this.
28 *
29 * In this mode, the tag is the hash of that which would normally be MACed by
30 * a symmetric key.
31 *
32 * This mode is very useful for testing because all the code except
33 * the actual MAC algorithm is run exactly as it would if a proper
34 * MAC algorithm was run. This can be used for end-end system
35 * testing all the way to a server or relying party, not just for
36 * testing device code as t_cose_mac0_verify() supports it too.
37 */
38 #define T_COSE_OPT_SHORT_CIRCUIT_TAG 0x00000004
39
40
41 /**
42 * This is the context for creating a \c COSE_Mac0 structure. The caller
43 * should allocate it and pass it to the functions here. This is
44 * about 32 bytes so it fits easily on the stack.
45 */
46 struct t_cose_mac0_sign_ctx {
47 /* Private data structure */
48 uint8_t protected_parameters_buffer[
49 T_COSE_MAC0_MAX_SIZE_PROTECTED_PARAMETERS];
50 struct q_useful_buf_c protected_parameters; /* The encoded protected parameters */
51 int32_t cose_algorithm_id;
52 struct t_cose_key signing_key;
53 int32_t option_flags;
54 struct q_useful_buf_c kid;
55 #ifndef T_COSE_DISABLE_CONTENT_TYPE
56 uint32_t content_type_uint;
57 const char *content_type_tstr;
58 #endif
59 };
60
61
62 /**
63 * \brief Initialize to start creating a \c COSE_Mac0.
64 *
65 * \param[in] context The t_cose signing context.
66 * \param[in] option_flags One of \c T_COSE_OPT_XXXX.
67 * \param[in] cose_algorithm_id The algorithm to generate the authentication
68 * tag, for example
69 * \ref T_COSE_ALGORITHM_HMAC256.
70 *
71 * Initialize the \ref t_cose_mac0_sign_ctx context. Typically, no
72 * \c option_flags are needed and 0 is passed. A \c cose_algorithm_id
73 * must always be given. See \ref T_COSE_OPT_SHORT_CIRCUIT_TAG and
74 * related for possible option flags.
75 *
76 * The algorithm ID space is from
77 * [COSE (RFC8152)](https://tools.ietf.org/html/rfc8152) and the
78 * [IANA COSE Registry](https://www.iana.org/assignments/cose/cose.xhtml).
79 * \ref T_COSE_ALGORITHM_HMAC256 is defined here for convenience.
80 * So far, only HMAC is supported in \c COSE_Mac0.
81 *
82 * Errors such as the passing of an unsupported \c cose_algorithm_id
83 * are reported when t_cose_mac0_encode_parameters() is called.
84 */
85 static void
86 t_cose_mac0_sign_init(struct t_cose_mac0_sign_ctx *me,
87 int32_t option_flags,
88 int32_t cose_algorithm_id);
89
90 /**
91 * \brief Set the key and kid (key ID) for signing.
92 *
93 * \param[in] context The t_cose signing context.
94 * \param[in] signing_key The signing key to use or \ref T_COSE_NULL_KEY.
95 * \param[in] kid COSE key ID parameter or \c NULL_Q_USEFUL_BUF_C.
96 *
97 * This needs to be called to set the signing key to use. The \c kid
98 * may be omitted by giving \c NULL_Q_USEFUL_BUF_C.
99 *
100 * If short-circuit signing is used,
101 * \ref T_COSE_OPT_SHORT_CIRCUIT_TAG, then this does not need to be
102 * called.
103 */
104 static void
105 t_cose_mac0_set_signing_key(struct t_cose_mac0_sign_ctx *context,
106 struct t_cose_key signing_key,
107 struct q_useful_buf_c kid);
108
109 /**
110 * \brief Output first part and parameters for a \c COSE_Mac0 message.
111 *
112 * \param[in] context The t_cose signing context.
113 * \param[in] cbor_encode_ctx Encoding context to output to.
114 *
115 * t_cose_mac0_sign_init() and t_cose_mac0_set_signing_key() must be
116 * called before calling this.
117 *
118 * When this is called, the opening parts of the \c COSE_Mac0 message
119 * are output to the \c cbor_encode_ctx.
120 *
121 * After this is called, the CBOR-formatted payload must be written to
122 * the \c cbor_encode_ctx by calling all the various
123 * \c QCBOREncode_AddXxx calls. It can be as simple or complex as needed.
124 *
125 * To complete the \c COSE_Mac0 call t_cose_mac0_encode_tag().
126 *
127 * The \c cbor_encode_ctx must have been initialized with an output
128 * buffer to hold the \c COSE_Mac0 header parameters, the payload and the
129 * signature.
130 *
131 * This and t_cose_mac0_encode_tag() can be used to calculate
132 * the size of the \c COSE_Mac0 in the way \c QCBOREncode is usually
133 * used to calculate sizes. In this case the \c t_cose_mac0_sign_ctx must
134 * be initialized with the options, algorithm, key and kid just as
135 * normal as these are needed to calculate the size. Then set up the
136 * QCBOR encoder context with a \c NULL pointer and large length like
137 * \c UINT32_MAX. Call t_cose_mac0_encode_parameters(), then format
138 * the payload into the encoder context, then call
139 * t_cose_mac0_encode_tag(). Finally call \c
140 * QCBOREncode_FinishGetSize() to get the length.
141 */
142 enum t_cose_err_t
143 t_cose_mac0_encode_parameters(struct t_cose_mac0_sign_ctx *context,
144 QCBOREncodeContext *cbor_encode_ctx);
145
146 /**
147 * \brief Finish a \c COSE_Mac0 message by outputting the authentication tag.
148 *
149 * \param[in] context The t_cose signing context.
150 * \param[in] cbor_encode_ctx Encoding context to output to.
151 *
152 * \return This returns one of the error codes defined by \ref t_cose_err_t.
153 *
154 * Call this to complete creation of a tagged \c COSE_Mac0 started
155 * with t_cose_mac0_encode_parameters().
156 *
157 * This is when the cryptographic MAC algorithm is run.
158 *
159 * The completed \c COSE_Mac0 message is retrieved from the
160 * \c cbor_encode_ctx by calling \c QCBOREncode_Finish().
161 */
162 enum t_cose_err_t
163 t_cose_mac0_encode_tag(struct t_cose_mac0_sign_ctx *context,
164 QCBOREncodeContext *cbor_encode_ctx);
165
166
167 #ifndef T_COSE_DISABLE_CONTENT_TYPE
168 /**
169 * \brief Set the payload content type using CoAP content types.
170 *
171 * \param[in] context The t_cose signing context.
172 * \param[in] content_type The content type of the payload as defined
173 * in the IANA CoAP Content-Formats registry.
174 *
175 * It is not allowed to have both a CoAP and MIME content type. This
176 * error will show up when t_cose_mac0_encode_parameters() is called
177 * as no error is returned by this function.
178 *
179 * The IANA CoAP Content-Formats registry is found
180 * [here](https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#content-formats).
181 */
182 static inline void
183 t_cose_mac0_set_content_type_uint(struct t_cose_mac0_sign_ctx *context,
184 uint16_t content_type);
185
186 /**
187 * \brief Set the payload content type using MIME content types.
188 *
189 * \param[in] context The t_cose signing context.
190 * \param[in] content_type The content type of the payload as defined
191 * in the IANA Media Types registry.
192
193 *
194 * It is not allowed to have both a CoAP and MIME content type. This
195 * error will show up when t_cose_mac0_encode_parameters() is called.
196 *
197 * The IANA Media Types registry can be found
198 * [here](https://www.iana.org/assignments/media-types/media-types.xhtml).
199 * These have been known as MIME types in the past.
200 */
201 static inline void
202 t_cose_mac0_set_content_type_tstr(struct t_cose_mac0_sign_ctx *context,
203 const char *content_type);
204 #endif /* T_COSE_DISABLE_CONTENT_TYPE */
205
206 /* ------------------------------------------------------------------------
207 * Inline implementations of public functions defined above.
208 */
209 static inline void
t_cose_mac0_sign_init(struct t_cose_mac0_sign_ctx * me,int32_t option_flags,int32_t cose_algorithm_id)210 t_cose_mac0_sign_init(struct t_cose_mac0_sign_ctx *me,
211 int32_t option_flags,
212 int32_t cose_algorithm_id)
213 {
214 memset(me, 0, sizeof(*me));
215
216 #ifndef T_COSE_DISABLE_CONTENT_TYPE
217 /* Only member for which 0 is not the empty state */
218 me->content_type_uint = T_COSE_EMPTY_UINT_CONTENT_TYPE;
219 #endif
220
221 me->cose_algorithm_id = cose_algorithm_id;
222 me->option_flags = option_flags;
223 }
224
225 static inline void
t_cose_mac0_set_signing_key(struct t_cose_mac0_sign_ctx * me,struct t_cose_key signing_key,struct q_useful_buf_c kid)226 t_cose_mac0_set_signing_key(struct t_cose_mac0_sign_ctx *me,
227 struct t_cose_key signing_key,
228 struct q_useful_buf_c kid)
229 {
230 me->kid = kid;
231 me->signing_key = signing_key;
232 }
233
234
235 #ifndef T_COSE_DISABLE_CONTENT_TYPE
236 static inline void
t_cose_mac0_set_content_type_uint(struct t_cose_mac0_sign_ctx * me,uint16_t content_type)237 t_cose_mac0_set_content_type_uint(struct t_cose_mac0_sign_ctx *me,
238 uint16_t content_type)
239 {
240 me->content_type_uint = content_type;
241 }
242
243 static inline void
t_cose_mac0_set_content_type_tstr(struct t_cose_mac0_sign_ctx * me,const char * content_type)244 t_cose_mac0_set_content_type_tstr(struct t_cose_mac0_sign_ctx *me,
245 const char *content_type)
246 {
247 me->content_type_tstr = content_type;
248 }
249 #endif /* T_COSE_DISABLE_CONTENT_TYPE */
250
251 #ifdef __cplusplus
252 }
253 #endif
254
255 #endif /* __T_COSE_MAC0_SIGN_H_ */
256