1 /*
2 * Copyright (c) 2022 Eriptic Technologies.
3 *
4 * SPDX-License-Identifier: Apache-2.0 or MIT
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/ztest.h>
9 #include <zephyr/debug/thread_analyzer.h>
10
11 #include <edhoc.h>
12
13 #include "edhoc_test_vectors_p256_v15.h"
14 #include "latency.h"
15
16 uint8_t I_prk_exporter_buf[32];
17 struct byte_array I_prk_exporter = { .ptr = I_prk_exporter_buf,
18 .len = sizeof(I_prk_exporter_buf) };
19
20 uint8_t I_master_secret_buf[16];
21 struct byte_array I_master_secret = { .ptr = I_master_secret_buf,
22 .len = sizeof(I_master_secret_buf) };
23
24 uint8_t I_master_salt_buf[8];
25 struct byte_array I_master_salt = { .ptr = I_master_salt_buf,
26 .len = sizeof(I_master_salt_buf) };
27
28 uint8_t I_PRK_out_buf[32];
29 struct byte_array I_PRK_out = { .ptr = I_PRK_out_buf,
30 .len = sizeof(I_PRK_out_buf) };
31
32 uint8_t I_err_msg_buf[0];
33 struct byte_array I_err_msg = { .ptr = I_err_msg_buf,
34 .len = sizeof(I_err_msg_buf) };
35 /******************************************************************************/
36
37 uint8_t R_prk_exporter_buf[32];
38 struct byte_array R_prk_exporter = { .ptr = R_prk_exporter_buf,
39 .len = sizeof(R_prk_exporter_buf) };
40
41 uint8_t R_master_secret_buf[16];
42 struct byte_array R_master_secret = { .ptr = R_master_secret_buf,
43 .len = sizeof(R_master_secret_buf) };
44
45 uint8_t R_master_salt_buf[8];
46 struct byte_array R_master_salt = { .ptr = R_master_salt_buf,
47 .len = sizeof(R_master_salt_buf) };
48
49 uint8_t R_PRK_out_buf[32];
50 struct byte_array R_PRK_out = { .ptr = R_PRK_out_buf,
51 .len = sizeof(R_PRK_out_buf) };
52
53 uint8_t R_err_msg_buf[0];
54 struct byte_array R_err_msg = { .ptr = R_err_msg_buf,
55 .len = sizeof(R_err_msg_buf) };
56
57 /* size of stack area used by each thread */
58 #define STACKSIZE 7500
59 /* scheduling priority used by each thread */
60 #define PRIORITY 7
61 K_THREAD_STACK_DEFINE(thread_initiator_stack_area, STACKSIZE);
62 static struct k_thread thread_initiator_data;
63 K_THREAD_STACK_DEFINE(thread_responder_stack_area, STACKSIZE);
64 static struct k_thread thread_responder_data;
65
66 /*semaphores*/
67 K_SEM_DEFINE(tx_initiator_completed, 0, 1);
68 K_SEM_DEFINE(tx_responder_completed, 0, 1);
69
70 /*message exchange buffer*/
71 uint8_t msg_exchange_buf[1024];
72 uint32_t msg_exchange_buf_len = sizeof(msg_exchange_buf);
73
semaphore_give(struct k_sem * sem)74 void semaphore_give(struct k_sem *sem)
75 {
76 k_sem_give(sem);
77 }
78
semaphore_take(struct k_sem * sem,uint8_t * data,uint32_t * data_len)79 enum err semaphore_take(struct k_sem *sem, uint8_t *data, uint32_t *data_len)
80 {
81 if (k_sem_take(sem, K_FOREVER) != 0) {
82 PRINT_MSG("Cannot receive a message!\n");
83 } else {
84 if (msg_exchange_buf_len > *data_len) {
85 return buffer_to_small;
86 } else {
87 memcpy(data, msg_exchange_buf, *data_len);
88 *data_len = msg_exchange_buf_len;
89 }
90 }
91 return ok;
92 }
93
copy_message(uint8_t * data,uint32_t data_len)94 enum err copy_message(uint8_t *data, uint32_t data_len)
95 {
96 if (data_len > sizeof(msg_exchange_buf)) {
97 PRINT_MSG("msg_exchange_buf to small\n");
98 return buffer_to_small;
99 } else {
100 memcpy(msg_exchange_buf, data, data_len);
101 msg_exchange_buf_len = data_len;
102 }
103 return ok;
104 }
105
tx_initiator(void * sock,struct byte_array * data)106 enum err tx_initiator(void *sock, struct byte_array *data)
107 {
108 enum err r = copy_message(data->ptr, data->len);
109 if (r != ok) {
110 return r;
111 }
112 semaphore_give(&tx_initiator_completed);
113 return ok;
114 }
115
tx_responder(void * sock,struct byte_array * data)116 enum err tx_responder(void *sock, struct byte_array *data)
117 {
118 //PRINTF("tx_responder data len: %d\n", data->len);
119 enum err r = copy_message(data->ptr, data->len);
120 if (r != ok) {
121 return r;
122 }
123 //PRINTF("msg_exchange_buf_len: %d\n",msg_exchange_buf_len);
124 semaphore_give(&tx_responder_completed);
125 return ok;
126 }
127
rx_initiator(void * sock,struct byte_array * data)128 enum err rx_initiator(void *sock, struct byte_array *data)
129 {
130 PRINTF("msg_exchange_buf_len: %d\n", msg_exchange_buf_len);
131 return semaphore_take(&tx_responder_completed, data->ptr, &data->len);
132 }
rx_responder(void * sock,struct byte_array * data)133 enum err rx_responder(void *sock, struct byte_array *data)
134 {
135 return semaphore_take(&tx_initiator_completed, data->ptr, &data->len);
136 }
ead_process(void * params,struct byte_array * ead13)137 enum err ead_process(void *params, struct byte_array *ead13)
138 {
139 return ok;
140 }
141
142 /**
143 * @brief A thread in which an Initiator instance is executed
144 *
145 * @param vec_num Test vector number
146 * @param dummy2 unused
147 * @param dummy3 unused
148 */
thread_initiator(void * vec_num,void * dummy2,void * dummy3)149 void thread_initiator(void *vec_num, void *dummy2, void *dummy3)
150 {
151 ARG_UNUSED(dummy2);
152 ARG_UNUSED(dummy3);
153
154 PRINT_MSG("Initiator thread started!\n");
155 int vec_num_i = *((int *)vec_num) - 1;
156
157 enum err r;
158
159 struct other_party_cred cred_r;
160 struct edhoc_initiator_context c_i;
161
162 c_i.sock = NULL;
163 c_i.c_i.len = test_vectors[vec_num_i].c_i_len;
164 c_i.c_i.ptr = (uint8_t *)test_vectors[vec_num_i].c_i;
165 c_i.method = (enum method_type) * test_vectors[vec_num_i].method;
166 c_i.suites_i.len = test_vectors[vec_num_i].SUITES_I_len;
167 c_i.suites_i.ptr = (uint8_t *)test_vectors[vec_num_i].SUITES_I;
168 c_i.ead_1.len = test_vectors[vec_num_i].ead_1_len;
169 c_i.ead_1.ptr = (uint8_t *)test_vectors[vec_num_i].ead_1;
170 c_i.ead_3.len = test_vectors[vec_num_i].ead_3_len;
171 c_i.ead_3.ptr = (uint8_t *)test_vectors[vec_num_i].ead_3;
172 c_i.id_cred_i.len = test_vectors[vec_num_i].id_cred_i_len;
173 c_i.id_cred_i.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_i;
174 c_i.cred_i.len = test_vectors[vec_num_i].cred_i_len;
175 c_i.cred_i.ptr = (uint8_t *)test_vectors[vec_num_i].cred_i;
176 c_i.g_x.len = test_vectors[vec_num_i].g_x_raw_len;
177 c_i.g_x.ptr = (uint8_t *)test_vectors[vec_num_i].g_x_raw;
178 c_i.x.len = test_vectors[vec_num_i].x_raw_len;
179 c_i.x.ptr = (uint8_t *)test_vectors[vec_num_i].x_raw;
180 c_i.g_i.len = test_vectors[vec_num_i].g_i_raw_len;
181 c_i.g_i.ptr = (uint8_t *)test_vectors[vec_num_i].g_i_raw;
182 c_i.i.len = test_vectors[vec_num_i].i_raw_len;
183 c_i.i.ptr = (uint8_t *)test_vectors[vec_num_i].i_raw;
184 c_i.sk_i.len = test_vectors[vec_num_i].sk_i_raw_len;
185 c_i.sk_i.ptr = (uint8_t *)test_vectors[vec_num_i].sk_i_raw;
186 c_i.pk_i.len = test_vectors[vec_num_i].pk_i_raw_len;
187 c_i.pk_i.ptr = (uint8_t *)test_vectors[vec_num_i].pk_i_raw;
188
189 cred_r.id_cred.len = test_vectors[vec_num_i].id_cred_r_len;
190 cred_r.id_cred.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_r;
191 cred_r.cred.len = test_vectors[vec_num_i].cred_r_len;
192 cred_r.cred.ptr = (uint8_t *)test_vectors[vec_num_i].cred_r;
193 cred_r.g.len = test_vectors[vec_num_i].g_r_raw_len;
194 cred_r.g.ptr = (uint8_t *)test_vectors[vec_num_i].g_r_raw;
195 cred_r.pk.len = test_vectors[vec_num_i].pk_r_raw_len;
196 cred_r.pk.ptr = (uint8_t *)test_vectors[vec_num_i].pk_r_raw;
197 cred_r.ca.len = test_vectors[vec_num_i].ca_r_len;
198 cred_r.ca.ptr = (uint8_t *)test_vectors[vec_num_i].ca_r;
199 cred_r.ca_pk.len = test_vectors[vec_num_i].ca_r_pk_len;
200 cred_r.ca_pk.ptr = (uint8_t *)test_vectors[vec_num_i].ca_r_pk;
201
202 struct cred_array cred_r_array = { .len = 1, .ptr = &cred_r };
203
204 r = edhoc_initiator_run(&c_i, &cred_r_array, &I_err_msg, &I_PRK_out,
205 tx_initiator, rx_initiator, ead_process);
206 if (r != ok) {
207 goto end;
208 }
209
210 PRINT_ARRAY("I_PRK_out", I_PRK_out.ptr, I_PRK_out.len);
211
212 r = prk_out2exporter(SHA_256, &I_PRK_out, &I_prk_exporter);
213 if (r != ok) {
214 goto end;
215 }
216 PRINT_ARRAY("I_prk_exporter", I_prk_exporter.ptr, I_prk_exporter.len);
217
218 r = edhoc_exporter(SHA_256, OSCORE_MASTER_SECRET, &I_prk_exporter,
219 &I_master_secret);
220 if (r != ok) {
221 goto end;
222 }
223 PRINT_ARRAY("OSCORE Master Secret", I_master_secret.ptr,
224 I_master_secret.len);
225
226 r = edhoc_exporter(SHA_256, OSCORE_MASTER_SALT, &I_prk_exporter,
227 &I_master_salt);
228 if (r != ok) {
229 goto end;
230 }
231 PRINT_ARRAY("OSCORE Master Salt", I_master_salt.ptr, I_master_salt.len);
232
233 #ifdef REPORT_STACK_USAGE
234 thread_analyzer_print();
235 #endif
236
237 return;
238 end:
239 PRINTF("An error has occurred. Error code: %d\n", r);
240 }
241
242 /**
243 * @brief A thread in which a Responder instance is executed
244 *
245 * @param vec_num Test vector number
246 * @param dummy2 unused
247 * @param dummy3 unused
248 */
thread_responder(void * vec_num,void * dummy2,void * dummy3)249 void thread_responder(void *vec_num, void *dummy2, void *dummy3)
250 {
251 ARG_UNUSED(dummy2);
252 ARG_UNUSED(dummy3);
253
254 PRINT_MSG("Responder thread started!\n");
255 enum err r;
256 int vec_num_i = *((int *)vec_num) - 1;
257
258 /* test vector inputs */
259 struct other_party_cred cred_i;
260 struct edhoc_responder_context c_r;
261
262 c_r.sock = NULL;
263 c_r.c_r.ptr = (uint8_t *)test_vectors[vec_num_i].c_r;
264 c_r.c_r.len = test_vectors[vec_num_i].c_r_len;
265 c_r.suites_r.len = test_vectors[vec_num_i].SUITES_R_len;
266 c_r.suites_r.ptr = (uint8_t *)test_vectors[vec_num_i].SUITES_R;
267 c_r.ead_2.len = test_vectors[vec_num_i].ead_2_len;
268 c_r.ead_2.ptr = (uint8_t *)test_vectors[vec_num_i].ead_2;
269 c_r.ead_4.len = test_vectors[vec_num_i].ead_4_len;
270 c_r.ead_4.ptr = (uint8_t *)test_vectors[vec_num_i].ead_4;
271 c_r.id_cred_r.len = test_vectors[vec_num_i].id_cred_r_len;
272 c_r.id_cred_r.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_r;
273 c_r.cred_r.len = test_vectors[vec_num_i].cred_r_len;
274 c_r.cred_r.ptr = (uint8_t *)test_vectors[vec_num_i].cred_r;
275 c_r.g_y.len = test_vectors[vec_num_i].g_y_raw_len;
276 c_r.g_y.ptr = (uint8_t *)test_vectors[vec_num_i].g_y_raw;
277 c_r.y.len = test_vectors[vec_num_i].y_raw_len;
278 c_r.y.ptr = (uint8_t *)test_vectors[vec_num_i].y_raw;
279 c_r.g_r.len = test_vectors[vec_num_i].g_r_raw_len;
280 c_r.g_r.ptr = (uint8_t *)test_vectors[vec_num_i].g_r_raw;
281 c_r.r.len = test_vectors[vec_num_i].r_raw_len;
282 c_r.r.ptr = (uint8_t *)test_vectors[vec_num_i].r_raw;
283 c_r.sk_r.len = test_vectors[vec_num_i].sk_r_raw_len;
284 c_r.sk_r.ptr = (uint8_t *)test_vectors[vec_num_i].sk_r_raw;
285 c_r.pk_r.len = test_vectors[vec_num_i].pk_r_raw_len;
286 c_r.pk_r.ptr = (uint8_t *)test_vectors[vec_num_i].pk_r_raw;
287
288 cred_i.id_cred.len = test_vectors[vec_num_i].id_cred_i_len;
289 cred_i.id_cred.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_i;
290 cred_i.cred.len = test_vectors[vec_num_i].cred_i_len;
291 cred_i.cred.ptr = (uint8_t *)test_vectors[vec_num_i].cred_i;
292 cred_i.g.len = test_vectors[vec_num_i].g_i_raw_len;
293 cred_i.g.ptr = (uint8_t *)test_vectors[vec_num_i].g_i_raw;
294 cred_i.pk.len = test_vectors[vec_num_i].pk_i_raw_len;
295 cred_i.pk.ptr = (uint8_t *)test_vectors[vec_num_i].pk_i_raw;
296 cred_i.ca.len = test_vectors[vec_num_i].ca_i_len;
297 cred_i.ca.ptr = (uint8_t *)test_vectors[vec_num_i].ca_i;
298 cred_i.ca_pk.len = test_vectors[vec_num_i].ca_i_pk_len;
299 cred_i.ca_pk.ptr = (uint8_t *)test_vectors[vec_num_i].ca_i_pk;
300
301 struct cred_array cred_i_array = { .len = 1, .ptr = &cred_i };
302 r = edhoc_responder_run(&c_r, &cred_i_array, &R_err_msg, &R_PRK_out,
303 tx_responder, rx_responder, ead_process);
304 if (r != ok) {
305 goto end;
306 }
307
308 PRINT_ARRAY("R_PRK_out", R_PRK_out.ptr, R_PRK_out.len);
309
310 r = prk_out2exporter(SHA_256, &R_PRK_out, &R_prk_exporter);
311 if (r != ok) {
312 goto end;
313 }
314 PRINT_ARRAY("R_prk_exporter", R_prk_exporter.ptr, R_prk_exporter.len);
315
316 r = edhoc_exporter(SHA_256, OSCORE_MASTER_SECRET, &R_prk_exporter,
317 &R_master_secret);
318 if (r != ok) {
319 goto end;
320 }
321 PRINT_ARRAY("OSCORE Master Secret", R_master_secret.ptr,
322 R_master_secret.len);
323
324 r = edhoc_exporter(SHA_256, OSCORE_MASTER_SALT, &R_prk_exporter,
325 &R_master_salt);
326 if (r != ok) {
327 goto end;
328 }
329 PRINT_ARRAY("OSCORE Master Salt", R_master_salt.ptr, R_master_salt.len);
330
331 #ifdef REPORT_STACK_USAGE
332 thread_analyzer_print();
333 #endif
334
335 return;
336 end:
337 PRINTF("An error has occurred. Error code: %d\n", r);
338 }
339
test_initiator_responder_interaction(int vec_num)340 int test_initiator_responder_interaction(int vec_num)
341 {
342 PRINT_MSG("start initiator_responder_interaction\n");
343
344 /*initiator thread*/
345 k_tid_t initiator_tid = k_thread_create(
346 &thread_initiator_data, thread_initiator_stack_area,
347 K_THREAD_STACK_SIZEOF(thread_initiator_stack_area),
348 thread_initiator, (void *)&vec_num, NULL, NULL, PRIORITY, 0,
349 K_NO_WAIT);
350
351 /*responder thread*/
352 k_tid_t responder_tid = k_thread_create(
353 &thread_responder_data, thread_responder_stack_area,
354 K_THREAD_STACK_SIZEOF(thread_responder_stack_area),
355 thread_responder, (void *)&vec_num, NULL, NULL, PRIORITY, 0,
356 K_NO_WAIT);
357
358 k_thread_start(&thread_initiator_data);
359 k_thread_start(&thread_responder_data);
360
361 if (0 != k_thread_join(&thread_initiator_data, K_FOREVER)) {
362 PRINT_MSG("initiator thread stalled! Aborting.");
363 k_thread_abort(initiator_tid);
364 }
365 if (0 != k_thread_join(&thread_responder_data, K_FOREVER)) {
366 PRINT_MSG("responder thread stalled! Aborting.");
367 k_thread_abort(responder_tid);
368 }
369
370 PRINT_MSG("threads completed\n");
371
372 /* check if Initiator and Responder computed the same values */
373
374 zassert_mem_equal__(I_PRK_out.ptr, R_PRK_out.ptr, R_PRK_out.len,
375 "wrong prk_out");
376
377 zassert_mem_equal__(I_prk_exporter.ptr, R_prk_exporter.ptr,
378 R_prk_exporter.len, "wrong prk_exporter");
379
380 zassert_mem_equal__(I_master_secret.ptr, R_master_secret.ptr,
381 R_master_secret.len, "wrong master_secret");
382
383 zassert_mem_equal__(I_master_salt.ptr, R_master_salt.ptr,
384 R_master_salt.len, "wrong master_salt");
385 return 0;
386 }
387
t_initiator_responder_interaction1()388 void t_initiator_responder_interaction1()
389 {
390 MEASURE_LATENCY(test_initiator_responder_interaction(1));
391 }
392
t_initiator_responder_interaction2()393 void t_initiator_responder_interaction2()
394 {
395 MEASURE_LATENCY(test_initiator_responder_interaction(2));
396 }