1 /*
2 Copyright (c) 2021 Fraunhofer AISEC. See the COPYRIGHT
3 file at the top-level directory of this distribution.
4
5 Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 option. This file may not be copied, modified, or distributed
9 except according to those terms.
10 */
11
12 #include "edhoc/buffer_sizes.h"
13 #include "edhoc_internal.h"
14
15 #include "common/memcpy_s.h"
16 #include "common/print_util.h"
17 #include "common/crypto_wrapper.h"
18 #include "common/oscore_edhoc_error.h"
19
20 #include "edhoc/hkdf_info.h"
21 #include "edhoc/messages.h"
22 #include "edhoc/okm.h"
23 #include "edhoc/plaintext.h"
24 #include "edhoc/prk.h"
25 #include "edhoc/retrieve_cred.h"
26 #include "edhoc/signature_or_mac_msg.h"
27 #include "edhoc/suites.h"
28 #include "edhoc/th.h"
29 #include "edhoc/txrx_wrapper.h"
30 #include "edhoc/ciphertext.h"
31 #include "edhoc/suites.h"
32 #include "edhoc/runtime_context.h"
33 #include "edhoc/bstr_encode_decode.h"
34 #include "edhoc/int_encode_decode.h"
35
36 #include "cbor/edhoc_decode_message_1.h"
37 #include "cbor/edhoc_encode_message_2.h"
38 #include "cbor/edhoc_decode_message_3.h"
39
40 #define CBOR_UINT_SINGLE_BYTE_UINT_MAX_VALUE (0x17)
41 #define CBOR_UINT_MULTI_BYTE_UINT_MAX_VALUE (0x17)
42 #define CBOR_BSTR_TYPE_MIN_VALUE (0x40)
43 #define CBOR_BSTR_TYPE_MAX_VALUE (0x57)
44
45 /**
46 * @brief Parses message 1.
47 * @param[in] msg1 Message 1.
48 * @param[out] method EDHOC method.
49 * @param[out] suites_i Cipher suites suported by the initiator
50 * @param[out] g_x Public ephemeral key of the initiator.
51 * @param[out] c_i Connection identifier of the initiator.
52 * @param[out] ead1 External authorized data 1.
53 * @retval Ok or error code.
54 */
55 static inline enum err
msg1_parse(struct byte_array * msg1,enum method_type * method,struct byte_array * suites_i,struct byte_array * g_x,struct byte_array * c_i,struct byte_array * ead1)56 msg1_parse(struct byte_array *msg1, enum method_type *method,
57 struct byte_array *suites_i, struct byte_array *g_x,
58 struct byte_array *c_i, struct byte_array *ead1)
59 {
60 uint32_t i;
61 struct message_1 m;
62 size_t decode_len = 0;
63
64 TRY_EXPECT(cbor_decode_message_1(msg1->ptr, msg1->len, &m, &decode_len),
65 0);
66
67 /*METHOD*/
68 if ((m.message_1_METHOD > INITIATOR_SDHK_RESPONDER_SDHK) ||
69 (m.message_1_METHOD < INITIATOR_SK_RESPONDER_SK)) {
70 return wrong_parameter;
71 }
72 *method = (enum method_type)m.message_1_METHOD;
73 PRINTF("msg1 METHOD: %d\n", (int)*method);
74
75 /*SUITES_I*/
76 if (m.message_1_SUITES_I_choice == message_1_SUITES_I_int_c) {
77 /*the initiator supports only one suite*/
78 suites_i->ptr[0] = (uint8_t)m.message_1_SUITES_I_int;
79 suites_i->len = 1;
80 } else {
81 if (0 == m.SUITES_I_suite_l_suite_count) {
82 return suites_i_list_empty;
83 }
84
85 /*the initiator supports more than one suite*/
86 if (m.SUITES_I_suite_l_suite_count > suites_i->len) {
87 return suites_i_list_to_long;
88 }
89
90 for (i = 0; i < m.SUITES_I_suite_l_suite_count; i++) {
91 suites_i->ptr[i] = (uint8_t)m.SUITES_I_suite_l_suite[i];
92 }
93 suites_i->len = (uint32_t)m.SUITES_I_suite_l_suite_count;
94 }
95 PRINT_ARRAY("msg1 SUITES_I", suites_i->ptr, suites_i->len);
96
97 /*G_X*/
98 TRY(_memcpy_s(g_x->ptr, g_x->len, m.message_1_G_X.value,
99 (uint32_t)m.message_1_G_X.len));
100 g_x->len = (uint32_t)m.message_1_G_X.len;
101 PRINT_ARRAY("msg1 G_X", g_x->ptr, g_x->len);
102
103 /*C_I*/
104 if (m.message_1_C_I_choice == message_1_C_I_int_c) {
105 c_i->ptr[0] = (uint8_t)m.message_1_C_I_int;
106 c_i->len = 1;
107 } else {
108 TRY(_memcpy_s(c_i->ptr, c_i->len, m.message_1_C_I_bstr.value,
109 (uint32_t)m.message_1_C_I_bstr.len));
110 c_i->len = (uint32_t)m.message_1_C_I_bstr.len;
111 }
112 PRINT_ARRAY("msg1 C_I_raw", c_i->ptr, c_i->len);
113
114 /*ead_1*/
115 if (m.message_1_ead_1_present) {
116 TRY(_memcpy_s(ead1->ptr, ead1->len, m.message_1_ead_1.value,
117 (uint32_t)m.message_1_ead_1.len));
118 ead1->len = (uint32_t)m.message_1_ead_1.len;
119 PRINT_ARRAY("msg1 ead_1", ead1->ptr, ead1->len);
120 }
121 return ok;
122 }
123
124 /**
125 * @brief Checks if the selected cipher suite
126 * (the first in the list received from the
127 * initiator) is supported.
128 * @param selected The selected suite.
129 * @param[in] suites_r The list of suported cipher suites.
130 * @retval True if supported.
131 */
selected_suite_is_supported(uint8_t selected,struct byte_array * suites_r)132 static inline bool selected_suite_is_supported(uint8_t selected,
133 struct byte_array *suites_r)
134 {
135 for (uint32_t i = 0; i < suites_r->len; i++) {
136 if (suites_r->ptr[i] == selected)
137 PRINTF("Suite %d will be used in this EDHOC run.\n",
138 selected);
139 return true;
140 }
141 return false;
142 }
143
144 /**
145 * @brief Encodes message 2.
146 * @param[in] g_y Public ephemeral DH key of the responder.
147 * @param[in] c_r Connection identifier of the responder.
148 * @param[in] ciphertext_2 The ciphertext.
149 * @param[out] msg2 The encoded message.
150 * @retval Ok or error code.
151 */
msg2_encode(const struct byte_array * g_y,struct byte_array * c_r,const struct byte_array * ciphertext_2,struct byte_array * msg2)152 static inline enum err msg2_encode(const struct byte_array *g_y,
153 struct byte_array *c_r,
154 const struct byte_array *ciphertext_2,
155 struct byte_array *msg2)
156 {
157 BYTE_ARRAY_NEW(g_y_ciphertext_2, G_Y_CIPHERTEXT_2,
158 g_y->len + ciphertext_2->len);
159
160 memcpy(g_y_ciphertext_2.ptr, g_y->ptr, g_y->len);
161 memcpy(g_y_ciphertext_2.ptr + g_y->len, ciphertext_2->ptr,
162 ciphertext_2->len);
163
164 TRY(encode_bstr(&g_y_ciphertext_2, msg2));
165
166 PRINT_ARRAY("message_2 (CBOR Sequence)", msg2->ptr, msg2->len);
167 return ok;
168 }
169
msg2_gen(struct edhoc_responder_context * c,struct runtime_context * rc,struct byte_array * c_i)170 enum err msg2_gen(struct edhoc_responder_context *c, struct runtime_context *rc,
171 struct byte_array *c_i)
172 {
173 PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
174
175 enum method_type method = INITIATOR_SK_RESPONDER_SK;
176 BYTE_ARRAY_NEW(suites_i, SUITES_I_SIZE, SUITES_I_SIZE);
177 BYTE_ARRAY_NEW(g_x, G_X_SIZE, G_X_SIZE);
178
179 TRY(msg1_parse(&rc->msg, &method, &suites_i, &g_x, c_i, &rc->ead));
180
181 // TODO this may be a vulnerability in case suites_i.len is zero
182 if (!(selected_suite_is_supported(suites_i.ptr[suites_i.len - 1],
183 &c->suites_r))) {
184 // TODO implement here the sending of an error message
185 return error_message_sent;
186 }
187
188 /*get cipher suite*/
189 TRY(get_suite((enum suite_label)suites_i.ptr[suites_i.len - 1],
190 &rc->suite));
191
192 bool static_dh_r;
193 authentication_type_get(method, &rc->static_dh_i, &static_dh_r);
194
195 /******************* create and send message 2*************************/
196 BYTE_ARRAY_NEW(th2, HASH_SIZE, get_hash_len(rc->suite.edhoc_hash));
197 TRY(hash(rc->suite.edhoc_hash, &rc->msg, &rc->msg1_hash));
198 TRY(th2_calculate(rc->suite.edhoc_hash, &rc->msg1_hash, &c->g_y, &th2));
199
200 /*calculate the DH shared secret*/
201 BYTE_ARRAY_NEW(g_xy, ECDH_SECRET_SIZE, ECDH_SECRET_SIZE);
202 TRY(shared_secret_derive(rc->suite.edhoc_ecdh, &c->y, &g_x, g_xy.ptr));
203
204 PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy.ptr, g_xy.len);
205
206 BYTE_ARRAY_NEW(PRK_2e, PRK_SIZE, PRK_SIZE);
207 TRY(hkdf_extract(rc->suite.edhoc_hash, &th2, &g_xy, PRK_2e.ptr));
208 PRINT_ARRAY("PRK_2e", PRK_2e.ptr, PRK_2e.len);
209
210 /*derive prk_3e2m*/
211 TRY(prk_derive(static_dh_r, rc->suite, SALT_3e2m, &th2, &PRK_2e, &g_x,
212 &c->r, rc->prk_3e2m.ptr));
213 PRINT_ARRAY("prk_3e2m", rc->prk_3e2m.ptr, rc->prk_3e2m.len);
214
215 /*compute signature_or_MAC_2*/
216 BYTE_ARRAY_NEW(sign_or_mac_2, SIGNATURE_SIZE,
217 get_signature_len(rc->suite.edhoc_sign));
218
219 TRY(signature_or_mac(GENERATE, static_dh_r, &rc->suite, &c->sk_r,
220 &c->pk_r, &rc->prk_3e2m, &c->c_r, &th2,
221 &c->id_cred_r, &c->cred_r, &c->ead_2, MAC_2,
222 &sign_or_mac_2));
223
224 /*compute ciphertext_2*/
225 BYTE_ARRAY_NEW(plaintext_2, PLAINTEXT2_SIZE,
226 AS_BSTR_SIZE(c->c_r.len) + c->id_cred_r.len +
227 AS_BSTR_SIZE(sign_or_mac_2.len) + c->ead_2.len);
228 BYTE_ARRAY_NEW(ciphertext_2, CIPHERTEXT2_SIZE, plaintext_2.len);
229
230 TRY(ciphertext_gen(CIPHERTEXT2, &rc->suite, &c->c_r, &c->id_cred_r,
231 &sign_or_mac_2, &c->ead_2, &PRK_2e, &th2,
232 &ciphertext_2, &plaintext_2));
233
234 /* Clear the message buffer. */
235 memset(rc->msg.ptr, 0, rc->msg.len);
236 rc->msg.len = sizeof(rc->msg_buf);
237 /*message 2 create*/
238 TRY(msg2_encode(&c->g_y, &c->c_r, &ciphertext_2, &rc->msg));
239
240 TRY(th34_calculate(rc->suite.edhoc_hash, &th2, &plaintext_2, &c->cred_r,
241 &rc->th3));
242
243 return ok;
244 }
245
msg3_process(struct edhoc_responder_context * c,struct runtime_context * rc,struct cred_array * cred_i_array,struct byte_array * prk_out,struct byte_array * initiator_pk)246 enum err msg3_process(struct edhoc_responder_context *c,
247 struct runtime_context *rc,
248 struct cred_array *cred_i_array,
249 struct byte_array *prk_out,
250 struct byte_array *initiator_pk)
251 {
252 BYTE_ARRAY_NEW(ctxt3, CIPHERTEXT3_SIZE, rc->msg.len);
253 TRY(decode_bstr(&rc->msg, &ctxt3));
254 PRINT_ARRAY("CIPHERTEXT_3", ctxt3.ptr, ctxt3.len);
255
256 BYTE_ARRAY_NEW(id_cred_i, ID_CRED_I_SIZE, ID_CRED_I_SIZE);
257 BYTE_ARRAY_NEW(sign_or_mac, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
258
259 PRINTF("PLAINTEXT3_SIZE: %d\n", PLAINTEXT3_SIZE);
260 PRINTF("ctxt3.len: %d\n", ctxt3.len);
261 #if defined(_WIN32)
262 BYTE_ARRAY_NEW(ptxt3,
263 PLAINTEXT3_SIZE + 16, // 16 is max aead mac length
264 ctxt3.len);
265 #else
266 BYTE_ARRAY_NEW(ptxt3,
267 PLAINTEXT3_SIZE + get_aead_mac_len(rc->suite.edhoc_aead),
268 ctxt3.len);
269 #endif
270
271 TRY(ciphertext_decrypt_split(CIPHERTEXT3, &rc->suite, NULL, &id_cred_i,
272 &sign_or_mac, &rc->ead, &rc->prk_3e2m,
273 &rc->th3, &ctxt3, &ptxt3));
274
275 /*check the authenticity of the initiator*/
276 BYTE_ARRAY_NEW(cred_i, CRED_I_SIZE, CRED_I_SIZE);
277 BYTE_ARRAY_NEW(pk, PK_SIZE, PK_SIZE);
278 BYTE_ARRAY_NEW(g_i, G_I_SIZE, G_I_SIZE);
279
280 TRY(retrieve_cred(rc->static_dh_i, cred_i_array, &id_cred_i, &cred_i,
281 &pk, &g_i));
282 PRINT_ARRAY("CRED_I", cred_i.ptr, cred_i.len);
283 PRINT_ARRAY("pk", pk.ptr, pk.len);
284 PRINT_ARRAY("g_i", g_i.ptr, g_i.len);
285
286 /* Export public key. */
287 if ((NULL != initiator_pk) && (NULL != initiator_pk->ptr)) {
288 _memcpy_s(initiator_pk->ptr, initiator_pk->len, pk.ptr, pk.len);
289 initiator_pk->len = pk.len;
290 }
291
292 /*derive prk_4e3m*/
293 TRY(prk_derive(rc->static_dh_i, rc->suite, SALT_4e3m, &rc->th3,
294 &rc->prk_3e2m, &g_i, &c->y, rc->prk_4e3m.ptr));
295 PRINT_ARRAY("prk_4e3m", rc->prk_4e3m.ptr, rc->prk_4e3m.len);
296
297 TRY(signature_or_mac(VERIFY, rc->static_dh_i, &rc->suite, NULL, &pk,
298 &rc->prk_4e3m, &NULL_ARRAY, &rc->th3, &id_cred_i,
299 &cred_i, &rc->ead, MAC_3, &sign_or_mac));
300
301 /*TH4*/
302 // ptxt3.len = ptxt3.len - get_aead_mac_len(rc->suite.edhoc_aead);
303 TRY(th34_calculate(rc->suite.edhoc_hash, &rc->th3, &ptxt3, &cred_i,
304 &rc->th4));
305
306 /*PRK_out*/
307 TRY(edhoc_kdf(rc->suite.edhoc_hash, &rc->prk_4e3m, PRK_out, &rc->th4,
308 prk_out));
309 return ok;
310 }
311
312 #ifdef MESSAGE_4
msg4_gen(struct edhoc_responder_context * c,struct runtime_context * rc)313 enum err msg4_gen(struct edhoc_responder_context *c, struct runtime_context *rc)
314 {
315 /*Ciphertext 4 calculate*/
316 BYTE_ARRAY_NEW(ctxt4, CIPHERTEXT4_SIZE, CIPHERTEXT4_SIZE);
317 #if PLAINTEXT4_SIZE != 0
318 BYTE_ARRAY_NEW(ptxt4, PLAINTEXT4_SIZE, PLAINTEXT4_SIZE);
319 #else
320 struct byte_array ptxt4 = BYTE_ARRAY_INIT(NULL, 0);
321 #endif
322
323 TRY(ciphertext_gen(CIPHERTEXT4, &rc->suite, &NULL_ARRAY, &NULL_ARRAY,
324 &NULL_ARRAY, &c->ead_4, &rc->prk_4e3m, &rc->th4,
325 &ctxt4, &ptxt4));
326
327 TRY(encode_bstr(&ctxt4, &rc->msg));
328
329 PRINT_ARRAY("Message 4 ", rc->msg.ptr, rc->msg.len);
330 return ok;
331 }
332 #endif // MESSAGE_4
333
edhoc_responder_run_extended(struct edhoc_responder_context * c,struct cred_array * cred_i_array,struct byte_array * err_msg,struct byte_array * prk_out,struct byte_array * initiator_pub_key,struct byte_array * c_i_bytes,enum err (* tx)(void * sock,struct byte_array * data),enum err (* rx)(void * sock,struct byte_array * data),enum err (* ead_process)(void * params,struct byte_array * ead13))334 enum err edhoc_responder_run_extended(
335 struct edhoc_responder_context *c, struct cred_array *cred_i_array,
336 struct byte_array *err_msg, struct byte_array *prk_out,
337 struct byte_array *initiator_pub_key, struct byte_array *c_i_bytes,
338 enum err (*tx)(void *sock, struct byte_array *data),
339 enum err (*rx)(void *sock, struct byte_array *data),
340 enum err (*ead_process)(void *params, struct byte_array *ead13))
341 {
342 struct runtime_context rc = { 0 };
343 runtime_context_init(&rc);
344
345 /*receive message 1*/
346 PRINT_MSG("waiting to receive message 1...\n");
347 TRY(rx(c->sock, &rc.msg));
348
349 /*create and send message 2*/
350 TRY(msg2_gen(c, &rc, c_i_bytes));
351 TRY(ead_process(c->params_ead_process, &rc.ead));
352 TRY(tx(c->sock, &rc.msg));
353
354 /*receive message 3*/
355 PRINT_MSG("waiting to receive message 3...\n");
356 rc.msg.len = sizeof(rc.msg_buf);
357 TRY(rx(c->sock, &rc.msg));
358 TRY(msg3_process(c, &rc, cred_i_array, prk_out, initiator_pub_key));
359 TRY(ead_process(c->params_ead_process, &rc.ead));
360
361 /*create and send message 4*/
362 #ifdef MESSAGE_4
363 TRY(msg4_gen(c, &rc));
364 TRY(tx(c->sock, &rc.msg));
365 #endif // MESSAGE_4
366 return ok;
367 }
368
edhoc_responder_run(struct edhoc_responder_context * c,struct cred_array * cred_i_array,struct byte_array * err_msg,struct byte_array * prk_out,enum err (* tx)(void * sock,struct byte_array * data),enum err (* rx)(void * sock,struct byte_array * data),enum err (* ead_process)(void * params,struct byte_array * ead13))369 enum err edhoc_responder_run(
370 struct edhoc_responder_context *c, struct cred_array *cred_i_array,
371 struct byte_array *err_msg, struct byte_array *prk_out,
372 enum err (*tx)(void *sock, struct byte_array *data),
373 enum err (*rx)(void *sock, struct byte_array *data),
374 enum err (*ead_process)(void *params, struct byte_array *ead13))
375 {
376 BYTE_ARRAY_NEW(c_i, C_I_SIZE, C_I_SIZE);
377 return edhoc_responder_run_extended(c, cred_i_array, err_msg, prk_out,
378 &NULL_ARRAY, &c_i, tx, rx,
379 ead_process);
380 }
381