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 <stdio.h>
13 #include <zephyr/net/coap.h>
14
15 #include "edhoc.h"
16 #include "sock.h"
17 #include "edhoc_test_vectors_p256_v16.h"
18
19 #define URI_PATH 11
20
21 /**
22 * @brief Initializes sockets for CoAP client.
23 * @param
24 * @retval error code
25 */
start_coap_client(int * sockfd)26 static int start_coap_client(int *sockfd)
27 {
28 struct sockaddr_in6 servaddr;
29 //const char IPV6_SERVADDR[] = { "::1" };
30 const char IPV6_SERVADDR[] = { "2001:db8::2" };
31 int r = ipv6_sock_init(SOCK_CLIENT, IPV6_SERVADDR, &servaddr,
32 sizeof(servaddr), sockfd);
33 if (r < 0) {
34 printf("error during socket initialization (error code: %d)",
35 r);
36 return -1;
37 }
38 return 0;
39 }
40
ead_process(void * params,struct byte_array * ead13)41 enum err ead_process(void *params, struct byte_array *ead13)
42 {
43 /*for this sample we are not using EAD*/
44 /*to save RAM we use FEATURES += -DEAD_SIZE=0*/
45 return ok;
46 }
47
48 /**
49 * @brief Callback function called inside the frontend when data needs to
50 * be send over the network. We use here CoAP as transport
51 * @param data pointer to the data that needs to be send
52 */
tx(void * sock,struct byte_array * data)53 enum err tx(void *sock, struct byte_array *data)
54 {
55 /* Initialize the CoAP message */
56 char *path = ".well-known/edhoc";
57 struct coap_packet request;
58 uint8_t _data[1000];
59
60 TRY_EXPECT(coap_packet_init(&request, _data, sizeof(_data), 1,
61 COAP_TYPE_CON, 8, coap_next_token(),
62 COAP_METHOD_POST, coap_next_id()),
63 0);
64
65 /* Append options */
66 TRY_EXPECT(coap_packet_append_option(&request, URI_PATH, path,
67 strlen(path)),
68 0);
69
70 /* Append Payload marker if you are going to add payload */
71 TRY_EXPECT(coap_packet_append_payload_marker(&request), 0);
72
73 /* Append payload */
74 TRY_EXPECT(coap_packet_append_payload(&request, data->ptr, data->len),
75 0);
76
77 PRINT_ARRAY("CoAP packet", request.data, request.offset);
78 ssize_t n = send(*((int *)sock), request.data, request.offset, 0);
79 if (n < 0) {
80 printf("send failed with error code: %d\n", n);
81 } else {
82 printf("%d bytes sent\n", n);
83 }
84
85 return ok;
86 }
87
88 /**
89 * @brief Callback function called inside the frontend when data needs to
90 * be received over the network. We use here CoAP as transport
91 * @param data pointer to the data that needs to be received
92 */
rx(void * sock,struct byte_array * data)93 enum err rx(void *sock, struct byte_array *data)
94 {
95 int n;
96 char buffer[MAXLINE];
97 struct coap_packet reply;
98 const uint8_t *edhoc_data_p;
99 uint16_t edhoc_data_len;
100
101 /* receive */
102 n = recv(*((int *)sock), (char *)buffer, MAXLINE, MSG_WAITALL);
103 if (n < 0) {
104 printf("recv error");
105 }
106
107 PRINT_ARRAY("received data", buffer, n);
108
109 TRY_EXPECT(coap_packet_parse(&reply, buffer, n, NULL, 0), 0);
110
111 edhoc_data_p = coap_packet_get_payload(&reply, &edhoc_data_len);
112
113 PRINT_ARRAY("received EDHOC data", edhoc_data_p, edhoc_data_len);
114
115 if (data->len >= edhoc_data_len) {
116 memcpy(data->ptr, edhoc_data_p, edhoc_data_len);
117 data->len = edhoc_data_len;
118 } else {
119 printf("insufficient space in buffer");
120 return buffer_to_small;
121 }
122 return ok;
123 }
124
internal_main(void)125 int internal_main(void)
126 {
127 int32_t s = 5000;
128 printf("sleep for %d msecond after connection in order to have time to start wireshark on bt0\n",
129 s);
130 k_msleep(s);
131
132 int sockfd;
133 BYTE_ARRAY_NEW(prk_exporter, 32, 32);
134 BYTE_ARRAY_NEW(oscore_master_secret, 16, 16);
135 BYTE_ARRAY_NEW(oscore_master_salt, 8, 8);
136 BYTE_ARRAY_NEW(PRK_out, 32, 32);
137 BYTE_ARRAY_NEW(err_msg, 0, 0);
138
139 /* test vector inputs */
140 struct other_party_cred cred_r;
141 struct edhoc_initiator_context c_i;
142
143 const uint8_t TEST_VEC_NUM = 2;
144 uint8_t vec_num_i = TEST_VEC_NUM - 1;
145
146 c_i.sock = &sockfd;
147 c_i.c_i.len = test_vectors[vec_num_i].c_i_len;
148 c_i.c_i.ptr = (uint8_t *)test_vectors[vec_num_i].c_i;
149 c_i.method = (enum method_type) * test_vectors[vec_num_i].method;
150 c_i.suites_i.len = test_vectors[vec_num_i].SUITES_I_len;
151 c_i.suites_i.ptr = (uint8_t *)test_vectors[vec_num_i].SUITES_I;
152 c_i.ead_1.len = test_vectors[vec_num_i].ead_1_len;
153 c_i.ead_1.ptr = (uint8_t *)test_vectors[vec_num_i].ead_1;
154 c_i.ead_3.len = test_vectors[vec_num_i].ead_3_len;
155 c_i.ead_3.ptr = (uint8_t *)test_vectors[vec_num_i].ead_3;
156 c_i.id_cred_i.len = test_vectors[vec_num_i].id_cred_i_len;
157 c_i.id_cred_i.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_i;
158 c_i.cred_i.len = test_vectors[vec_num_i].cred_i_len;
159 c_i.cred_i.ptr = (uint8_t *)test_vectors[vec_num_i].cred_i;
160 c_i.g_x.len = test_vectors[vec_num_i].g_x_raw_len;
161 c_i.g_x.ptr = (uint8_t *)test_vectors[vec_num_i].g_x_raw;
162 c_i.x.len = test_vectors[vec_num_i].x_raw_len;
163 c_i.x.ptr = (uint8_t *)test_vectors[vec_num_i].x_raw;
164 c_i.g_i.len = test_vectors[vec_num_i].g_i_raw_len;
165 c_i.g_i.ptr = (uint8_t *)test_vectors[vec_num_i].g_i_raw;
166 c_i.i.len = test_vectors[vec_num_i].i_raw_len;
167 c_i.i.ptr = (uint8_t *)test_vectors[vec_num_i].i_raw;
168 c_i.sk_i.len = test_vectors[vec_num_i].sk_i_raw_len;
169 c_i.sk_i.ptr = (uint8_t *)test_vectors[vec_num_i].sk_i_raw;
170 c_i.pk_i.len = test_vectors[vec_num_i].pk_i_raw_len;
171 c_i.pk_i.ptr = (uint8_t *)test_vectors[vec_num_i].pk_i_raw;
172
173 cred_r.id_cred.len = test_vectors[vec_num_i].id_cred_r_len;
174 cred_r.id_cred.ptr = (uint8_t *)test_vectors[vec_num_i].id_cred_r;
175 cred_r.cred.len = test_vectors[vec_num_i].cred_r_len;
176 cred_r.cred.ptr = (uint8_t *)test_vectors[vec_num_i].cred_r;
177 cred_r.g.len = test_vectors[vec_num_i].g_r_raw_len;
178 cred_r.g.ptr = (uint8_t *)test_vectors[vec_num_i].g_r_raw;
179 cred_r.pk.len = test_vectors[vec_num_i].pk_r_raw_len;
180 cred_r.pk.ptr = (uint8_t *)test_vectors[vec_num_i].pk_r_raw;
181 cred_r.ca.len = test_vectors[vec_num_i].ca_r_len;
182 cred_r.ca.ptr = (uint8_t *)test_vectors[vec_num_i].ca_r;
183 cred_r.ca_pk.len = test_vectors[vec_num_i].ca_r_pk_len;
184 cred_r.ca_pk.ptr = (uint8_t *)test_vectors[vec_num_i].ca_r_pk;
185
186 struct cred_array cred_r_array = { .len = 1, .ptr = &cred_r };
187
188 start_coap_client(&sockfd);
189 edhoc_initiator_run(&c_i, &cred_r_array, &err_msg, &PRK_out, tx, rx,
190 ead_process);
191
192 PRINT_ARRAY("PRK_out", PRK_out.ptr, PRK_out.len);
193
194 prk_out2exporter(SHA_256, &PRK_out, &prk_exporter);
195 PRINT_ARRAY("prk_exporter", prk_exporter.ptr, prk_exporter.len);
196
197 edhoc_exporter(SHA_256, OSCORE_MASTER_SECRET, &prk_exporter,
198 &oscore_master_secret);
199 PRINT_ARRAY("OSCORE Master Secret", oscore_master_secret.ptr,
200 oscore_master_secret.len);
201
202 edhoc_exporter(SHA_256, OSCORE_MASTER_SALT, &prk_exporter,
203 &oscore_master_salt);
204 PRINT_ARRAY("OSCORE Master Salt", oscore_master_salt.ptr,
205 oscore_master_salt.len);
206
207 close(sockfd);
208 return 0;
209 }
210
main(void)211 void main(void)
212 {
213 int r = internal_main();
214 if (r != 0) {
215 printf("error during initiator run. Error code: %d\n", r);
216 }
217 }