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