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