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