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 <stdbool.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/buffer_sizes.h"
21 #include "edhoc/hkdf_info.h"
22 #include "edhoc/messages.h"
23 #include "edhoc/okm.h"
24 #include "edhoc/plaintext.h"
25 #include "edhoc/prk.h"
26 #include "edhoc/retrieve_cred.h"
27 #include "edhoc/signature_or_mac_msg.h"
28 #include "edhoc/suites.h"
29 #include "edhoc/th.h"
30 #include "edhoc/txrx_wrapper.h"
31 #include "edhoc/ciphertext.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_encode_message_1.h"
37 #include "cbor/edhoc_decode_message_2.h"
38 #include "cbor/edhoc_encode_message_3.h"
39 
40 /**
41  * @brief   			Parses message 2.
42  * @param c 			Initiator context.
43  * @param[in] msg2 		Message 2.
44  * @param[out] g_y		G_Y ephemeral public key of the responder.
45  * @param[out] c_r		C_R connection identifier of the responder.
46  * @param[out] ciphertext2	Ciphertext 2.
47  * @retval			Ok or error code.
48  */
msg2_parse(struct byte_array * msg2,struct byte_array * g_y,struct byte_array * c_r,struct byte_array * ciphertext2)49 static inline enum err msg2_parse(struct byte_array *msg2,
50 				  struct byte_array *g_y,
51 				  struct byte_array *c_r,
52 				  struct byte_array *ciphertext2)
53 {
54 	size_t decode_len = 0;
55 	struct m2 m;
56 
57 	TRY_EXPECT(cbor_decode_m2(msg2->ptr, msg2->len, &m, &decode_len), 0);
58 	TRY(_memcpy_s(g_y->ptr, g_y->len, m.m2_G_Y_CIPHERTEXT_2.value,
59 		      g_y->len));
60 	PRINT_ARRAY("g_y", g_y->ptr, g_y->len);
61 
62 	TRY(_memcpy_s(ciphertext2->ptr, ciphertext2->len,
63 		      m.m2_G_Y_CIPHERTEXT_2.value + g_y->len,
64 		      (uint32_t)(m.m2_G_Y_CIPHERTEXT_2.len - g_y->len)));
65 
66 	ciphertext2->len = (uint32_t)m.m2_G_Y_CIPHERTEXT_2.len - g_y->len;
67 	PRINT_ARRAY("ciphertext2", ciphertext2->ptr, ciphertext2->len);
68 
69 	if (m.m2_C_R_choice == m2_C_R_int_c) {
70 		TRY(encode_int(&m.m2_C_R_int, 1, c_r));
71 	} else {
72 		TRY(_memcpy_s(c_r->ptr, c_r->len, m.m2_C_R_bstr.value,
73 			      (uint32_t)m.m2_C_R_bstr.len));
74 		c_r->len = (uint32_t)m.m2_C_R_bstr.len;
75 	}
76 	PRINT_ARRAY("C_R_raw", c_r->ptr, c_r->len);
77 
78 	return ok;
79 }
80 
msg1_gen(const struct edhoc_initiator_context * c,struct runtime_context * rc)81 enum err msg1_gen(const struct edhoc_initiator_context *c,
82 		  struct runtime_context *rc)
83 {
84 	struct message_1 m1;
85 
86 	/*METHOD_CORR*/
87 	m1.message_1_METHOD = (int32_t)c->method;
88 
89 	/*SUITES_I*/
90 	if (c->suites_i.len == 1) {
91 		/* only one suite, encode into int */
92 		m1.message_1_SUITES_I_choice = message_1_SUITES_I_int_c;
93 		m1.message_1_SUITES_I_int = c->suites_i.ptr[0];
94 	} else if (c->suites_i.len > 1) {
95 		/* more than one suites, encode into array */
96 		m1.message_1_SUITES_I_choice = SUITES_I_suite_l_c;
97 		m1.SUITES_I_suite_l_suite_count = c->suites_i.len;
98 		for (uint32_t i = 0; i < c->suites_i.len; i++) {
99 			m1.SUITES_I_suite_l_suite[i] = c->suites_i.ptr[i];
100 		}
101 	}
102 
103 	/* G_X ephemeral public key */
104 	m1.message_1_G_X.value = c->g_x.ptr;
105 	m1.message_1_G_X.len = c->g_x.len;
106 
107 	/* C_I connection ID  of the initiator*/
108 	PRINT_ARRAY("C_I", c->c_i.ptr, c->c_i.len);
109 	if (c->c_i.len == 1 &&
110 	    ((0x00 <= c->c_i.ptr[0] && c->c_i.ptr[0] < 0x18) ||
111 	     (0x1F < c->c_i.ptr[0] && c->c_i.ptr[0] <= 0x37))) {
112 		m1.message_1_C_I_choice = message_1_C_I_int_c;
113 		TRY(decode_int(&c->c_i, &m1.message_1_C_I_int));
114 	} else {
115 		m1.message_1_C_I_choice = message_1_C_I_bstr_c;
116 		m1.message_1_C_I_bstr.value = c->c_i.ptr;
117 		m1.message_1_C_I_bstr.len = c->c_i.len;
118 	}
119 
120 	if (c->ead_1.len != 0) {
121 		/* ead_1 unprotected opaque auxiliary data */
122 		m1.message_1_ead_1.value = c->ead_1.ptr;
123 		m1.message_1_ead_1.len = c->ead_1.len;
124 		m1.message_1_ead_1_present = true;
125 	} else {
126 		m1.message_1_ead_1_present = false;
127 	}
128 
129 	size_t payload_len_out;
130 	TRY_EXPECT(cbor_encode_message_1(rc->msg.ptr, rc->msg.len, &m1,
131 					 &payload_len_out),
132 		   0);
133 	rc->msg.len = (uint32_t)payload_len_out;
134 
135 	PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
136 
137 	TRY(get_suite((enum suite_label)c->suites_i.ptr[c->suites_i.len - 1],
138 		      &rc->suite));
139 	/* Calculate hash of msg1 for TH2. */
140 	TRY(hash(rc->suite.edhoc_hash, &rc->msg, &rc->msg1_hash));
141 	return ok;
142 }
143 
msg2_process(const struct edhoc_initiator_context * c,struct runtime_context * rc,struct cred_array * cred_r_array,struct byte_array * c_r,bool static_dh_i,bool static_dh_r,struct byte_array * th3,struct byte_array * PRK_3e2m)144 static enum err msg2_process(const struct edhoc_initiator_context *c,
145 			     struct runtime_context *rc,
146 			     struct cred_array *cred_r_array,
147 			     struct byte_array *c_r, bool static_dh_i,
148 			     bool static_dh_r, struct byte_array *th3,
149 			     struct byte_array *PRK_3e2m)
150 {
151 	BYTE_ARRAY_NEW(g_y, G_Y_SIZE, get_ecdh_pk_len(rc->suite.edhoc_ecdh));
152 	uint32_t ciphertext_len = rc->msg.len - g_y.len - c_r->len;
153 	ciphertext_len -= BSTR_ENCODING_OVERHEAD(ciphertext_len);
154 	BYTE_ARRAY_NEW(ciphertext, CIPHERTEXT2_SIZE, ciphertext_len);
155 	BYTE_ARRAY_NEW(plaintext, PLAINTEXT2_SIZE, ciphertext.len);
156 	PRINT_ARRAY("message_2 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
157 
158 	/*parse the message*/
159 	TRY(msg2_parse(&rc->msg, &g_y, c_r, &ciphertext));
160 
161 	/*calculate the DH shared secret*/
162 	BYTE_ARRAY_NEW(g_xy, ECDH_SECRET_SIZE, ECDH_SECRET_SIZE);
163 
164 	TRY(shared_secret_derive(rc->suite.edhoc_ecdh, &c->x, &g_y, g_xy.ptr));
165 	PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy.ptr, g_xy.len);
166 
167 	/*calculate th2*/
168 	BYTE_ARRAY_NEW(th2, HASH_SIZE, get_hash_len(rc->suite.edhoc_hash));
169 
170 	TRY(th2_calculate(rc->suite.edhoc_hash, &rc->msg1_hash, &g_y, c_r,
171 			  &th2));
172 	PRINT_ARRAY("TH_2", th2.ptr, th2.len);
173 
174 	/*calculate PRK_2e*/
175 	BYTE_ARRAY_NEW(PRK_2e, PRK_SIZE, PRK_SIZE);
176 	TRY(hkdf_extract(rc->suite.edhoc_hash, &th2, &g_xy, PRK_2e.ptr));
177 	PRINT_ARRAY("PRK_2e", PRK_2e.ptr, PRK_2e.len);
178 
179 	BYTE_ARRAY_NEW(sign_or_mac, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
180 	BYTE_ARRAY_NEW(id_cred_r, ID_CRED_R_SIZE, ID_CRED_R_SIZE);
181 
182 	plaintext.len = ciphertext.len;
183 	TRY(check_buffer_size(PLAINTEXT2_SIZE, plaintext.len));
184 
185 	TRY(ciphertext_decrypt_split(CIPHERTEXT2, &rc->suite, &id_cred_r,
186 				     &sign_or_mac, &rc->ead, &PRK_2e, &th2,
187 				     &ciphertext, &plaintext));
188 
189 	/*check the authenticity of the responder*/
190 	BYTE_ARRAY_NEW(cred_r, CRED_R_SIZE, CRED_R_SIZE);
191 	BYTE_ARRAY_NEW(pk, PK_SIZE, PK_SIZE);
192 	BYTE_ARRAY_NEW(g_r, G_R_SIZE, G_R_SIZE);
193 	TRY(retrieve_cred(static_dh_r, cred_r_array, &id_cred_r, &cred_r, &pk,
194 			  &g_r));
195 	PRINT_ARRAY("CRED_R", cred_r.ptr, cred_r.len);
196 	PRINT_ARRAY("pk", pk.ptr, pk.len);
197 	PRINT_ARRAY("g_r", g_r.ptr, g_r.len);
198 
199 	/*derive prk_3e2m*/
200 	TRY(prk_derive(static_dh_r, rc->suite, SALT_3e2m, &th2, &PRK_2e, &g_r,
201 		       &c->x, PRK_3e2m->ptr));
202 	PRINT_ARRAY("prk_3e2m", PRK_3e2m->ptr, PRK_3e2m->len);
203 
204 	TRY(signature_or_mac(VERIFY, static_dh_r, &rc->suite, NULL, &pk,
205 			     PRK_3e2m, &th2, &id_cred_r, &cred_r, &rc->ead,
206 			     MAC_2, &sign_or_mac));
207 
208 	TRY(th34_calculate(rc->suite.edhoc_hash, &th2, &plaintext, &cred_r,
209 			   th3));
210 
211 	/*derive prk_4e3m*/
212 	TRY(prk_derive(static_dh_i, rc->suite, SALT_4e3m, th3, PRK_3e2m, &g_y,
213 		       &c->i, rc->prk_4e3m.ptr));
214 	PRINT_ARRAY("prk_4e3m", rc->prk_4e3m.ptr, rc->prk_4e3m.len);
215 
216 	return ok;
217 }
218 
msg3_only_gen(const struct edhoc_initiator_context * c,struct runtime_context * rc,bool static_dh_i,struct byte_array * th3,struct byte_array * PRK_3e2m,struct byte_array * prk_out)219 static enum err msg3_only_gen(const struct edhoc_initiator_context *c,
220 			      struct runtime_context *rc, bool static_dh_i,
221 			      struct byte_array *th3,
222 			      struct byte_array *PRK_3e2m,
223 			      struct byte_array *prk_out)
224 {
225 	BYTE_ARRAY_NEW(plaintext, PLAINTEXT3_SIZE,
226 		       c->id_cred_i.len + (SIG_OR_MAC_SIZE + 2) + c->ead_3.len);
227 	BYTE_ARRAY_NEW(ciphertext, CIPHERTEXT3_SIZE,
228 		       plaintext.len + ENCODING_OVERHEAD);
229 	/*calculate Signature_or_MAC_3*/
230 	BYTE_ARRAY_NEW(sign_or_mac_3, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
231 	TRY(signature_or_mac(GENERATE, static_dh_i, &rc->suite, &c->sk_i,
232 			     &c->pk_i, &rc->prk_4e3m, th3, &c->id_cred_i,
233 			     &c->cred_i, &c->ead_3, MAC_3, &sign_or_mac_3));
234 
235 	/*create plaintext3 and ciphertext3*/
236 	TRY(ciphertext_gen(CIPHERTEXT3, &rc->suite, &c->id_cred_i,
237 			   &sign_or_mac_3, &c->ead_3, PRK_3e2m, th3,
238 			   &ciphertext, &plaintext));
239 
240 	/*massage 3 create and send*/
241 	TRY(encode_bstr(&ciphertext, &rc->msg));
242 	PRINT_ARRAY("msg3", rc->msg.ptr, rc->msg.len);
243 
244 	/*TH4*/
245 	TRY(th34_calculate(rc->suite.edhoc_hash, th3, &plaintext, &c->cred_i,
246 			   &rc->th4));
247 
248 	/*PRK_out*/
249 	TRY(edhoc_kdf(rc->suite.edhoc_hash, &rc->prk_4e3m, PRK_out, &rc->th4,
250 		      prk_out));
251 	return ok;
252 }
253 
msg3_gen(const struct edhoc_initiator_context * c,struct runtime_context * rc,struct cred_array * cred_r_array,struct byte_array * c_r,struct byte_array * prk_out)254 enum err msg3_gen(const struct edhoc_initiator_context *c,
255 		  struct runtime_context *rc, struct cred_array *cred_r_array,
256 		  struct byte_array *c_r, struct byte_array *prk_out)
257 {
258 	bool static_dh_i = false, static_dh_r = false;
259 	authentication_type_get(c->method, &static_dh_i, &static_dh_r);
260 	BYTE_ARRAY_NEW(th3, HASH_SIZE, HASH_SIZE);
261 	BYTE_ARRAY_NEW(PRK_3e2m, PRK_SIZE, PRK_SIZE);
262 
263 	/*process message 2*/
264 	TRY(msg2_process(c, rc, cred_r_array, c_r, static_dh_i, static_dh_r,
265 			 &th3, &PRK_3e2m));
266 
267 	/*generate message 3*/
268 	msg3_only_gen(c, rc, static_dh_i, &th3, &PRK_3e2m, prk_out);
269 	return ok;
270 }
271 
272 #ifdef MESSAGE_4
msg4_process(struct runtime_context * rc)273 enum err msg4_process(struct runtime_context *rc)
274 {
275 	PRINT_ARRAY("message4 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
276 
277 	BYTE_ARRAY_NEW(ciphertext4, CIPHERTEXT4_SIZE, CIPHERTEXT4_SIZE);
278 	TRY(decode_bstr(&rc->msg, &ciphertext4));
279 	PRINT_ARRAY("ciphertext_4", ciphertext4.ptr, ciphertext4.len);
280 
281 	BYTE_ARRAY_NEW(plaintext4,
282 		       PLAINTEXT4_SIZE + get_aead_mac_len(rc->suite.edhoc_aead),
283 		       ciphertext4.len);
284 	TRY(ciphertext_decrypt_split(CIPHERTEXT4, &rc->suite, &NULL_ARRAY,
285 				     &NULL_ARRAY, &rc->ead, &rc->prk_4e3m,
286 				     &rc->th4, &ciphertext4, &plaintext4));
287 	return ok;
288 }
289 #endif // MESSAGE_4
290 
edhoc_initiator_run_extended(const struct edhoc_initiator_context * c,struct cred_array * cred_r_array,struct byte_array * err_msg,struct byte_array * c_r_bytes,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 * ead24))291 enum err edhoc_initiator_run_extended(
292 	const struct edhoc_initiator_context *c,
293 	struct cred_array *cred_r_array, struct byte_array *err_msg,
294 	struct byte_array *c_r_bytes, struct byte_array *prk_out,
295 	enum err (*tx)(void *sock, struct byte_array *data),
296 	enum err (*rx)(void *sock, struct byte_array *data),
297 	enum err (*ead_process)(void *params, struct byte_array *ead24))
298 {
299 	struct runtime_context rc = { 0 };
300 	runtime_context_init(&rc);
301 
302 	/*create and send message 1*/
303 	TRY(msg1_gen(c, &rc));
304 	TRY(tx(c->sock, &rc.msg));
305 
306 	/*receive message 2*/
307 	PRINT_MSG("waiting to receive message 2...\n");
308 	rc.msg.len = sizeof(rc.msg_buf);
309 	TRY(rx(c->sock, &rc.msg));
310 
311 	/*create and send message 3*/
312 	TRY(msg3_gen(c, &rc, cred_r_array, c_r_bytes, prk_out));
313 	TRY(ead_process(c->params_ead_process, &rc.ead));
314 	TRY(tx(c->sock, &rc.msg));
315 
316 	/*receive message 4*/
317 #ifdef MESSAGE_4
318 	PRINT_MSG("waiting to receive message 4...\n");
319 	rc.msg.len = sizeof(rc.msg_buf);
320 	TRY(rx(c->sock, &rc.msg));
321 	TRY(msg4_process(&rc));
322 	TRY(ead_process(c->params_ead_process, &rc.ead));
323 #endif // MESSAGE_4
324 	return ok;
325 }
326 
edhoc_initiator_run(const struct edhoc_initiator_context * c,struct cred_array * cred_r_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 * ead24))327 enum err edhoc_initiator_run(
328 	const struct edhoc_initiator_context *c,
329 	struct cred_array *cred_r_array, struct byte_array *err_msg,
330 	struct byte_array *prk_out,
331 	enum err (*tx)(void *sock, struct byte_array *data),
332 	enum err (*rx)(void *sock, struct byte_array *data),
333 	enum err (*ead_process)(void *params, struct byte_array *ead24))
334 {
335 	BYTE_ARRAY_NEW(c_r, C_R_SIZE, C_R_SIZE);
336 
337 	return edhoc_initiator_run_extended(c, cred_r_array, err_msg, &c_r,
338 					    prk_out, tx, rx, ead_process);
339 }
340