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