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.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 
34 #include "cbor/edhoc_decode_message_1.h"
35 #include "cbor/edhoc_encode_message_2.h"
36 #include "cbor/edhoc_decode_bstr_type.h"
37 #include "cbor/edhoc_decode_message_3.h"
38 
39 /**
40  * @brief   Parses message 1
41  * @param   msg1 buffer containing message 1
42  * @param   msg1_len length of msg1
43  * @param   method method
44  * @param   suites_i
45  * @param   suites_i_len length of suites_i
46  * @param   g_x Public ephemeral key of the initiator
47  * @param   g_x_len length of g_x
48  * @param   c_i connection identifier of the initiator
49  * @param   c_i_len length of c_i
50  * @param   ad1 axillary data 1
51  * @param   ad1_len length of ad1
52  * @retval an err code
53  */
msg1_parse(uint8_t * msg1,uint32_t msg1_len,enum method_type * method,uint8_t * suites_i,uint32_t * suites_i_len,uint8_t * g_x,uint32_t * g_x_len,struct c_x * c_i,uint8_t * ad1,uint32_t * ad1_len)54 static inline enum err msg1_parse(uint8_t *msg1, uint32_t msg1_len,
55 				  enum method_type *method, uint8_t *suites_i,
56 				  uint32_t *suites_i_len, uint8_t *g_x,
57 				  uint32_t *g_x_len, struct c_x *c_i,
58 				  uint8_t *ad1, uint32_t *ad1_len)
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, msg1_len, &m, &decode_len),
65 		   true);
66 
67 	/*METHOD*/
68 	*method = (enum method_type)m._message_1_METHOD;
69 	PRINTF("msg1 METHOD: %d\n", (int)*method);
70 
71 	/*SUITES_I*/
72 	if (m._message_1_SUITES_I_choice == _message_1_SUITES_I_int) {
73 		/*the initiator supports only one suite*/
74 		suites_i[0] = (uint8_t)m._message_1_SUITES_I_int;
75 		*suites_i_len = 1;
76 	} else {
77 		/*the initiator supports more than one suite*/
78 		if (m._SUITES_I__suite_suite_count > *suites_i_len) {
79 			return suites_i_list_to_long;
80 		}
81 
82 		for (i = 0; i < m._SUITES_I__suite_suite_count; i++) {
83 			suites_i[i] = (uint8_t)m._SUITES_I__suite_suite[i];
84 		}
85 		*suites_i_len = (uint32_t)m._SUITES_I__suite_suite_count;
86 	}
87 	PRINT_ARRAY("msg1 SUITES_I", suites_i, *suites_i_len);
88 
89 	/*G_X*/
90 	TRY(_memcpy_s(g_x, *g_x_len, m._message_1_G_X.value,
91 		      (uint32_t)m._message_1_G_X.len));
92 	*g_x_len = (uint32_t)m._message_1_G_X.len;
93 	PRINT_ARRAY("msg1 G_X", g_x, *g_x_len);
94 
95 	/*C_I*/
96 	if (m._message_1_C_I_choice == _message_1_C_I_int) {
97 		TRY(c_x_set(INT, NULL, 0, m._message_1_C_I_int, c_i));
98 		PRINTF("msg1 C_I_raw (int): %d\n", c_i->mem.c_x_int);
99 	} else {
100 		TRY(c_x_set(BSTR, m._message_1_C_I_bstr.value, 0,
101 			    m._message_1_C_I_int, c_i));
102 		PRINT_ARRAY("msg1 C_I_raw (bstr)", c_i->mem.c_x_bstr.ptr,
103 			    c_i->mem.c_x_bstr.len);
104 	}
105 
106 	/*ead_1*/
107 	if (m._message_1_ead_1_present) {
108 		TRY(_memcpy_s(ad1, *ad1_len, m._message_1_ead_1.value,
109 			      (uint32_t)m._message_1_ead_1.len));
110 		*ad1_len = (uint32_t)m._message_1_ead_1.len;
111 		PRINT_ARRAY("msg1 ead_1", ad1, *ad1_len);
112 	}
113 	return ok;
114 }
115 
116 /**
117  * @brief   checks if the selected (the first in the list received from the
118  *          initiator) ciphersute is supported
119  * @param   selected the selected suite
120  * @param   suites_r the list of suported ciphersuites
121  * @retval  true if supported
122  */
selected_suite_is_supported(uint8_t selected,struct byte_array * suites_r)123 static inline bool selected_suite_is_supported(uint8_t selected,
124 					       struct byte_array *suites_r)
125 {
126 	for (uint8_t i = 0; i < suites_r->len; i++) {
127 		if (suites_r->ptr[i] == selected)
128 			return true;
129 	}
130 	return false;
131 }
132 
133 /**
134  * @brief   Encodes message 2
135  * @param   corr corelation parameter
136  * @param   c_i Connection identifier of the initiator
137  * @param   c_i_len length of c_i
138  * @param   g_y public ephemeral DH key of the responder
139  * @param   g_y_len length of g_y
140  * @param   c_r connection identifier of the responder
141  * @param   c_r_len length of c_r
142  * @param   ciphertext_2 the ciphertext
143  * @param   ciphertext_2_len length of ciphertext_2
144  * @param   msg2 the encoded message
145  * @param   msg2_len length of msg2
146  * @retval  an err error code
147  */
msg2_encode(const uint8_t * g_y,uint32_t g_y_len,struct c_x * c_r,const uint8_t * ciphertext_2,uint32_t ciphertext_2_len,uint8_t * msg2,uint32_t * msg2_len)148 static inline enum err msg2_encode(const uint8_t *g_y, uint32_t g_y_len,
149 				   struct c_x *c_r, const uint8_t *ciphertext_2,
150 				   uint32_t ciphertext_2_len, uint8_t *msg2,
151 				   uint32_t *msg2_len)
152 {
153 	size_t payload_len_out;
154 	struct m2 m;
155 	uint32_t g_y_ciphertext_2_len = g_y_len + ciphertext_2_len;
156 	TRY(check_buffer_size(G_Y_DEFAULT_SIZE + CIPHERTEXT2_DEFAULT_SIZE,
157 			      g_y_ciphertext_2_len));
158 	uint8_t g_y_ciphertext_2[G_Y_DEFAULT_SIZE + CIPHERTEXT2_DEFAULT_SIZE];
159 
160 	memcpy(g_y_ciphertext_2, g_y, g_y_len);
161 	memcpy(g_y_ciphertext_2 + g_y_len, ciphertext_2, ciphertext_2_len);
162 
163 	/*Encode g_y_ciphertext_2*/
164 	m._m2_G_Y_CIPHERTEXT_2.value = g_y_ciphertext_2;
165 	m._m2_G_Y_CIPHERTEXT_2.len = g_y_ciphertext_2_len;
166 
167 	/*Encode C_R*/
168 	if (c_r->type == INT) {
169 		m._m2_C_R_choice = _m2_C_R_int;
170 		m._m2_C_R_int = c_r->mem.c_x_int;
171 	} else {
172 		m._m2_C_R_choice = _m2_C_R_bstr;
173 		m._m2_C_R_bstr.value = c_r->mem.c_x_bstr.ptr;
174 		m._m2_C_R_bstr.len = c_r->mem.c_x_bstr.len;
175 	}
176 
177 	TRY_EXPECT(cbor_encode_m2(msg2, *msg2_len, &m, &payload_len_out), true);
178 	*msg2_len = (uint32_t)payload_len_out;
179 
180 	PRINT_ARRAY("message_2 (CBOR Sequence)", msg2, *msg2_len);
181 	return ok;
182 }
183 
msg2_gen(struct edhoc_responder_context * c,struct runtime_context * rc,uint8_t * ead_1,uint32_t * ead_1_len)184 enum err msg2_gen(struct edhoc_responder_context *c, struct runtime_context *rc,
185 		  uint8_t *ead_1, uint32_t *ead_1_len)
186 {
187 	PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg1, rc->msg1_len);
188 
189 	enum method_type method = INITIATOR_SK_RESPONDER_SK;
190 	uint8_t suites_i[5];
191 	uint32_t suites_i_len = sizeof(suites_i);
192 	uint8_t g_x[G_X_DEFAULT_SIZE];
193 	uint32_t g_x_len = sizeof(g_x);
194 	uint8_t c_i_buf[C_I_DEFAULT_SIZE];
195 	struct c_x c_i;
196 	c_x_init(&c_i, c_i_buf, sizeof(c_i_buf));
197 
198 	TRY(msg1_parse(rc->msg1, rc->msg1_len, &method, suites_i, &suites_i_len,
199 		       g_x, &g_x_len, &c_i, ead_1, ead_1_len));
200 
201 	if (!(selected_suite_is_supported(suites_i[suites_i_len - 1],
202 					  &c->suites_r))) {
203 		// r = tx_err_msg(RESPONDER, method, c_i, c_i_len, NULL, 0,
204 		// 	       c->suites_r.ptr, c->suites_r.len);
205 		// if (r != ok) {
206 		// 	return r;
207 		// }
208 		/*After an error message is sent the protocol must be discontinued*/
209 		return error_message_sent;
210 	}
211 
212 	/*get cipher suite*/
213 	TRY(get_suite((enum suite_label)suites_i[suites_i_len - 1],
214 		      &rc->suite));
215 
216 	bool static_dh_r;
217 	authentication_type_get(method, &rc->static_dh_i, &static_dh_r);
218 
219 	/******************* create and send message 2*************************/
220 	uint8_t th2[SHA_DEFAULT_SIZE];
221 	uint32_t th2_len = sizeof(th2);
222 	TRY(th2_calculate(rc->suite.edhoc_hash, rc->msg1, rc->msg1_len,
223 			  c->g_y.ptr, c->g_y.len, &c->c_r, th2));
224 
225 	/*calculate the DH shared secret*/
226 	uint8_t g_xy[ECDH_SECRET_DEFAULT_SIZE];
227 	TRY(shared_secret_derive(rc->suite.edhoc_ecdh, c->y.ptr, c->y.len, g_x,
228 				 g_x_len, g_xy));
229 
230 	PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy, sizeof(g_xy));
231 
232 	uint8_t PRK_2e[PRK_DEFAULT_SIZE];
233 	TRY(hkdf_extract(rc->suite.edhoc_hash, NULL, 0, g_xy, sizeof(g_xy),
234 			 PRK_2e));
235 	PRINT_ARRAY("PRK_2e", PRK_2e, sizeof(PRK_2e));
236 
237 	/*derive prk_3e2m*/
238 	TRY(prk_derive(static_dh_r, rc->suite, PRK_2e, sizeof(PRK_2e), g_x,
239 		       g_x_len, c->r.ptr, c->r.len, rc->PRK_3e2m));
240 	PRINT_ARRAY("prk_3e2m", rc->PRK_3e2m, rc->PRK_3e2m_len);
241 
242 	/*compute signature_or_MAC_2*/
243 	uint32_t sign_or_mac_2_len = get_signature_len(rc->suite.edhoc_sign);
244 	TRY(check_buffer_size(SIGNATURE_DEFAULT_SIZE, sign_or_mac_2_len));
245 
246 	uint8_t sign_or_mac_2[SIGNATURE_DEFAULT_SIZE];
247 	TRY(signature_or_mac(GENERATE, static_dh_r, &rc->suite, c->sk_r.ptr,
248 			     c->sk_r.len, c->pk_r.ptr, c->pk_r.len,
249 			     rc->PRK_3e2m, rc->PRK_3e2m_len, th2, th2_len,
250 			     c->id_cred_r.ptr, c->id_cred_r.len, c->cred_r.ptr,
251 			     c->cred_r.len, c->ead_2.ptr, c->ead_2.len, "MAC_2",
252 			     sign_or_mac_2, &sign_or_mac_2_len));
253 
254 	/*compute ciphertext_2*/
255 	uint8_t ciphertext_2[CIPHERTEXT2_DEFAULT_SIZE];
256 	uint32_t ciphertext_2_len = sizeof(ciphertext_2);
257 	TRY(ciphertext_gen(CIPHERTEXT2, &rc->suite, c->id_cred_r.ptr,
258 			   c->id_cred_r.len, sign_or_mac_2, sign_or_mac_2_len,
259 			   c->ead_2.ptr, c->ead_2.len, PRK_2e, sizeof(PRK_2e),
260 			   th2, th2_len, ciphertext_2, &ciphertext_2_len));
261 
262 	/*message 2 create*/
263 	TRY(msg2_encode(c->g_y.ptr, c->g_y.len, &c->c_r, ciphertext_2,
264 			ciphertext_2_len, rc->msg2, &rc->msg2_len));
265 
266 	TRY(th3_calculate(rc->suite.edhoc_hash, th2, th2_len, ciphertext_2,
267 			  ciphertext_2_len, rc->th3));
268 
269 	return ok;
270 }
271 
msg3_process(struct edhoc_responder_context * c,struct runtime_context * rc,struct other_party_cred * cred_i_array,uint16_t num_cred_i,uint8_t * ead_3,uint32_t * ead_3_len,uint8_t * prk_4x3m,uint32_t prk_4x3m_len,uint8_t * th4)272 enum err msg3_process(struct edhoc_responder_context *c,
273 		      struct runtime_context *rc,
274 		      struct other_party_cred *cred_i_array,
275 		      uint16_t num_cred_i, uint8_t *ead_3, uint32_t *ead_3_len,
276 		      uint8_t *prk_4x3m, uint32_t prk_4x3m_len, uint8_t *th4)
277 {
278 	uint8_t ciphertext_3[CIPHERTEXT3_DEFAULT_SIZE];
279 	uint32_t ciphertext_3_len = sizeof(ciphertext_3);
280 
281 	// if (r == error_message_received) {
282 	// 	/*provide the error message to the caller*/
283 	// 	r = _memcpy_s(err_msg, *err_msg_len, msg3, msg3_len);
284 	// 	if (r != ok) {
285 	// 		return r;
286 	// 	}
287 	// 	*err_msg_len = msg3_len;
288 	// 	return error_message_received;
289 	// }
290 	TRY(decode_byte_string(rc->msg3, rc->msg3_len, ciphertext_3,
291 			       &ciphertext_3_len));
292 	PRINT_ARRAY("CIPHERTEXT_3", ciphertext_3, ciphertext_3_len);
293 
294 	uint8_t id_cred_i[ID_CRED_DEFAULT_SIZE];
295 	uint32_t id_cred_i_len = sizeof(id_cred_i);
296 	uint8_t sign_or_mac[SGN_OR_MAC_DEFAULT_SIZE];
297 	uint32_t sign_or_mac_len = sizeof(sign_or_mac);
298 	TRY(ciphertext_decrypt_split(
299 		CIPHERTEXT3, &rc->suite, id_cred_i, &id_cred_i_len, sign_or_mac,
300 		&sign_or_mac_len, ead_3, (uint32_t *)ead_3_len, rc->PRK_3e2m,
301 		rc->PRK_3e2m_len, rc->th3, rc->th3_len, ciphertext_3,
302 		ciphertext_3_len));
303 
304 	/*check the authenticity of the initiator*/
305 	uint8_t cred_i[CRED_DEFAULT_SIZE];
306 	uint32_t cred_i_len = sizeof(cred_i);
307 	uint8_t pk[PK_DEFAULT_SIZE];
308 	uint32_t pk_len = sizeof(pk);
309 	uint8_t g_i[G_I_DEFAULT_SIZE];
310 	uint32_t g_i_len = sizeof(g_i);
311 
312 	TRY(retrieve_cred(rc->static_dh_i, cred_i_array, num_cred_i, id_cred_i,
313 			  id_cred_i_len, cred_i, &cred_i_len, pk, &pk_len, g_i,
314 			  &g_i_len));
315 	PRINT_ARRAY("CRED_I", cred_i, cred_i_len);
316 	PRINT_ARRAY("pk", pk, pk_len);
317 	PRINT_ARRAY("g_i", g_i, g_i_len);
318 
319 	/*derive prk_4x3m*/
320 	TRY(prk_derive(rc->static_dh_i, rc->suite, rc->PRK_3e2m,
321 		       rc->PRK_3e2m_len, g_i, g_i_len, c->y.ptr, c->y.len,
322 		       prk_4x3m));
323 	PRINT_ARRAY("prk_4x3m", prk_4x3m, prk_4x3m_len);
324 
325 	TRY(signature_or_mac(VERIFY, rc->static_dh_i, &rc->suite, NULL, 0, pk,
326 			     pk_len, prk_4x3m, prk_4x3m_len, rc->th3,
327 			     rc->th3_len, id_cred_i, id_cred_i_len, cred_i,
328 			     cred_i_len, ead_3, *(uint32_t *)ead_3_len, "MAC_3",
329 			     sign_or_mac, &sign_or_mac_len));
330 
331 	/*TH4*/
332 	TRY(th4_calculate(rc->suite.edhoc_hash, rc->th3, rc->th3_len,
333 			  ciphertext_3, ciphertext_3_len, th4));
334 	return ok;
335 }
336 
msg4_gen(struct edhoc_responder_context * c,struct runtime_context * rc,uint8_t * prk_4x3m,uint32_t prk_4x3m_len,uint8_t * th4,uint32_t th4_len)337 enum err msg4_gen(struct edhoc_responder_context *c, struct runtime_context *rc,
338 		  uint8_t *prk_4x3m, uint32_t prk_4x3m_len, uint8_t *th4,
339 		  uint32_t th4_len)
340 {
341 	/*Ciphertext 4 calculate*/
342 	uint8_t ciphertext_4[CIPHERTEXT4_DEFAULT_SIZE];
343 	uint32_t ciphertext_4_len = sizeof(ciphertext_4);
344 
345 	TRY(ciphertext_gen(CIPHERTEXT4, &rc->suite, NULL, 0, NULL, 0,
346 			   c->ead_4.ptr, c->ead_4.len, prk_4x3m, prk_4x3m_len,
347 			   th4, th4_len, ciphertext_4, &ciphertext_4_len));
348 
349 	TRY(encode_byte_string(ciphertext_4, ciphertext_4_len, rc->msg4,
350 			       &rc->msg4_len));
351 
352 	PRINT_ARRAY("Message 4 ", rc->msg4, rc->msg4_len);
353 	return ok;
354 }
355 
edhoc_responder_run(struct edhoc_responder_context * c,struct other_party_cred * cred_i_array,uint16_t num_cred_i,uint8_t * err_msg,uint32_t * err_msg_len,uint8_t * ead_1,uint32_t * ead_1_len,uint8_t * ead_3,uint32_t * ead_3_len,uint8_t * prk_4x3m,uint32_t prk_4x3m_len,uint8_t * th4,uint32_t th4_len,enum err (* tx)(void * sock,uint8_t * data,uint32_t data_len),enum err (* rx)(void * sock,uint8_t * data,uint32_t * data_len))356 enum err edhoc_responder_run(
357 	struct edhoc_responder_context *c,
358 	struct other_party_cred *cred_i_array, uint16_t num_cred_i,
359 	uint8_t *err_msg, uint32_t *err_msg_len, uint8_t *ead_1,
360 	uint32_t *ead_1_len, uint8_t *ead_3, uint32_t *ead_3_len,
361 	uint8_t *prk_4x3m, uint32_t prk_4x3m_len, uint8_t *th4,
362 	uint32_t th4_len,
363 	enum err (*tx)(void *sock, uint8_t *data, uint32_t data_len),
364 	enum err (*rx)(void *sock, uint8_t *data, uint32_t *data_len))
365 {
366 	struct runtime_context rc = { 0 };
367 	runtime_context_init(&rc);
368 
369 	PRINT_MSG("waiting to receive message 1...\n");
370 	TRY(rx(c->sock, rc.msg1, &rc.msg1_len));
371 	TRY(msg2_gen(c, &rc, ead_1, ead_1_len));
372 	TRY(tx(c->sock, rc.msg2, rc.msg2_len));
373 
374 	PRINT_MSG("waiting to receive message 3...\n");
375 	TRY(rx(c->sock, rc.msg3, &rc.msg3_len));
376 	TRY(msg3_process(c, &rc, cred_i_array, num_cred_i, ead_3, ead_3_len,
377 			 prk_4x3m, prk_4x3m_len, th4));
378 	if (c->msg4) {
379 		TRY(msg4_gen(c, &rc, prk_4x3m, prk_4x3m_len, th4, th4_len));
380 		TRY(tx(c->sock, rc.msg4, rc.msg4_len));
381 	}
382 
383 	return ok;
384 }
385