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 }