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