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/crypto_wrapper.h"
16 #include "common/oscore_edhoc_error.h"
17 #include "common/memcpy_s.h"
18 #include "common/print_util.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/c_x.h"
31 #include "edhoc/ciphertext.h"
32 #include "edhoc/runtime_context.h"
33 
34 #include "cbor/edhoc_encode_message_1.h"
35 #include "cbor/edhoc_decode_message_2.h"
36 #include "cbor/edhoc_encode_message_3.h"
37 
38 /**
39  * @brief   Parses message 2
40  * @param   c initiator context
41  * @param   msg2 pointer to a buffer containign message 2
42  * @param   msg2_len the length of the raw message
43  * @param   msg2_struct pointer to a structure for the parsed message
44  * @param   err_msg pointer to an error message structure
45  */
msg2_parse(uint8_t * msg2,uint32_t msg2_len,uint8_t * g_y,uint32_t g_y_len,struct c_x * c_r,uint8_t * ciphertext2,uint32_t * ciphertext2_len)46 static inline enum err msg2_parse(uint8_t *msg2, uint32_t msg2_len,
47 				  uint8_t *g_y, uint32_t g_y_len,
48 				  struct c_x *c_r, uint8_t *ciphertext2,
49 				  uint32_t *ciphertext2_len)
50 {
51 	size_t decode_len = 0;
52 	struct m2 m;
53 
54 	TRY_EXPECT(cbor_decode_m2(msg2, msg2_len, &m, &decode_len), true);
55 	TRY(_memcpy_s(g_y, g_y_len, m._m2_G_Y_CIPHERTEXT_2.value, g_y_len));
56 	PRINT_ARRAY("g_y", g_y, g_y_len);
57 
58 	TRY(_memcpy_s(ciphertext2, *ciphertext2_len,
59 		      m._m2_G_Y_CIPHERTEXT_2.value + g_y_len,
60 		      (uint32_t)(m._m2_G_Y_CIPHERTEXT_2.len - g_y_len)));
61 
62 	*ciphertext2_len = (uint32_t)m._m2_G_Y_CIPHERTEXT_2.len - g_y_len;
63 	PRINT_ARRAY("ciphertext2", ciphertext2, *ciphertext2_len);
64 
65 	if (m._m2_C_R_choice == _m2_C_R_int) {
66 		TRY(c_x_set(INT, NULL, 0, m._m2_C_R_int, c_r));
67 		PRINTF("C_R is an int: %d\n", c_r->mem.c_x_int);
68 	} else {
69 		TRY(c_x_set(BSTR, m._m2_C_R_bstr.value,
70 			    (uint32_t)m._m2_C_R_bstr.len, 0, c_r));
71 		PRINT_ARRAY("C_R_raw bstr", c_r->mem.c_x_bstr.ptr,
72 			    c_r->mem.c_x_bstr.len);
73 	}
74 
75 	return ok;
76 }
77 
msg1_gen(const struct edhoc_initiator_context * c,struct runtime_context * rc)78 enum err msg1_gen(const struct edhoc_initiator_context *c,
79 		  struct runtime_context *rc)
80 {
81 	struct message_1 m1;
82 
83 	/*METHOD_CORR*/
84 	m1._message_1_METHOD = (int32_t)c->method;
85 
86 	/*SUITES_I*/
87 	if (c->suites_i.len == 1) {
88 		/* only one suite, encode into int */
89 		m1._message_1_SUITES_I_choice = _message_1_SUITES_I_int;
90 		m1._message_1_SUITES_I_int = c->suites_i.ptr[0];
91 	} else if (c->suites_i.len > 1) {
92 		/* more than one suites, encode into array */
93 		m1._message_1_SUITES_I_choice = _SUITES_I__suite;
94 		m1._SUITES_I__suite_suite_count = c->suites_i.len;
95 		for (uint32_t i = 0; i < c->suites_i.len; i++) {
96 			m1._SUITES_I__suite_suite[i] = c->suites_i.ptr[i];
97 		}
98 	}
99 
100 	/* G_X ephemeral public key */
101 	m1._message_1_G_X.value = c->g_x.ptr;
102 	m1._message_1_G_X.len = c->g_x.len;
103 
104 	/* C_I connection id, encoded as  bstr_identifier */
105 	if (c->c_i.type == INT) {
106 		m1._message_1_C_I_choice = _message_1_C_I_int;
107 		m1._message_1_C_I_int = c->c_i.mem.c_x_int;
108 	} else {
109 		m1._message_1_C_I_choice = _message_1_C_I_bstr;
110 		m1._message_1_C_I_bstr.value = c->c_i.mem.c_x_bstr.ptr;
111 		m1._message_1_C_I_bstr.len = c->c_i.mem.c_x_bstr.len;
112 	}
113 
114 	if (c->ead_1.len != 0) {
115 		/* ead_1 unprotected opaque auxiliary data */
116 		m1._message_1_ead_1.value = c->ead_1.ptr;
117 		m1._message_1_ead_1.len = c->ead_1.len;
118 		m1._message_1_ead_1_present = true;
119 	} else {
120 		m1._message_1_ead_1_present = 0;
121 	}
122 
123 	size_t payload_len_out;
124 	TRY_EXPECT(cbor_encode_message_1(rc->msg1, rc->msg1_len, &m1,
125 					 &payload_len_out),
126 		   true);
127 	rc->msg1_len = (uint32_t)payload_len_out;
128 
129 	PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg1, rc->msg1_len);
130 	return ok;
131 }
132 
msg3_gen(const struct edhoc_initiator_context * c,struct runtime_context * rc,struct other_party_cred * cred_r_array,uint16_t num_cred_r,uint8_t * ead_2,uint32_t * ead_2_len,uint8_t * prk_4x3m,uint32_t prk_4x3m_len,uint8_t * th4)133 enum err msg3_gen(const struct edhoc_initiator_context *c,
134 		  struct runtime_context *rc,
135 		  struct other_party_cred *cred_r_array, uint16_t num_cred_r,
136 		  uint8_t *ead_2, uint32_t *ead_2_len, uint8_t *prk_4x3m,
137 		  uint32_t prk_4x3m_len, uint8_t *th4)
138 {
139 	bool static_dh_i = false, static_dh_r = false;
140 	TRY(get_suite((enum suite_label)c->suites_i.ptr[c->suites_i.len - 1],
141 		      &rc->suite));
142 	TRY(authentication_type_get(c->method, &static_dh_i, &static_dh_r));
143 
144 	uint8_t g_y[G_Y_DEFAULT_SIZE];
145 	uint32_t g_y_len = get_ecdh_pk_len(rc->suite.edhoc_ecdh);
146 
147 	uint8_t c_r_buf[C_R_DEFAULT_SIZE];
148 	struct c_x c_r;
149 	c_x_init(&c_r, c_r_buf, sizeof(c_r_buf));
150 
151 	uint8_t ciphertext2[CIPHERTEXT2_DEFAULT_SIZE];
152 	uint32_t ciphertext2_len = sizeof(ciphertext2);
153 
154 	PRINT_ARRAY("message_2 (CBOR Sequence)", rc->msg2, rc->msg2_len);
155 
156 	/*
157 	* If an error message is received msg2_parse will return
158 	* error_message_received. If this hapens edhoc_initiator_run will
159 	* return. Then the caller needs to examine SUITES_R in err_msg
160 	* re-initialize the initiator and call edhoc_initiator_run again
161 	*/
162 	TRY(msg2_parse(rc->msg2, rc->msg2_len, g_y, g_y_len, &c_r,
163 		       (uint8_t *)&ciphertext2, &ciphertext2_len));
164 	// if (r == error_message_received) {
165 	// 	/*provide the error message to the caller*/
166 	// 	r = _memcpy_s(err_msg, *err_msg_len, msg2, msg2_len);
167 	// 	if (r != ok) {
168 	// 		return r;
169 	// 	}
170 	// 	*err_msg_len = msg2_len;
171 	// 	return error_message_received;
172 	// }
173 
174 	/*calculate the DH shared secret*/
175 	uint8_t g_xy[ECDH_SECRET_DEFAULT_SIZE];
176 	TRY(shared_secret_derive(rc->suite.edhoc_ecdh, c->x.ptr, c->x.len, g_y,
177 				 g_y_len, g_xy));
178 	PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy, sizeof(g_xy));
179 
180 	/*calculate th2*/
181 	uint8_t th2[SHA_DEFAULT_SIZE];
182 	TRY(th2_calculate(rc->suite.edhoc_hash, rc->msg1, rc->msg1_len, g_y,
183 			  g_y_len, &c_r, th2));
184 
185 	/*calculate PRK_2e*/
186 	uint8_t PRK_2e[PRK_DEFAULT_SIZE];
187 	TRY(hkdf_extract(rc->suite.edhoc_hash, NULL, 0, g_xy, sizeof(g_xy),
188 			 PRK_2e));
189 	PRINT_ARRAY("PRK_2e", PRK_2e, sizeof(PRK_2e));
190 
191 	uint8_t sign_or_mac[SGN_OR_MAC_DEFAULT_SIZE];
192 	uint32_t sign_or_mac_len = sizeof(sign_or_mac);
193 	uint8_t id_cred_r[ID_CRED_DEFAULT_SIZE];
194 	uint32_t id_cred_r_len = sizeof(id_cred_r);
195 	TRY(ciphertext_decrypt_split(
196 		CIPHERTEXT2, &rc->suite, id_cred_r, &id_cred_r_len, sign_or_mac,
197 		&sign_or_mac_len, ead_2, (uint32_t *)ead_2_len, PRK_2e,
198 		sizeof(PRK_2e), th2, sizeof(th2), ciphertext2,
199 		ciphertext2_len));
200 
201 	/*check the authenticity of the responder*/
202 	uint8_t cred_r[CRED_DEFAULT_SIZE];
203 	uint32_t cred_r_len = sizeof(cred_r);
204 	uint8_t pk[PK_DEFAULT_SIZE];
205 	uint32_t pk_len = sizeof(pk);
206 	uint8_t g_r[G_R_DEFAULT_SIZE];
207 	uint32_t g_r_len = sizeof(g_r);
208 
209 	TRY(retrieve_cred(static_dh_r, cred_r_array, num_cred_r, id_cred_r,
210 			  id_cred_r_len, cred_r, &cred_r_len, pk, &pk_len, g_r,
211 			  &g_r_len));
212 	PRINT_ARRAY("CRED_R", cred_r, cred_r_len);
213 	PRINT_ARRAY("pk", pk, pk_len);
214 	PRINT_ARRAY("g_r", g_r, g_r_len);
215 
216 	/*derive prk_3e2m*/
217 	uint8_t PRK_3e2m[PRK_DEFAULT_SIZE];
218 	TRY(prk_derive(static_dh_r, rc->suite, PRK_2e, sizeof(PRK_2e), g_r,
219 		       g_r_len, c->x.ptr, c->x.len, PRK_3e2m));
220 	PRINT_ARRAY("prk_3e2m", PRK_3e2m, sizeof(PRK_3e2m));
221 	//todo why static_dh_r?
222 	TRY(signature_or_mac(VERIFY, static_dh_r, &rc->suite, NULL, 0, pk,
223 			     pk_len, PRK_3e2m, sizeof(PRK_3e2m), th2,
224 			     sizeof(th2), id_cred_r, id_cred_r_len, cred_r,
225 			     cred_r_len, ead_2, *(uint32_t *)ead_2_len, "MAC_2",
226 			     sign_or_mac, &sign_or_mac_len));
227 
228 	/********msg3 create and send**************************************/
229 	uint8_t th3[32];
230 	TRY(th3_calculate(rc->suite.edhoc_hash, (uint8_t *)&th2, sizeof(th2),
231 			  ciphertext2, ciphertext2_len, th3));
232 
233 	/*derive prk_4x3m*/
234 	TRY(prk_derive(static_dh_i, rc->suite, (uint8_t *)&PRK_3e2m,
235 		       sizeof(PRK_3e2m), g_y, g_y_len, c->i.ptr, c->i.len,
236 		       prk_4x3m));
237 	PRINT_ARRAY("prk_4x3m", prk_4x3m, prk_4x3m_len);
238 
239 	/*calculate Signature_or_MAC_3*/
240 	uint32_t sign_or_mac_3_len = get_signature_len(rc->suite.edhoc_sign);
241 	uint8_t sign_or_mac_3[SIGNATURE_DEFAULT_SIZE];
242 
243 	TRY(signature_or_mac(GENERATE, static_dh_i, &rc->suite, c->sk_i.ptr,
244 			     c->sk_i.len, c->pk_i.ptr, c->pk_i.len, prk_4x3m,
245 			     prk_4x3m_len, th3, sizeof(th3), c->id_cred_i.ptr,
246 			     c->id_cred_i.len, c->cred_i.ptr, c->cred_i.len,
247 			     c->ead_3.ptr, c->ead_3.len, "MAC_3", sign_or_mac_3,
248 			     &sign_or_mac_3_len));
249 
250 	uint8_t ciphertext_3[CIPHERTEXT3_DEFAULT_SIZE];
251 	uint32_t ciphertext_3_len = sizeof(ciphertext_3);
252 	TRY(ciphertext_gen(CIPHERTEXT3, &rc->suite, c->id_cred_i.ptr,
253 			   c->id_cred_i.len, sign_or_mac_3, sign_or_mac_3_len,
254 			   c->ead_3.ptr, c->ead_3.len, PRK_3e2m,
255 			   sizeof(PRK_3e2m), th3, sizeof(th3), ciphertext_3,
256 			   &ciphertext_3_len));
257 
258 	/*massage 3 create and send*/
259 	TRY(check_buffer_size(CIPHERTEXT3_DEFAULT_SIZE,
260 			      ciphertext_3_len + ENCODING_OVERHEAD));
261 
262 	TRY(encode_byte_string(ciphertext_3, ciphertext_3_len, rc->msg3,
263 			       &rc->msg3_len));
264 	PRINT_ARRAY("msg3", rc->msg3, rc->msg3_len);
265 	/*TH4*/
266 	TRY(th4_calculate(rc->suite.edhoc_hash, th3, sizeof(th3), ciphertext_3,
267 			  ciphertext_3_len, th4));
268 	return ok;
269 }
270 
msg4_process(struct runtime_context * rc,uint8_t * ead_4,uint32_t * ead_4_len,uint8_t * prk_4x3m,uint32_t prk_4x3m_len,uint8_t * th4,uint32_t th4_len)271 enum err msg4_process(struct runtime_context *rc, uint8_t *ead_4,
272 		      uint32_t *ead_4_len, uint8_t *prk_4x3m,
273 		      uint32_t prk_4x3m_len, uint8_t *th4, uint32_t th4_len)
274 {
275 	PRINT_ARRAY("message_4 (CBOR Sequence)", rc->msg4, rc->msg4_len);
276 
277 	uint8_t ciphertext_4[CIPHERTEXT4_DEFAULT_SIZE];
278 	uint32_t ciphertext_4_len = sizeof(ciphertext_4);
279 	TRY(decode_byte_string(rc->msg4, rc->msg4_len, ciphertext_4,
280 			       &ciphertext_4_len));
281 	PRINT_ARRAY("ciphertext_4", ciphertext_4, ciphertext_4_len);
282 
283 	TRY(ciphertext_decrypt_split(CIPHERTEXT4, &rc->suite, NULL, 0, NULL, 0,
284 				     ead_4, (uint32_t *)ead_4_len, prk_4x3m,
285 				     prk_4x3m_len, th4, th4_len, ciphertext_4,
286 				     ciphertext_4_len));
287 	return ok;
288 }
289 
edhoc_initiator_run(const struct edhoc_initiator_context * c,struct other_party_cred * cred_r_array,uint16_t num_cred_r,uint8_t * err_msg,uint32_t * err_msg_len,uint8_t * ead_2,uint32_t * ead_2_len,uint8_t * ead_4,uint32_t * ead_4_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))290 enum err edhoc_initiator_run(
291 	const struct edhoc_initiator_context *c,
292 	struct other_party_cred *cred_r_array, uint16_t num_cred_r,
293 	uint8_t *err_msg, uint32_t *err_msg_len, uint8_t *ead_2,
294 	uint32_t *ead_2_len, uint8_t *ead_4, uint32_t *ead_4_len,
295 	uint8_t *prk_4x3m, uint32_t prk_4x3m_len, uint8_t *th4,
296 	uint32_t th4_len,
297 	enum err (*tx)(void *sock, uint8_t *data, uint32_t data_len),
298 	enum err (*rx)(void *sock, uint8_t *data, uint32_t *data_len))
299 {
300 	struct runtime_context rc = { 0 };
301 	runtime_context_init(&rc);
302 
303 	TRY(msg1_gen(c, &rc));
304 	TRY(tx(c->sock, rc.msg1, rc.msg1_len));
305 
306 	PRINT_MSG("waiting to receive message 2...\n");
307 	TRY(rx(c->sock, rc.msg2, &rc.msg2_len));
308 	TRY(msg3_gen(c, &rc, cred_r_array, num_cred_r, ead_2, ead_2_len,
309 		     prk_4x3m, prk_4x3m_len, th4));
310 	TRY(tx(c->sock, rc.msg3, rc.msg3_len));
311 
312 	if (c->msg4) {
313 		PRINT_MSG("waiting to receive message 4...\n");
314 		TRY(rx(c->sock, rc.msg4, &rc.msg4_len));
315 		TRY(msg4_process(&rc, ead_4, ead_4_len, prk_4x3m, prk_4x3m_len,
316 				 th4, th4_len));
317 	}
318 	return ok;
319 }
320