Branch data Line data Source code
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 : : */
48 : 3 : static inline enum err msg2_parse(struct byte_array *msg2,
49 : : struct byte_array *g_y,
50 : : struct byte_array *ciphertext2)
51 : : {
52 [ - + ]: 3 : BYTE_ARRAY_NEW(g_y_ciphertext_2, G_Y_CIPHERTEXT_2, G_Y_CIPHERTEXT_2);
53 [ - + ]: 3 : TRY(decode_bstr(msg2, &g_y_ciphertext_2));
54 : :
55 [ - + ]: 3 : TRY(_memcpy_s(g_y->ptr, g_y->len, g_y_ciphertext_2.ptr, g_y->len));
56 : 3 : PRINT_ARRAY("g_y", g_y->ptr, g_y->len);
57 : :
58 [ - + ]: 3 : 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 : 3 : ciphertext2->len = g_y_ciphertext_2.len - g_y->len;
63 : 3 : PRINT_ARRAY("ciphertext2", ciphertext2->ptr, ciphertext2->len);
64 : :
65 : 3 : return ok;
66 : : }
67 : :
68 : 3 : 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 : 3 : m1.message_1_METHOD = (int32_t)c->method;
75 : :
76 : : /*SUITES_I*/
77 [ + - ]: 3 : if (c->suites_i.len == 1) {
78 : : /* only one suite, encode into int */
79 : 3 : m1.message_1_SUITES_I_choice = message_1_SUITES_I_int_c;
80 : 3 : m1.message_1_SUITES_I_int = c->suites_i.ptr[0];
81 [ # # ]: 0 : } else if (c->suites_i.len > 1) {
82 : : /* more than one suites, encode into array */
83 : 0 : m1.message_1_SUITES_I_choice = SUITES_I_suite_l_c;
84 : 0 : m1.SUITES_I_suite_l_suite_count = c->suites_i.len;
85 [ # # ]: 0 : for (uint32_t i = 0; i < c->suites_i.len; i++) {
86 : 0 : m1.SUITES_I_suite_l_suite[i] = c->suites_i.ptr[i];
87 : : }
88 : : }
89 : :
90 : : /* G_X ephemeral public key */
91 : 3 : m1.message_1_G_X.value = c->g_x.ptr;
92 : 3 : m1.message_1_G_X.len = c->g_x.len;
93 : :
94 : : /* C_I connection ID of the initiator*/
95 : 3 : PRINT_ARRAY("C_I", c->c_i.ptr, c->c_i.len);
96 [ + - ]: 3 : if (c_x_is_encoded_int(&c->c_i)) {
97 : 3 : m1.message_1_C_I_choice = message_1_C_I_int_c;
98 [ - + ]: 3 : TRY(decode_int(&c->c_i, &m1.message_1_C_I_int));
99 : : } else {
100 : 0 : m1.message_1_C_I_choice = message_1_C_I_bstr_c;
101 : 0 : m1.message_1_C_I_bstr.value = c->c_i.ptr;
102 : 0 : m1.message_1_C_I_bstr.len = c->c_i.len;
103 : : }
104 : :
105 [ - + ]: 3 : if (c->ead_1.len != 0) {
106 : : /* ead_1 unprotected opaque auxiliary data */
107 : 0 : m1.message_1_ead_1.value = c->ead_1.ptr;
108 : 0 : m1.message_1_ead_1.len = c->ead_1.len;
109 : 0 : m1.message_1_ead_1_present = true;
110 : : } else {
111 : 3 : m1.message_1_ead_1_present = false;
112 : : }
113 : :
114 : : size_t payload_len_out;
115 [ - + ]: 3 : TRY_EXPECT(cbor_encode_message_1(rc->msg.ptr, rc->msg.len, &m1,
116 : : &payload_len_out),
117 : : 0);
118 : 3 : rc->msg.len = (uint32_t)payload_len_out;
119 : :
120 : 3 : PRINT_ARRAY("message_1 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
121 : :
122 [ - + ]: 3 : 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 [ - + ]: 3 : TRY(hash(rc->suite.edhoc_hash, &rc->msg, &rc->msg1_hash));
126 : 3 : return ok;
127 : : }
128 : :
129 : 3 : 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 [ - + - + ]: 3 : BYTE_ARRAY_NEW(g_y, G_Y_SIZE, get_ecdh_pk_len(rc->suite.edhoc_ecdh));
137 : 3 : uint32_t ciphertext_len = rc->msg.len - g_y.len;
138 [ + - + + : 3 : ciphertext_len -= BSTR_ENCODING_OVERHEAD(ciphertext_len);
+ - ]
139 [ - + - + ]: 3 : BYTE_ARRAY_NEW(ciphertext, CIPHERTEXT2_SIZE, ciphertext_len);
140 [ - + - + ]: 3 : BYTE_ARRAY_NEW(plaintext, PLAINTEXT2_SIZE, ciphertext.len);
141 : 3 : PRINT_ARRAY("message_2 (CBOR Sequence)", rc->msg.ptr, rc->msg.len);
142 : :
143 : : /*parse the message*/
144 [ - + ]: 3 : TRY(msg2_parse(&rc->msg, &g_y, &ciphertext));
145 : :
146 : : /*calculate the DH shared secret*/
147 [ - + ]: 3 : BYTE_ARRAY_NEW(g_xy, ECDH_SECRET_SIZE, ECDH_SECRET_SIZE);
148 : :
149 [ - + ]: 3 : TRY(shared_secret_derive(rc->suite.edhoc_ecdh, &c->x, &g_y, g_xy.ptr));
150 : 3 : PRINT_ARRAY("G_XY (ECDH shared secret) ", g_xy.ptr, g_xy.len);
151 : :
152 : : /*calculate th2*/
153 [ - + - + ]: 3 : BYTE_ARRAY_NEW(th2, HASH_SIZE, get_hash_len(rc->suite.edhoc_hash));
154 : :
155 [ - + ]: 3 : TRY(th2_calculate(rc->suite.edhoc_hash, &rc->msg1_hash, &g_y, &th2));
156 : :
157 : : /*calculate PRK_2e*/
158 [ - + ]: 3 : BYTE_ARRAY_NEW(PRK_2e, PRK_SIZE, PRK_SIZE);
159 [ - + ]: 3 : TRY(hkdf_extract(rc->suite.edhoc_hash, &th2, &g_xy, PRK_2e.ptr));
160 : 3 : PRINT_ARRAY("PRK_2e", PRK_2e.ptr, PRK_2e.len);
161 : :
162 [ - + ]: 3 : BYTE_ARRAY_NEW(sign_or_mac, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
163 [ - + ]: 3 : BYTE_ARRAY_NEW(id_cred_r, ID_CRED_R_SIZE, ID_CRED_R_SIZE);
164 : :
165 : 3 : plaintext.len = ciphertext.len;
166 [ - + ]: 3 : TRY(check_buffer_size(PLAINTEXT2_SIZE, plaintext.len));
167 : :
168 [ - + ]: 3 : 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 [ - + ]: 3 : BYTE_ARRAY_NEW(cred_r, CRED_R_SIZE, CRED_R_SIZE);
174 [ - + ]: 3 : BYTE_ARRAY_NEW(pk, PK_SIZE, PK_SIZE);
175 [ - + ]: 3 : BYTE_ARRAY_NEW(g_r, G_R_SIZE, G_R_SIZE);
176 [ - + ]: 3 : TRY(retrieve_cred(static_dh_r, cred_r_array, &id_cred_r, &cred_r, &pk,
177 : : &g_r));
178 : 3 : PRINT_ARRAY("CRED_R", cred_r.ptr, cred_r.len);
179 : 3 : PRINT_ARRAY("pk", pk.ptr, pk.len);
180 : 3 : PRINT_ARRAY("g_r", g_r.ptr, g_r.len);
181 : :
182 : : /*derive prk_3e2m*/
183 [ - + ]: 3 : TRY(prk_derive(static_dh_r, rc->suite, SALT_3e2m, &th2, &PRK_2e, &g_r,
184 : : &c->x, PRK_3e2m->ptr));
185 : 3 : PRINT_ARRAY("prk_3e2m", PRK_3e2m->ptr, PRK_3e2m->len);
186 : :
187 [ - + ]: 3 : 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 [ - + ]: 3 : TRY(th34_calculate(rc->suite.edhoc_hash, &th2, &plaintext, &cred_r,
192 : : th3));
193 : :
194 : : /*derive prk_4e3m*/
195 [ - + ]: 3 : TRY(prk_derive(static_dh_i, rc->suite, SALT_4e3m, th3, PRK_3e2m, &g_y,
196 : : &c->i, rc->prk_4e3m.ptr));
197 : 3 : PRINT_ARRAY("prk_4e3m", rc->prk_4e3m.ptr, rc->prk_4e3m.len);
198 : :
199 : 3 : return ok;
200 : : }
201 : :
202 : 3 : 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 [ - + - + ]: 3 : 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 [ + - + + : 3 : 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 [ - + ]: 3 : BYTE_ARRAY_NEW(sign_or_mac_3, SIG_OR_MAC_SIZE, SIG_OR_MAC_SIZE);
216 [ - + ]: 3 : 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 [ - + ]: 3 : 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 [ - + ]: 3 : TRY(encode_bstr(&ciphertext, &rc->msg));
228 : 3 : PRINT_ARRAY("msg3", rc->msg.ptr, rc->msg.len);
229 : :
230 : : /*TH4*/
231 [ - + ]: 3 : TRY(th34_calculate(rc->suite.edhoc_hash, th3, &plaintext, &c->cred_i,
232 : : &rc->th4));
233 : :
234 : : /*PRK_out*/
235 [ - + ]: 3 : TRY(edhoc_kdf(rc->suite.edhoc_hash, &rc->prk_4e3m, PRK_out, &rc->th4,
236 : : prk_out));
237 : 3 : return ok;
238 : : }
239 : :
240 : 3 : 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 : 3 : bool static_dh_i = false, static_dh_r = false;
245 : 3 : authentication_type_get(c->method, &static_dh_i, &static_dh_r);
246 [ - + ]: 3 : BYTE_ARRAY_NEW(th3, HASH_SIZE, HASH_SIZE);
247 [ - + ]: 3 : BYTE_ARRAY_NEW(PRK_3e2m, PRK_SIZE, PRK_SIZE);
248 : :
249 : : /*process message 2*/
250 [ - + ]: 3 : 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 : 3 : msg3_only_gen(c, rc, static_dh_i, &th3, &PRK_3e2m, prk_out);
255 : 3 : return ok;
256 : : }
257 : :
258 : : #ifdef MESSAGE_4
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 : :
277 : 3 : 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 : 3 : struct runtime_context rc = { 0 };
286 : 3 : runtime_context_init(&rc);
287 : :
288 : : /*create and send message 1*/
289 [ - + ]: 3 : TRY(msg1_gen(c, &rc));
290 [ - + ]: 3 : TRY(tx(c->sock, &rc.msg));
291 : :
292 : : /*receive message 2*/
293 : 3 : PRINT_MSG("waiting to receive message 2...\n");
294 : 3 : rc.msg.len = sizeof(rc.msg_buf);
295 [ - + ]: 3 : TRY(rx(c->sock, &rc.msg));
296 : :
297 : : /*create and send message 3*/
298 [ - + ]: 3 : TRY(msg3_gen(c, &rc, cred_r_array, c_r_bytes, prk_out));
299 [ - + ]: 3 : TRY(ead_process(c->params_ead_process, &rc.ead));
300 [ - + ]: 3 : 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 : 3 : return ok;
311 : : }
312 : :
313 : 3 : 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 [ - + ]: 3 : BYTE_ARRAY_NEW(c_r, C_R_SIZE, C_R_SIZE);
322 : :
323 : 3 : return edhoc_initiator_run_extended(c, cred_r_array, err_msg, &c_r,
324 : : prk_out, tx, rx, ead_process);
325 : : }
|