1 /*
2 * Copyright (c) 2020 Friedt Professional Engineering Services, Inc
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <logging/log.h>
8 #include <net/net_core.h>
9 #include <net/net_ip.h>
10 #include <net/socket.h>
11 #include <net/tls_credentials.h>
12 #include <posix/unistd.h>
13 #include <sys/util.h>
14 #include <ztest.h>
15
16 LOG_MODULE_REGISTER(tls_test, CONFIG_NET_SOCKETS_LOG_LEVEL);
17
18 /**
19 * @brief An encrypted message to pass between server and client.
20 *
21 * The answer to life, the universe, and everything.
22 *
23 * See also <a href="https://en.wikipedia.org/wiki/42_(number)#The_Hitchhiker's_Guide_to_the_Galaxy">42</a>.
24 */
25 #define SECRET "forty-two"
26
27 /**
28 * @brief Size of the encrypted message passed between server and client.
29 */
30 #define SECRET_SIZE (sizeof(SECRET) - 1)
31
32 /** @brief Stack size for the server thread */
33 #define STACK_SIZE 8192
34
35 /** @brief TCP port for the server thread */
36 #define PORT 4242
37
38 /** @brief arbitrary timeout value in ms */
39 #define TIMEOUT 1000
40
41 /**
42 * @brief Application-dependent TLS credential identifiers
43 *
44 * Since both the server and client exist in the same test
45 * application in this case, both the server and client credendtials
46 * are loaded together.
47 *
48 * The server would normally need
49 * - SERVER_CERTIFICATE_TAG (for both public and private keys)
50 * - CA_CERTIFICATE_TAG (only when client authentication is required)
51 *
52 * The client would normally load
53 * - CA_CERTIFICATE_TAG (always required, to verify the server)
54 * - CLIENT_CERTIFICATE_TAG (for both public and private keys, only when
55 * client authentication is required)
56 */
57 enum tls_tag {
58 /** The Certificate Authority public key */
59 CA_CERTIFICATE_TAG,
60 /** Used for both the public and private server keys */
61 SERVER_CERTIFICATE_TAG,
62 /** Used for both the public and private client keys */
63 CLIENT_CERTIFICATE_TAG,
64 };
65
66 /** @brief synchronization object for server & client threads */
67 static struct k_sem server_sem;
68
69 /** @brief The server thread stack */
70 static K_THREAD_STACK_DEFINE(server_stack, STACK_SIZE);
71 /** @brief the server thread object */
72 static struct k_thread server_thread;
73
74 #ifdef CONFIG_TLS_CREDENTIALS
75 /**
76 * @brief The Certificate Authority (CA) Certificate
77 *
78 * The client needs the CA cert to verify the server public key. TLS client
79 * sockets are always required to verify the server public key.
80 *
81 * Additionally, when the peer verification mode is
82 * @ref TLS_PEER_VERIFY_OPTIONAL or @ref TLS_PEER_VERIFY_REQUIRED, then
83 * the server also needs the CA cert in order to verify the client. This
84 * type of configuration is often referred to as *mutual authentication*.
85 */
86 static const unsigned char ca[] = {
87 #include "ca.inc"
88 };
89
90 /**
91 * @brief The Server Certificate
92 *
93 * This is the public key of the server.
94 */
95 static const unsigned char server[] = {
96 #include "server.inc"
97 };
98
99 /**
100 * @brief The Server Private Key
101 *
102 * This is the private key of the server.
103 */
104 static const unsigned char server_privkey[] = {
105 #include "server_privkey.inc"
106 };
107
108 /**
109 * @brief The Client Certificate
110 *
111 * This is the public key of the client.
112 */
113 static const unsigned char client[] = {
114 #include "client.inc"
115 };
116
117 /**
118 * @brief The Client Private Key
119 *
120 * This is the private key of the client.
121 */
122 static const unsigned char client_privkey[] = {
123 #include "client_privkey.inc"
124 };
125 #else /* CONFIG_TLS_CREDENTIALS */
126 #define ca NULL
127 #define server NULL
128 #define server_privkey NULL
129 #define client NULL
130 #define client_privkey NULL
131 #endif /* CONFIG_TLS_CREDENTIALS */
132
133 /**
134 * @brief The server thread function
135 *
136 * This function simply accepts a client connection and
137 * echoes the first @ref SECRET_SIZE bytes of the first
138 * packet. After that, the server is closed and connections
139 * are no longer accepted.
140 *
141 * @param arg0 a pointer to the int representing the server file descriptor
142 * @param arg1 ignored
143 * @param arg2 ignored
144 */
server_thread_fn(void * arg0,void * arg1,void * arg2)145 static void server_thread_fn(void *arg0, void *arg1, void *arg2)
146 {
147 const int server_fd = POINTER_TO_INT(arg0);
148
149 int r;
150 int client_fd;
151 socklen_t addrlen;
152 char addrstr[INET_ADDRSTRLEN];
153 struct sockaddr_in sa;
154 char *addrstrp;
155
156 k_thread_name_set(k_current_get(), "server");
157
158 NET_DBG("Server thread running");
159
160 memset(&sa, 0, sizeof(sa));
161 addrlen = sizeof(sa);
162
163 NET_DBG("Accepting client connection..");
164 k_sem_give(&server_sem);
165 r = accept(server_fd, (struct sockaddr *)&sa, &addrlen);
166 zassert_not_equal(r, -1, "accept() failed (%d)", r);
167 client_fd = r;
168
169 memset(addrstr, '\0', sizeof(addrstr));
170 addrstrp = (char *)inet_ntop(AF_INET, &sa.sin_addr,
171 addrstr, sizeof(addrstr));
172 zassert_not_equal(addrstrp, NULL, "inet_ntop() failed (%d)", errno);
173
174 NET_DBG("accepted connection from [%s]:%d as fd %d",
175 log_strdup(addrstr), ntohs(sa.sin_port), client_fd);
176
177 NET_DBG("calling recv()");
178 r = recv(client_fd, addrstr, sizeof(addrstr), 0);
179 zassert_not_equal(r, -1, "recv() failed (%d)", errno);
180 zassert_equal(r, SECRET_SIZE, "expected: %zu actual: %d", SECRET_SIZE, r);
181
182 NET_DBG("calling send()");
183 r = send(client_fd, SECRET, SECRET_SIZE, 0);
184 zassert_not_equal(r, -1, "send() failed (%d)", errno);
185 zassert_equal(r, SECRET_SIZE, "expected: %zu actual: %d", SECRET_SIZE, r);
186
187 NET_DBG("closing client fd");
188 r = close(client_fd);
189 zassert_not_equal(r, -1, "close() failed on the server fd (%d)", errno);
190 }
191
test_common(int peer_verify)192 static void test_common(int peer_verify)
193 {
194 const int yes = true;
195
196 int r;
197 int server_fd;
198 int client_fd;
199 int proto = IPPROTO_TCP;
200 char *addrstrp;
201 k_tid_t server_thread_id;
202 struct sockaddr_in sa;
203 char addrstr[INET_ADDRSTRLEN];
204
205 k_sem_init(&server_sem, 0, 1);
206
207 /* set the common protocol for both client and server */
208 if (IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
209 proto = IPPROTO_TLS_1_2;
210 }
211 /*
212 * Server socket setup
213 */
214
215 NET_DBG("Creating server socket");
216 r = socket(AF_INET, SOCK_STREAM, proto);
217 zassert_not_equal(r, -1, "failed to create server socket (%d)", errno);
218 server_fd = r;
219
220 r = setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes));
221 zassert_not_equal(r, -1, "failed to set SO_REUSEADDR (%d)", errno);
222
223 if (IS_ENABLED(CONFIG_TLS_CREDENTIALS)
224 && IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
225
226 static const sec_tag_t server_tag_list_verify_none[] = {
227 SERVER_CERTIFICATE_TAG,
228 };
229
230 static const sec_tag_t server_tag_list_verify[] = {
231 CA_CERTIFICATE_TAG,
232 SERVER_CERTIFICATE_TAG,
233 };
234
235 const sec_tag_t *sec_tag_list;
236 size_t sec_tag_list_size;
237
238 switch (peer_verify) {
239 case TLS_PEER_VERIFY_NONE:
240 sec_tag_list = server_tag_list_verify_none;
241 sec_tag_list_size = sizeof(server_tag_list_verify_none);
242 break;
243 case TLS_PEER_VERIFY_OPTIONAL:
244 case TLS_PEER_VERIFY_REQUIRED:
245 sec_tag_list = server_tag_list_verify;
246 sec_tag_list_size = sizeof(server_tag_list_verify);
247
248 r = setsockopt(server_fd, SOL_TLS, TLS_PEER_VERIFY,
249 &peer_verify, sizeof(peer_verify));
250 zassert_not_equal(r, -1,
251 "failed to set TLS_PEER_VERIFY (%d)", errno);
252 break;
253 default:
254 zassert_true(false,
255 "unrecognized TLS peer verify type %d",
256 peer_verify);
257 return;
258 }
259
260 r = setsockopt(server_fd, SOL_TLS, TLS_SEC_TAG_LIST,
261 sec_tag_list, sec_tag_list_size);
262 zassert_not_equal(r, -1, "failed to set TLS_SEC_TAG_LIST (%d)",
263 errno);
264
265 r = setsockopt(server_fd, SOL_TLS, TLS_HOSTNAME, "localhost",
266 sizeof("localhost"));
267 zassert_not_equal(r, -1, "failed to set TLS_HOSTNAME (%d)",
268 errno);
269 }
270
271 memset(&sa, 0, sizeof(sa));
272 /* The server listens on all network interfaces */
273 sa.sin_addr.s_addr = INADDR_ANY;
274 sa.sin_family = AF_INET;
275 sa.sin_port = htons(PORT);
276
277 r = bind(server_fd, (struct sockaddr *)&sa, sizeof(sa));
278 zassert_not_equal(r, -1, "failed to bind (%d)", errno);
279
280 r = listen(server_fd, 1);
281 zassert_not_equal(r, -1, "failed to listen (%d)", errno);
282
283 memset(addrstr, '\0', sizeof(addrstr));
284 addrstrp = (char *)inet_ntop(AF_INET, &sa.sin_addr,
285 addrstr, sizeof(addrstr));
286 zassert_not_equal(addrstrp, NULL, "inet_ntop() failed (%d)", errno);
287
288 NET_DBG("listening on [%s]:%d as fd %d",
289 log_strdup(addrstr), ntohs(sa.sin_port), server_fd);
290
291 NET_DBG("Creating server thread");
292 server_thread_id = k_thread_create(&server_thread, server_stack,
293 STACK_SIZE, server_thread_fn,
294 INT_TO_POINTER(server_fd), NULL, NULL,
295 K_PRIO_PREEMPT(8), 0, K_NO_WAIT);
296
297 r = k_sem_take(&server_sem, K_MSEC(TIMEOUT));
298 zassert_equal(0, r, "failed to synchronize with server thread (%d)", r);
299
300 /*
301 * Client socket setup
302 */
303
304 k_thread_name_set(k_current_get(), "client");
305
306 NET_DBG("Creating client socket");
307 r = socket(AF_INET, SOCK_STREAM, proto);
308 zassert_not_equal(r, -1, "failed to create client socket (%d)", errno);
309 client_fd = r;
310
311 if (IS_ENABLED(CONFIG_TLS_CREDENTIALS)
312 && IS_ENABLED(CONFIG_NET_SOCKETS_SOCKOPT_TLS)) {
313
314 static const sec_tag_t client_tag_list_verify_none[] = {
315 CA_CERTIFICATE_TAG,
316 };
317
318 static const sec_tag_t client_tag_list_verify[] = {
319 CA_CERTIFICATE_TAG,
320 CLIENT_CERTIFICATE_TAG,
321 };
322
323 const sec_tag_t *sec_tag_list;
324 size_t sec_tag_list_size;
325
326 switch (peer_verify) {
327 case TLS_PEER_VERIFY_NONE:
328 sec_tag_list = client_tag_list_verify_none;
329 sec_tag_list_size = sizeof(client_tag_list_verify_none);
330 break;
331 case TLS_PEER_VERIFY_OPTIONAL:
332 case TLS_PEER_VERIFY_REQUIRED:
333 sec_tag_list = client_tag_list_verify;
334 sec_tag_list_size = sizeof(client_tag_list_verify);
335 break;
336 default:
337 zassert_true(false, "unrecognized TLS peer verify type %d",
338 peer_verify);
339 return;
340 }
341
342 r = setsockopt(client_fd, SOL_TLS, TLS_SEC_TAG_LIST,
343 sec_tag_list, sec_tag_list_size);
344 zassert_not_equal(r, -1, "failed to set TLS_SEC_TAG_LIST (%d)",
345 errno);
346
347 r = setsockopt(client_fd, SOL_TLS, TLS_HOSTNAME, "localhost",
348 sizeof("localhost"));
349 zassert_not_equal(r, -1, "failed to set TLS_HOSTNAME (%d)", errno);
350 }
351
352 r = inet_pton(AF_INET, CONFIG_NET_CONFIG_MY_IPV4_ADDR, &sa.sin_addr.s_addr);
353 zassert_not_equal(-1, r, "inet_pton() failed (%d)", errno);
354 zassert_not_equal(0, r, "%s is not a valid IPv4 address", CONFIG_NET_CONFIG_MY_IPV4_ADDR);
355 zassert_equal(1, r, "inet_pton() failed to convert %s", CONFIG_NET_CONFIG_MY_IPV4_ADDR);
356
357 memset(addrstr, '\0', sizeof(addrstr));
358 addrstrp = (char *)inet_ntop(AF_INET, &sa.sin_addr,
359 addrstr, sizeof(addrstr));
360 zassert_not_equal(addrstrp, NULL, "inet_ntop() failed (%d)", errno);
361
362 NET_DBG("connecting to [%s]:%d with fd %d",
363 log_strdup(addrstr), ntohs(sa.sin_port), client_fd);
364
365 r = connect(client_fd, (struct sockaddr *)&sa, sizeof(sa));
366 zassert_not_equal(r, -1, "failed to connect (%d)", errno);
367
368 /*
369 * The main part of the test
370 */
371
372 NET_DBG("Calling send()");
373 r = send(client_fd, SECRET, SECRET_SIZE, 0);
374 zassert_not_equal(r, -1, "send() failed (%d)", errno);
375 zassert_equal(SECRET_SIZE, r, "expected: %zu actual: %d", SECRET_SIZE, r);
376
377 NET_DBG("Calling recv()");
378 memset(addrstr, 0, sizeof(addrstr));
379 r = recv(client_fd, addrstr, sizeof(addrstr), 0);
380 zassert_not_equal(r, -1, "recv() failed (%d)", errno);
381 zassert_equal(SECRET_SIZE, r, "expected: %zu actual: %d", SECRET_SIZE, r);
382
383 zassert_mem_equal(SECRET, addrstr, SECRET_SIZE,
384 "expected: %s actual: %s", SECRET, addrstr);
385
386 /*
387 * Cleanup resources
388 */
389
390 NET_DBG("closing client fd");
391 r = close(client_fd);
392 zassert_not_equal(-1, r, "close() failed on the client fd (%d)", errno);
393
394 NET_DBG("closing server fd");
395 r = close(server_fd);
396 zassert_not_equal(-1, r, "close() failed on the server fd (%d)", errno);
397
398 r = k_thread_join(&server_thread, K_FOREVER);
399 zassert_equal(0, r, "k_thread_join() failed (%d)", r);
400 }
401
test_tls_peer_verify_none(void)402 static void test_tls_peer_verify_none(void)
403 {
404 test_common(TLS_PEER_VERIFY_NONE);
405 }
406
test_tls_peer_verify_optional(void)407 static void test_tls_peer_verify_optional(void)
408 {
409 test_common(TLS_PEER_VERIFY_OPTIONAL);
410 }
411
test_tls_peer_verify_required(void)412 static void test_tls_peer_verify_required(void)
413 {
414 test_common(TLS_PEER_VERIFY_REQUIRED);
415 }
416
test_main(void)417 void test_main(void)
418 {
419 int r;
420
421 /*
422 * Load both client & server credentials
423 *
424 * Normally, this would be split into separate applications but
425 * for testing purposes, we just use separate threads.
426 *
427 * Also, it has to be done before tests are run, otherwise
428 * there are errors due to attempts to load too many certificates.
429 *
430 * The server would normally load
431 * - server public key
432 * - server private key
433 * - ca cert (only when client authentication is required)
434 *
435 * The client would normally load
436 * - ca cert (to verify the server)
437 * - client public key (only when client authentication is required)
438 * - client private key (only when client authentication is required)
439 */
440 if (IS_ENABLED(CONFIG_TLS_CREDENTIALS)) {
441 NET_DBG("Loading credentials");
442 r = tls_credential_add(CA_CERTIFICATE_TAG,
443 TLS_CREDENTIAL_CA_CERTIFICATE,
444 ca, sizeof(ca));
445 zassert_equal(r, 0, "failed to add CA Certificate (%d)", r);
446
447 r = tls_credential_add(SERVER_CERTIFICATE_TAG,
448 TLS_CREDENTIAL_SERVER_CERTIFICATE,
449 server, sizeof(server));
450 zassert_equal(r, 0, "failed to add Server Certificate (%d)", r);
451
452 r = tls_credential_add(SERVER_CERTIFICATE_TAG,
453 TLS_CREDENTIAL_PRIVATE_KEY,
454 server_privkey, sizeof(server_privkey));
455 zassert_equal(r, 0, "failed to add Server Private Key (%d)", r);
456
457 r = tls_credential_add(CLIENT_CERTIFICATE_TAG,
458 TLS_CREDENTIAL_SERVER_CERTIFICATE,
459 client, sizeof(client));
460 zassert_equal(r, 0, "failed to add Client Certificate (%d)", r);
461
462 r = tls_credential_add(CLIENT_CERTIFICATE_TAG,
463 TLS_CREDENTIAL_PRIVATE_KEY,
464 client_privkey, sizeof(client_privkey));
465 zassert_equal(r, 0, "failed to add Client Private Key (%d)", r);
466 }
467
468 ztest_test_suite(
469 tls_socket_api_extension,
470 ztest_unit_test(test_tls_peer_verify_none),
471 ztest_unit_test(test_tls_peer_verify_optional),
472 ztest_unit_test(test_tls_peer_verify_required)
473 );
474
475 ztest_run_test_suite(tls_socket_api_extension);
476 }
477