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 size_t payload_len_out;
158 struct m2 m;
159
160 BYTE_ARRAY_NEW(g_y_ciphertext_2, G_Y_SIZE + CIPHERTEXT2_SIZE,
161 g_y->len + ciphertext_2->len);
162
163 memcpy(g_y_ciphertext_2.ptr, g_y->ptr, g_y->len);
164 memcpy(g_y_ciphertext_2.ptr + g_y->len, ciphertext_2->ptr,
165 ciphertext_2->len);
166
167 /*Encode g_y_ciphertext_2*/
168 m.m2_G_Y_CIPHERTEXT_2.value = g_y_ciphertext_2.ptr;
169 m.m2_G_Y_CIPHERTEXT_2.len = g_y_ciphertext_2.len;
170
171 /*Encode C_R*/
172 PRINT_ARRAY("C_R", c_r->ptr, c_r->len);
173 if (c_r->len == 1 && (c_r->ptr[0] < 0x18 ||
174 (0x1F < c_r->ptr[0] && c_r->ptr[0] <= 0x37))) {
175 m.m2_C_R_choice = m2_C_R_int_c;
176 TRY(decode_int(c_r, &m.m2_C_R_int));
177 } else {
178 m.m2_C_R_choice = m2_C_R_bstr_c;
179 m.m2_C_R_bstr.value = c_r->ptr;
180 m.m2_C_R_bstr.len = c_r->len;
181 }
182
183 TRY_EXPECT(cbor_encode_m2(msg2->ptr, msg2->len, &m, &payload_len_out),
184 0);
185 msg2->len = (uint32_t)payload_len_out;
186
187 PRINT_ARRAY("message_2 (CBOR Sequence)", msg2->ptr, msg2->len);
188 return ok;
189 }
190
msg2_gen(struct edhoc_responder_context * c,struct runtime_context * rc,struct byte_array * c_i)191 enum err msg2_gen(struct edhoc_responder_context *c, struct runtime_context *rc,
192 struct byte_array *c_i)
193 {
194 PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
195
196 enum method_type method = INITIATOR_SK_RESPONDER_SK;
197 BYTE_ARRAY_NEW(suites_i, SUITES_I_SIZE, SUITES_I_SIZE);
198 BYTE_ARRAY_NEW(g_x, G_X_SIZE, G_X_SIZE);
199
200 TRY(msg1_parse(&rc->msg, &method, &suites_i, &g_x, c_i, &rc->ead));
201
202 // TODO this may be a vulnerability in case suites_i.len is zero
203 if (!(selected_suite_is_supported(suites_i.ptr[suites_i.len - 1],
204 &c->suites_r))) {
205 // TODO implement here the sending of an error message
206 return error_message_sent;
207 }
208
209 /*get cipher suite*/
210 TRY(get_suite((enum suite_label)suites_i.ptr[suites_i.len - 1],
211 &rc->suite));
212
213 bool static_dh_r;
214 authentication_type_get(method, &rc->static_dh_i, &static_dh_r);
215
216 /******************* create and send message 2*************************/
217 BYTE_ARRAY_NEW(th2, HASH_SIZE, get_hash_len(rc->suite.edhoc_hash));
218 TRY(hash(rc->suite.edhoc_hash, &rc->msg, &rc->msg1_hash));
219 TRY(th2_calculate(rc->suite.edhoc_hash, &rc->msg1_hash, &c->g_y,
220 &c->c_r, &th2));
221
222 /*calculate the DH shared secret*/
223 BYTE_ARRAY_NEW(g_xy, ECDH_SECRET_SIZE, ECDH_SECRET_SIZE);
224 TRY(shared_secret_derive(rc->suite.edhoc_ecdh, &c->y, &g_x, g_xy.ptr));
225
226 PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy.ptr, g_xy.len);
227
228 BYTE_ARRAY_NEW(PRK_2e, PRK_SIZE, PRK_SIZE);
229 TRY(hkdf_extract(rc->suite.edhoc_hash, &th2, &g_xy, PRK_2e.ptr));
230 PRINT_ARRAY("PRK_2e", PRK_2e.ptr, PRK_2e.len);
231
232 /*derive prk_3e2m*/
233 TRY(prk_derive(static_dh_r, rc->suite, SALT_3e2m, &th2, &PRK_2e, &g_x,
234 &c->r, rc->prk_3e2m.ptr));
235 PRINT_ARRAY("prk_3e2m", rc->prk_3e2m.ptr, rc->prk_3e2m.len);
236
237 /*compute signature_or_MAC_2*/
238 BYTE_ARRAY_NEW(sign_or_mac_2, SIGNATURE_SIZE,
239 get_signature_len(rc->suite.edhoc_sign));
240
241 TRY(signature_or_mac(GENERATE, static_dh_r, &rc->suite, &c->sk_r,
242 &c->pk_r, &rc->prk_3e2m, &th2, &c->id_cred_r,
243 &c->cred_r, &c->ead_2, MAC_2, &sign_or_mac_2));
244
245 /*compute ciphertext_2*/
246 BYTE_ARRAY_NEW(plaintext_2, PLAINTEXT2_SIZE,
247 c->id_cred_r.len + sign_or_mac_2.len +
248 SIG_OR_MAC_SIZE_ENCODING_OVERHEAD +
249 c->ead_2.len);
250 BYTE_ARRAY_NEW(ciphertext_2, CIPHERTEXT2_SIZE, plaintext_2.len);
251
252 TRY(ciphertext_gen(CIPHERTEXT2, &rc->suite, &c->id_cred_r,
253 &sign_or_mac_2, &c->ead_2, &PRK_2e, &th2,
254 &ciphertext_2, &plaintext_2));
255
256 /* Clear the message buffer. */
257 memset(rc->msg.ptr, 0, rc->msg.len);
258 rc->msg.len = sizeof(rc->msg_buf);
259 /*message 2 create*/
260 TRY(msg2_encode(&c->g_y, &c->c_r, &ciphertext_2, &rc->msg));
261
262 TRY(th34_calculate(rc->suite.edhoc_hash, &th2, &plaintext_2, &c->cred_r,
263 &rc->th3));
264
265 return ok;
266 }
267
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)268 enum err msg3_process(struct edhoc_responder_context *c,
269 struct runtime_context *rc,
270 struct cred_array *cred_i_array,
271 struct byte_array *prk_out,
272 struct byte_array *initiator_pk)
273 {
274 BYTE_ARRAY_NEW(ctxt3, CIPHERTEXT3_SIZE, rc->msg.len);
275 TRY(decode_bstr(&rc->msg, &ctxt3));
276 PRINT_ARRAY("CIPHERTEXT_3", ctxt3.ptr, ctxt3.len);
277
278 BYTE_ARRAY_NEW(id_cred_i, ID_CRED_I_SIZE, ID_CRED_I_SIZE);
279 BYTE_ARRAY_NEW(sign_or_mac, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
280
281 PRINTF("PLAINTEXT3_SIZE: %d\n", PLAINTEXT3_SIZE);
282 PRINTF("ctxt3.len: %d\n", ctxt3.len);
283 #if defined(_WIN32)
284 BYTE_ARRAY_NEW(ptxt3,
285 PLAINTEXT3_SIZE + 16, // 16 is max aead mac length
286 ctxt3.len);
287 #else
288 BYTE_ARRAY_NEW(ptxt3,
289 PLAINTEXT3_SIZE + get_aead_mac_len(rc->suite.edhoc_aead),
290 ctxt3.len);
291 #endif
292
293 TRY(ciphertext_decrypt_split(CIPHERTEXT3, &rc->suite, &id_cred_i,
294 &sign_or_mac, &rc->ead, &rc->prk_3e2m,
295 &rc->th3, &ctxt3, &ptxt3));
296
297 /*check the authenticity of the initiator*/
298 BYTE_ARRAY_NEW(cred_i, CRED_I_SIZE, CRED_I_SIZE);
299 BYTE_ARRAY_NEW(pk, PK_SIZE, PK_SIZE);
300 BYTE_ARRAY_NEW(g_i, G_I_SIZE, G_I_SIZE);
301
302 TRY(retrieve_cred(rc->static_dh_i, cred_i_array, &id_cred_i, &cred_i,
303 &pk, &g_i));
304 PRINT_ARRAY("CRED_I", cred_i.ptr, cred_i.len);
305 PRINT_ARRAY("pk", pk.ptr, pk.len);
306 PRINT_ARRAY("g_i", g_i.ptr, g_i.len);
307
308 /* Export public key. */
309 if ((NULL != initiator_pk) && (NULL != initiator_pk->ptr)) {
310 _memcpy_s(initiator_pk->ptr, initiator_pk->len, pk.ptr, pk.len);
311 initiator_pk->len = pk.len;
312 }
313
314 /*derive prk_4e3m*/
315 TRY(prk_derive(rc->static_dh_i, rc->suite, SALT_4e3m, &rc->th3,
316 &rc->prk_3e2m, &g_i, &c->y, rc->prk_4e3m.ptr));
317 PRINT_ARRAY("prk_4e3m", rc->prk_4e3m.ptr, rc->prk_4e3m.len);
318
319 TRY(signature_or_mac(VERIFY, rc->static_dh_i, &rc->suite, NULL, &pk,
320 &rc->prk_4e3m, &rc->th3, &id_cred_i, &cred_i,
321 &rc->ead, MAC_3, &sign_or_mac));
322
323 /*TH4*/
324 // ptxt3.len = ptxt3.len - get_aead_mac_len(rc->suite.edhoc_aead);
325 TRY(th34_calculate(rc->suite.edhoc_hash, &rc->th3, &ptxt3, &cred_i,
326 &rc->th4));
327
328 /*PRK_out*/
329 TRY(edhoc_kdf(rc->suite.edhoc_hash, &rc->prk_4e3m, PRK_out, &rc->th4,
330 prk_out));
331 return ok;
332 }
333
334 #ifdef MESSAGE_4
msg4_gen(struct edhoc_responder_context * c,struct runtime_context * rc)335 enum err msg4_gen(struct edhoc_responder_context *c, struct runtime_context *rc)
336 {
337 /*Ciphertext 4 calculate*/
338 BYTE_ARRAY_NEW(ctxt4, CIPHERTEXT4_SIZE, CIPHERTEXT4_SIZE);
339 #if PLAINTEXT4_SIZE != 0
340 BYTE_ARRAY_NEW(ptxt4, PLAINTEXT4_SIZE, PLAINTEXT4_SIZE);
341 #else
342 struct byte_array ptxt4 = BYTE_ARRAY_INIT(NULL, 0);
343 #endif
344
345 TRY(ciphertext_gen(CIPHERTEXT4, &rc->suite, &NULL_ARRAY, &NULL_ARRAY,
346 &c->ead_4, &rc->prk_4e3m, &rc->th4, &ctxt4, &ptxt4));
347
348 TRY(encode_bstr(&ctxt4, &rc->msg));
349
350 PRINT_ARRAY("Message 4 ", rc->msg.ptr, rc->msg.len);
351 return ok;
352 }
353 #endif // MESSAGE_4
354
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))355 enum err edhoc_responder_run_extended(
356 struct edhoc_responder_context *c, struct cred_array *cred_i_array,
357 struct byte_array *err_msg, struct byte_array *prk_out,
358 struct byte_array *initiator_pub_key, struct byte_array *c_i_bytes,
359 enum err (*tx)(void *sock, struct byte_array *data),
360 enum err (*rx)(void *sock, struct byte_array *data),
361 enum err (*ead_process)(void *params, struct byte_array *ead13))
362 {
363 struct runtime_context rc = { 0 };
364 runtime_context_init(&rc);
365
366 /*receive message 1*/
367 PRINT_MSG("waiting to receive message 1...\n");
368 TRY(rx(c->sock, &rc.msg));
369
370 /*create and send message 2*/
371 TRY(msg2_gen(c, &rc, c_i_bytes));
372 TRY(ead_process(c->params_ead_process, &rc.ead));
373 TRY(tx(c->sock, &rc.msg));
374
375 /*receive message 3*/
376 PRINT_MSG("waiting to receive message 3...\n");
377 rc.msg.len = sizeof(rc.msg_buf);
378 TRY(rx(c->sock, &rc.msg));
379 TRY(msg3_process(c, &rc, cred_i_array, prk_out, initiator_pub_key));
380 TRY(ead_process(c->params_ead_process, &rc.ead));
381
382 /*create and send message 4*/
383 #ifdef MESSAGE_4
384 TRY(msg4_gen(c, &rc));
385 TRY(tx(c->sock, &rc.msg));
386 #endif // MESSAGE_4
387 return ok;
388 }
389
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))390 enum err edhoc_responder_run(
391 struct edhoc_responder_context *c, struct cred_array *cred_i_array,
392 struct byte_array *err_msg, struct byte_array *prk_out,
393 enum err (*tx)(void *sock, struct byte_array *data),
394 enum err (*rx)(void *sock, struct byte_array *data),
395 enum err (*ead_process)(void *params, struct byte_array *ead13))
396 {
397 BYTE_ARRAY_NEW(c_i, C_I_SIZE, C_I_SIZE);
398 return edhoc_responder_run_extended(c, cred_i_array, err_msg, prk_out,
399 &NULL_ARRAY, &c_i, tx, rx,
400 ead_process);
401 }
402