libcoap 4.3.5rc1
Loading...
Searching...
No Matches
coap_wolfssl.c
Go to the documentation of this file.
1/*
2 * coap_wolfssl.c -- wolfSSL Transport Layer Support for libcoap
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2023 Javier Blanco <frblanco@pa.uc3m.es>
6 * Copyright (C) 2018-2024 Jon Shallow <supjps-libcoap@jpshallow.com>
7 *
8 * SPDX-License-Identifier: BSD-2-Clause
9 *
10 * This file is part of the CoAP library libcoap. Please see README for terms
11 * of use.
12 */
13
20
21#ifdef COAP_WITH_LIBWOLFSSL
22
23/*
24 * Implemented using wolfSSL's OpenSSL compatibility layer based on coap_openssl.c.
25 *
26 * It is possible to override the Ciphers, define the Algorithms or Groups
27 * to use for the SSL negotiations at compile time. This is done by the adding
28 * of the appropriate -D option to the CFLAGS parameter that is used on the
29 * ./configure command line.
30 * E.g. ./configure CFLAGS="-DXX='\"YY\"' -DUU='\"VV\"'"
31 * The parameter value is case-sensitive and needs the extra " wrapper so that
32 * it includes the "text" with quotes in the defined parameter..
33 *
34 * The (client) PKI ciphers can be overridden with (example)
35 * CFLAGS="-DCOAP_WOLFSSL_PKI_CIPHERS='\"TLS13-AES128-GCM-SHA256\"'"
36 *
37 * The (client) PSK ciphers can be overridden with (example)
38 * CFLAGS="-DCOAP_WOLFSSL_PSK_CIPHERS='\"PSK-AES128-CCM\"'"
39 *
40 * The Algorithms can be defined by (example)
41 * CFLAGS="-DCOAP_WOLFSSL_SIGALGS='\"RSA+SHA256\"'"
42 *
43 * The Groups (including post-quantum ones, if wolfSSL has been built with liboqs
44 * and DTLS 1.3 enabled) can be defined using the following example:
45 * CFLAGS="-DCOAP_WOLFSSL_GROUPS=\"\\\"P-384:P-256:KYBER_LEVEL1\\\"\"" ./configure ...
46 *
47 * wolfSSL library building (not libcoap library building)
48 *
49 * If wolfSSL is going to interoperate with TinyDTLS, then the wolfSSL library
50 * needs to be build with
51 * $ ./configure CFLAGS="-DBUILD_TLS_PSK_WITH_AES_128_CCM"
52 * as TinyDTLS currently only supports CCM.
53 *
54 * If wolfSSL debug logging is required, then the wolfSSL library needs to be built with
55 * $ ./configure --enable-debug
56 *
57 * For extra TLS debugging
58 * $./configure --enable-debug CFLAGS="-DWOLFSSL_DEBUG_TLS"
59 *
60 * If wolfSSL dtls1.3 support is required, then the wolfSSL library needs to be built with
61 * $ ./configure --enable-dtls13
62 *
63 * If wolfSSL RPK support is required, then the wolfSSL library needs to be built with
64 * $ ./configure CFLAGS="-DHAVE_RPK"
65 *
66 * When building the wolfSSL library from scratch, it is suggested that the library
67 * built with
68 * $ ./configure --enable-all
69 * to get the needed common options, or perhaps
70 * $ ./configure --enable-all --enable-dtls13 CFLAGS="-DBUILD_TLS_PSK_WITH_AES_128_CCM -DHAVE_RPK"
71 */
72
73#include <wolfssl/options.h>
74#include <wolfssl/ssl.h>
75#include <wolfssl/wolfcrypt/settings.h>
76#include <wolfssl/openssl/ssl.h>
77#include <wolfssl/openssl/x509v3.h>
78
79#ifdef COAP_EPOLL_SUPPORT
80# include <sys/epoll.h>
81#endif /* COAP_EPOLL_SUPPORT */
82
83#if LIBWOLFSSL_VERSION_HEX < 0x05002000
84#error Must be compiled against wolfSSL 5.2.0 or later
85#endif
86
87#ifdef _WIN32
88#define strcasecmp _stricmp
89#define strncasecmp _strnicmp
90#endif
91
92/* missing definitions */
93#define WOLFSSL3_AL_FATAL 2
94#define WOLFSSL_TLSEXT_ERR_OK 0
95
96/* This structure encapsulates the wolfSSL context object. */
97typedef struct coap_dtls_context_t {
98 WOLFSSL_CTX *ctx;
99 WOLFSSL_HMAC_CTX *cookie_hmac;
100} coap_dtls_context_t;
101
102typedef struct coap_tls_context_t {
103 WOLFSSL_CTX *ctx;
104} coap_tls_context_t;
105
106#define IS_PSK 0x1
107#define IS_PKI 0x2
108
109typedef struct coap_wolfssl_context_t {
110 coap_dtls_context_t dtls;
111#if !COAP_DISABLE_TCP
112 coap_tls_context_t tls;
113#endif /* !COAP_DISABLE_TCP */
114 coap_dtls_pki_t setup_data;
115 int psk_pki_enabled;
116 char *root_ca_file;
117 char *root_ca_dir;
118} coap_wolfssl_context_t;
119
120typedef struct coap_ssl_data_t {
121 coap_session_t *session;
122 const void *pdu;
123 unsigned pdu_len;
124 unsigned peekmode;
125} coap_ssl_data_t;
126
127typedef struct coap_wolfssl_env_t {
128 WOLFSSL *ssl;
129 coap_tick_t last_timeout;
130 unsigned int retry_scalar;
131 coap_ssl_data_t data;
132 int done_psk_check;
133 coap_dtls_role_t role;
134} coap_wolfssl_env_t;
135
136typedef enum coap_enc_method_t {
137 COAP_ENC_PSK,
138 COAP_ENC_PKI,
139} coap_enc_method_t;
140
141static void *
142wolfssl_malloc(size_t size) {
143 void *ret = XMALLOC(size, NULL, DYNAMIC_TYPE_TMP_BUFFER);
144
145 return ret;
146}
147
148static void
149wolfssl_free(void *ptr) {
150 if (ptr)
151 XFREE(ptr, NULL, DYNAMIC_TYPE_TMP_BUFFER);
152}
153
154static char *
155wolfssl_strdup(const char *str) {
156 char *ret = (char *)wolfssl_malloc(strlen(str) + 1);
157
158 if (ret) {
159 strcpy(ret, str);
160 }
161 return ret;
162}
163
164static char *
165wolfssl_strndup(const char *str, size_t n) {
166 size_t len = strnlen(str, n);
167 char *ret = (char *)wolfssl_malloc(len + 1);
168
169 if (ret) {
170 strncpy(ret, str, len);
171 ret[len] = '\0';
172 }
173 return ret;
174}
175
176static coap_wolfssl_env_t *
177coap_dtls_new_wolfssl_env(coap_session_t *c_session, coap_dtls_role_t role) {
178 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)c_session->tls;
179
180 assert(w_env == NULL);
181 w_env = (coap_wolfssl_env_t *)wolfssl_malloc(sizeof(coap_wolfssl_env_t));
182 if (!w_env) {
183 return NULL;
184 }
185 memset(w_env, 0, sizeof(coap_wolfssl_env_t));
186 w_env->role = role;
187 return w_env;
188}
189
190static void
191coap_dtls_free_wolfssl_env(coap_wolfssl_env_t *w_env) {
192 if (w_env) {
193 wolfssl_free(w_env);
194 }
195}
196
197#if COAP_CLIENT_SUPPORT
198#ifndef WOLFSSL_CIPHER_LIST_MAX_SIZE
199#define WOLFSSL_CIPHER_LIST_MAX_SIZE 4096
200#endif /* WOLFSSL_CIPHER_LIST_MAX_SIZE */
201
202#ifdef COAP_WOLFSSL_PSK_CIPHERS
203static char psk_ciphers[] = COAP_WOLFSSL_PSK_CIPHERS;
204#else /* ! COAP_WOLFSSL_PSK_CIPHERS */
205static char psk_ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
206#endif /* ! COAP_WOLFSSL_PSK_CIPHERS */
207
208#ifdef COAP_WOLFSSL_PKI_CIPHERS
209static char pki_ciphers[] = COAP_WOLFSSL_PKI_CIPHERS;
210#else /* ! COAP_WOLFSSL_PKI_CIPHERS */
211static char pki_ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
212#endif /* ! COAP_WOLFSSL_PKI_CIPHERS */
213
214static void
215set_ciphersuites(WOLFSSL *ssl, coap_enc_method_t method) {
216#if ! defined(COAP_WOLFSSL_PSK_CIPHERS) || ! defined(COAP_WOLFSSL_PKI_CIPHERS)
217 static int processed_ciphers = 0;
218
219 if (!processed_ciphers) {
220 static char ciphers[WOLFSSL_CIPHER_LIST_MAX_SIZE];
221 char *ciphers_ofs = ciphers;
222 char *cp;
223#if ! defined(COAP_WOLFSSL_PSK_CIPHERS)
224 char *psk_ofs = psk_ciphers;
225#endif /* ! COAP_WOLFSSL_PSK_CIPHERS */
226#if ! defined(COAP_WOLFSSL_PKI_CIPHERS)
227 char *pki_ofs = pki_ciphers;
228#endif /* ! COAP_WOLFSSL_PKI_CIPHERS */
229
230 if (wolfSSL_get_ciphers(ciphers, (int)sizeof(ciphers)) != WOLFSSL_SUCCESS) {
231 coap_log_warn("set_ciphersuites: Failed to get ciphers\n");
232 return;
233 }
234
235 while (ciphers_ofs) {
236 cp = strchr(ciphers_ofs, ':');
237 if (cp)
238 *cp = '\000';
239 if (strstr(ciphers_ofs, "NULL")) {
240 /* NULL type not required */
241 goto next_a;
242 }
243 if (strcmp(ciphers_ofs, "RENEGOTIATION-INFO") == 0) {
244 /* Skip for now - adding to end */
245 goto next_a;
246 } else if (strstr(ciphers_ofs, "PSK")) {
247#if ! defined(COAP_WOLFSSL_PSK_CIPHERS)
248 if (psk_ofs != psk_ciphers) {
249 psk_ofs[0] = ':';
250 psk_ofs++;
251 }
252 strcpy(psk_ofs, ciphers_ofs);
253 psk_ofs += strlen(ciphers_ofs);
254 psk_ofs[0] = '\000';
255#endif /* ! COAP_WOLFSSL_PSK_CIPHERS */
256 } else {
257#if ! defined(COAP_WOLFSSL_PKI_CIPHERS)
258 if (pki_ofs != pki_ciphers) {
259 pki_ofs[0] = ':';
260 pki_ofs++;
261 }
262 strcpy(pki_ofs, ciphers_ofs);
263 pki_ofs += strlen(ciphers_ofs);
264 pki_ofs[0] = '\000';
265#endif /* ! COAP_WOLFSSL_PKI_CIPHERS */
266 }
267next_a:
268 if (cp)
269 ciphers_ofs = cp + 1;
270 else
271 ciphers_ofs = NULL;
272 }
273#ifndef HAVE_SECURE_RENEGOTIATION
274 /*
275 * Need to add in dummy "RENEGOTIATION-INFO" at end.
276 * This addition will get ignored if the complied library does not
277 * support it.
278 */
279#if ! defined(COAP_WOLFSSL_PSK_CIPHERS)
280 if (psk_ofs != psk_ciphers) {
281 psk_ofs[0] = ':';
282 psk_ofs++;
283 }
284 strcpy(psk_ofs, "RENEGOTIATION-INFO");
285 psk_ofs += strlen("RENEGOTIATION-INFO");
286 psk_ofs[0] = '\000';
287#endif /* ! COAP_WOLFSSL_PSK_CIPHERS */
288#if ! defined(COAP_WOLFSSL_PKI_CIPHERS)
289 if (pki_ofs != pki_ciphers) {
290 pki_ofs[0] = ':';
291 pki_ofs++;
292 }
293 strcpy(pki_ofs, "RENEGOTIATION-INFO");
294 pki_ofs += strlen("RENEGOTIATION-INFO");
295 pki_ofs[0] = '\000';
296#endif /* ! COAP_WOLFSSL_PSK_CIPHERS */
297#endif /* ! HAVE_SECURE_RENEGOTIATION */
298
299 processed_ciphers = 1;
300 }
301#endif /* ! COAP_WOLFSSL_PSK_CIPHERS || ! COAP_WOLFSSL_PKI_CIPHERS */
302
303 if (method == COAP_ENC_PSK) {
304 wolfSSL_set_cipher_list(ssl, psk_ciphers);
305 } else {
306 wolfSSL_set_cipher_list(ssl, pki_ciphers);
307 }
308}
309#endif /* COAP_CLIENT_SUPPORT */
310
311#if COAP_SERVER_SUPPORT
312static int psk_tls_server_name_call_back(WOLFSSL *ssl, int *sd, void *arg);
313#endif /* COAP_SERVER_SUPPORT */
314static int tls_verify_call_back(int preverify_ok, WOLFSSL_X509_STORE_CTX *ctx);
315
316int
318 if (wolfSSL_lib_version_hex() < 0x05002000) {
319 coap_log_warn("wolfSSL version 5.2.0 or later is required\n");
320 return 0;
321 }
322 return 1;
323}
324
325int
327#if !COAP_DISABLE_TCP
328 if (wolfSSL_lib_version_hex() < 0x05002000) {
329 coap_log_warn("wolfSSL version 5.2.0 or later is required\n");
330 return 0;
331 }
332 return 1;
333#else /* COAP_DISABLE_TCP */
334 return 0;
335#endif /* COAP_DISABLE_TCP */
336}
337
338/*
339 * return 0 failed
340 * 1 passed
341 */
342int
344 return 1;
345}
346
347/*
348 * return 0 failed
349 * 1 passed
350 */
351int
353 return 1;
354}
355
356/*
357 * return 0 failed
358 * 1 passed
359 */
360int
362 return 0;
363}
364
365/*
366 * return 0 failed
367 * 1 passed
368 */
369int
371#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
372 return 1;
373#else /* ! HAVE_RPK || LIBWOLFSSL_VERSION_HEX < 0x05006004 */
374 return 0;
375#endif /* ! HAVE_RPK || LIBWOLFSSL_VERSION_HEX < 0x05006004 */
376}
377
380 static coap_tls_version_t version;
381 version.version = wolfSSL_lib_version_hex();
382 version.built_version = LIBWOLFSSL_VERSION_HEX;
384
385 return &version;
386}
387
388static void
389coap_wolfssl_log_func(int level, const char *text) {
390 int use_level;
391
392 switch ((int)level) {
393 case ERROR_LOG:
394 use_level = COAP_LOG_DEBUG;
395 break;
396 case INFO_LOG:
397 use_level = COAP_LOG_INFO;
398 break;
399 case ENTER_LOG:
400 use_level = COAP_LOG_INFO;
401 break;
402 case LEAVE_LOG:
403 use_level = COAP_LOG_INFO;
404 break;
405 case OTHER_LOG:
406 use_level = COAP_LOG_DEBUG;
407 break;
408 default:
409 use_level = COAP_LOG_DEBUG;
410 break;
411 }
412 coap_dtls_log(use_level, "%s\n", text);
413}
414
415void
416coap_dtls_startup(void) {
417 if (wolfSSL_library_init() != WOLFSSL_SUCCESS) {
418 coap_log_err("wolfSSL_library_init: Fail\n");
419 return;
420 }
421 wolfSSL_load_error_strings();
422 wolfSSL_SetLoggingCb(coap_wolfssl_log_func);
423 wolfSSL_Debugging_ON();
424}
425
426void
427coap_dtls_shutdown(void) {
428 wolfSSL_ERR_free_strings();
430 wolfSSL_Debugging_OFF();
431}
432
433void *
434coap_dtls_get_tls(const coap_session_t *c_session,
435 coap_tls_library_t *tls_lib) {
436 if (tls_lib)
437 *tls_lib = COAP_TLS_LIBRARY_WOLFSSL;
438 if (c_session) {
439 coap_wolfssl_env_t *w_env;
440
441 /* To get around const issue */
442 memcpy(&w_env, &c_session->tls, sizeof(w_env));
443
444 return (void *)&w_env->ssl;
445 }
446 return NULL;
447}
448
449/*
450 * Logging levels use the standard CoAP logging levels
451 */
453
454void
456 dtls_log_level = level;
457}
458
461 return dtls_log_level;
462}
463
464static int
465coap_dgram_read(WOLFSSL *ssl, char *out, int outl, void *ctx) {
466 int ret = 0;
467 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)ctx;
468 coap_ssl_data_t *data = w_env ? &w_env->data : NULL;
469 coap_tick_t now;
470
471 (void)ssl;
472 if (w_env && !w_env->done_psk_check && w_env->ssl) {
473 if (wolfSSL_SSL_in_init(w_env->ssl)) {
474 const char *name = wolfSSL_get_cipher_name(w_env->ssl);
475
476 if (name) {
477 coap_dtls_log(COAP_LOG_DEBUG," Cipher Suite: %s\n", name);
478
479 if (strstr(name, "PSK") && w_env->role == COAP_DTLS_ROLE_SERVER) {
480 wolfSSL_set_verify(w_env->ssl, WOLFSSL_VERIFY_NONE, tls_verify_call_back);
481 w_env->done_psk_check = 1;
482 }
483 }
484 }
485 }
486 if (out != NULL) {
487 if (data != NULL && data->pdu_len > 0) {
488 if (outl < (int)data->pdu_len) {
489 memcpy(out, data->pdu, outl);
490 ret = outl;
491 } else {
492 memcpy(out, data->pdu, data->pdu_len);
493 ret = (int)data->pdu_len;
494 }
495 if (!data->peekmode) {
496 data->pdu_len = 0;
497 data->pdu = NULL;
498 }
499 coap_ticks(&now);
500 w_env->last_timeout = now;
501 } else {
502 ret = WANT_READ;
503 }
504 }
505 return ret;
506}
507
508static int
509coap_dgram_write(WOLFSSL *ssl, char *in, int inl, void *ctx) {
510 int ret = 0;
511 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)ctx;
512 coap_ssl_data_t *data = w_env ? &w_env->data : NULL;
513 coap_tick_t now;
514
515 (void)ssl;
516 assert(data);
517 if (data->session) {
518 if (!coap_netif_available(data->session)
520 && data->session->endpoint == NULL
521#endif /* COAP_SERVER_SUPPORT */
522 ) {
523 /* socket was closed on client due to error */
524 errno = ECONNRESET;
525 return -1;
526 }
527 ret = (int)data->session->sock.lfunc[COAP_LAYER_TLS].l_write(data->session,
528 (const uint8_t *)in,
529 inl);
530 if (ret > 0) {
531 coap_ticks(&now);
532 w_env->last_timeout = now;
533 }
534 } else {
535 ret = -1;
536 }
537 return ret;
538}
539
540#if COAP_CLIENT_SUPPORT
541static unsigned int
542coap_dtls_psk_client_callback(WOLFSSL *ssl,
543 const char *hint,
544 char *identity,
545 unsigned int max_identity_len,
546 unsigned char *psk,
547 unsigned int max_psk_len) {
548 coap_session_t *c_session;
549 coap_wolfssl_context_t *w_context;
550 coap_dtls_cpsk_t *setup_data;
551 const coap_dtls_cpsk_info_t *cpsk_info;
552 const coap_bin_const_t *psk_key;
553 const coap_bin_const_t *psk_identity;
554
555 c_session = (coap_session_t *)wolfSSL_get_app_data(ssl);
556 if (c_session == NULL)
557 return 0;
558 w_context = (coap_wolfssl_context_t *)c_session->context->dtls_context;
559 if (w_context == NULL)
560 return 0;
561 setup_data = &c_session->cpsk_setup_data;
562
563 if (setup_data->validate_ih_call_back) {
564 coap_bin_const_t temp;
565 coap_str_const_t lhint;
566
567 temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
568 temp.length = strlen((const char *)temp.s);
569 coap_session_refresh_psk_hint(c_session, &temp);
570
571 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
572 (const char *)temp.s);
573
574
575 lhint.s = temp.s;
576 lhint.length = temp.length;
577 cpsk_info =
578 setup_data->validate_ih_call_back(&lhint,
579 c_session,
580 setup_data->ih_call_back_arg);
581
582 if (cpsk_info == NULL)
583 return 0;
584
585 coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
586 coap_session_refresh_psk_key(c_session, &cpsk_info->key);
587 psk_identity = &cpsk_info->identity;
588 psk_key = &cpsk_info->key;
589 } else {
590 psk_identity = coap_get_session_client_psk_identity(c_session);
591 psk_key = coap_get_session_client_psk_key(c_session);
592 }
593
594 if (psk_identity == NULL || psk_key == NULL) {
595 coap_log_warn("no PSK available\n");
596 return 0;
597 }
598
599 /* identity has to be NULL terminated */
600 if (!max_identity_len)
601 return 0;
602 max_identity_len--;
603 if (psk_identity->length > max_identity_len) {
604 coap_log_warn("psk_identity too large, truncated to %d bytes\n",
605 max_identity_len);
606 } else {
607 /* Reduce to match */
608 max_identity_len = (unsigned int)psk_identity->length;
609 }
610 memcpy(identity, psk_identity->s, max_identity_len);
611 identity[max_identity_len] = '\000';
612
613 if (psk_key->length > max_psk_len) {
614 coap_log_warn("psk_key too large, truncated to %d bytes\n",
615 max_psk_len);
616 } else {
617 /* Reduce to match */
618 max_psk_len = (unsigned int)psk_key->length;
619 }
620 memcpy(psk, psk_key->s, max_psk_len);
621 return max_psk_len;
622}
623
624static unsigned int
625coap_dtls_psk_client_cs_callback(WOLFSSL *ssl, const char *hint,
626 char *identity, unsigned int max_identity_len,
627 unsigned char *psk, unsigned int max_psk_len,
628 const char *ciphersuite) {
629 int key_len = coap_dtls_psk_client_callback(ssl,
630 hint,
631 identity,
632 max_identity_len,
633 psk,
634 max_psk_len);
635
636 (void)ciphersuite;
637 return key_len;
638}
639
640#endif /* COAP_CLIENT_SUPPORT */
641
642#if COAP_SERVER_SUPPORT
643static unsigned int
644coap_dtls_psk_server_callback(
645 WOLFSSL *ssl,
646 const char *identity,
647 unsigned char *psk,
648 unsigned int max_psk_len) {
649 coap_session_t *c_session;
650 coap_dtls_spsk_t *setup_data;
651 coap_bin_const_t lidentity;
652 const coap_bin_const_t *psk_key;
653
654 c_session = (coap_session_t *)wolfSSL_get_app_data(ssl);
655 if (c_session == NULL)
656 return 0;
657
658 setup_data = &c_session->context->spsk_setup_data;
659
660 /* Track the Identity being used */
661 lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
662 lidentity.length = strlen((const char *)lidentity.s);
663 coap_session_refresh_psk_identity(c_session, &lidentity);
664
665 coap_log_debug("got psk_identity: '%.*s'\n",
666 (int)lidentity.length, (const char *)lidentity.s);
667
668 if (setup_data->validate_id_call_back) {
669 psk_key = setup_data->validate_id_call_back(&lidentity,
670 c_session,
671 setup_data->id_call_back_arg);
672
673 coap_session_refresh_psk_key(c_session, psk_key);
674 } else {
675 psk_key = coap_get_session_server_psk_key(c_session);
676 }
677
678 if (psk_key == NULL)
679 return 0;
680
681 if (psk_key->length > max_psk_len) {
682 coap_log_warn("psk_key too large, truncated to %d bytes\n",
683 max_psk_len);
684 } else {
685 /* Reduce to match */
686 max_psk_len = (unsigned int)psk_key->length;
687 }
688 memcpy(psk, psk_key->s, max_psk_len);
689 return max_psk_len;
690}
691#endif /* COAP_SERVER_SUPPORT */
692
693static const char *
694ssl_function_definition(unsigned long e) {
695 static char buff[80];
696
697 snprintf(buff, sizeof(buff), " at %s:%s",
698 wolfSSL_ERR_lib_error_string(e), wolfSSL_ERR_func_error_string(e));
699 return buff;
700}
701
702static void
703coap_dtls_info_callback(const WOLFSSL *ssl, int where, int ret) {
704 coap_session_t *session = (coap_session_t *)wolfSSL_get_app_data(ssl);
705 const char *pstr;
706 int w = where &~SSL_ST_MASK;
707
708 if (w & SSL_ST_CONNECT)
709 pstr = "wolfSSL_connect";
710 else if (w & SSL_ST_ACCEPT)
711 pstr = "wolfSSL_accept";
712 else
713 pstr = "undefined";
714
715 if (where & SSL_CB_LOOP) {
716 coap_dtls_log(COAP_LOG_DEBUG, "* %s: %s:%s\n",
717 coap_session_str(session), pstr, wolfSSL_state_string_long(ssl));
718 } else if (where & SSL_CB_ALERT) {
719 coap_log_t log_level = COAP_LOG_INFO;
720 pstr = (where & SSL_CB_READ) ? "read" : "write";
721 if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == WOLFSSL3_AL_FATAL) {
723 if ((ret & 0xff) != close_notify)
724 log_level = COAP_LOG_WARN;
725 }
726
727 /* Need to let CoAP logging know why this session is dying */
728 coap_log(log_level, "* %s: SSL3 alert %s:%s:%s\n",
729 coap_session_str(session),
730 pstr,
731 wolfSSL_alert_type_string_long(ret),
732 wolfSSL_alert_desc_string_long(ret));
733 } else if (where & SSL_CB_EXIT) {
734 if (ret == 0) {
736 unsigned long e;
737 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:failed in %s\n",
738 coap_session_str(session), pstr, wolfSSL_state_string_long(ssl));
739 while ((e = wolfSSL_ERR_get_error()))
740 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
741 coap_session_str(session), wolfSSL_ERR_reason_error_string(e),
742 ssl_function_definition(e));
743 }
744 } else if (ret < 0) {
746 WOLFSSL *rw_ssl;
747
748 /* Need to do this to not get a compiler warning about const parameters */
749 memcpy(&rw_ssl, &ssl, sizeof(rw_ssl));
750 int err = wolfSSL_get_error(rw_ssl, ret);
751 if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE &&
752 err != WOLFSSL_ERROR_WANT_CONNECT && err != WOLFSSL_ERROR_WANT_ACCEPT &&
753 err != WOLFSSL_ERROR_WANT_X509_LOOKUP) {
754 long e;
755 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:error in %s\n",
756 coap_session_str(session), pstr, wolfSSL_state_string_long(ssl));
757 while ((e = wolfSSL_ERR_get_error()))
758 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
759 coap_session_str(session), wolfSSL_ERR_reason_error_string(e),
760 ssl_function_definition(e));
761 }
762 }
763 }
764 }
765
766 if (where == SSL_CB_HANDSHAKE_START) {
767 WOLFSSL *rw_ssl;
768
769 /* Need to do this to not get a compiler warning about const parameters */
770 memcpy(&rw_ssl, &ssl, sizeof(rw_ssl));
771 if (wolfSSL_is_init_finished(rw_ssl))
773 }
774}
775
776/*
777 * strm
778 * return +ve data amount
779 * 0 no more
780 * -1 error
781 */
782static int
783coap_sock_read(WOLFSSL *ssl, char *out, int outl, void *ctx) {
784 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)ctx;
785 int ret = 0;
786 coap_session_t *session = w_env ? w_env->data.session : NULL;
787
788 (void)ssl;
789 assert(session);
790 if (w_env && !w_env->done_psk_check && w_env->ssl &&
791 w_env->role == COAP_DTLS_ROLE_SERVER) {
792 if (wolfSSL_SSL_in_init(w_env->ssl)) {
793 const char *name = wolfSSL_get_cipher_name(w_env->ssl);
794
795 if (name) {
796 coap_dtls_log(COAP_LOG_DEBUG,"Cipher Suite: %s\n", name);
797
798 if (strstr(name, "PSK")) {
799 wolfSSL_set_verify(w_env->ssl, WOLFSSL_VERIFY_NONE, tls_verify_call_back);
800 w_env->done_psk_check = 1;
801 }
802 }
803 }
804 }
805 if (out != NULL) {
806 ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (u_char *)out,
807 outl);
808 if (ret == 0) {
809 ret = WANT_READ;
810 }
811 }
812 return ret;
813}
814
815/*
816 * strm
817 * return +ve data amount
818 * 0 no more
819 * -1 error (error in errno)
820 */
821static int
822coap_sock_write(WOLFSSL *ssl, char *in, int inl, void *ctx) {
823 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)ctx;
824 int ret = 0;
825 coap_session_t *session = w_env ? w_env->data.session : NULL;
826
827 (void)ssl;
828 assert(session);
829 ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
830 (const uint8_t *)in,
831 inl);
832 /* Translate layer what returns into what wolfSSL expects */
833 if (ret == 0) {
834 ret = -1;
835 } else {
836 if (ret == -1) {
837 if ((session->state == COAP_SESSION_STATE_CSM ||
838 session->state == COAP_SESSION_STATE_HANDSHAKE) &&
839 (errno == EPIPE || errno == ECONNRESET)) {
840 /*
841 * Need to handle a TCP timing window where an agent continues with
842 * the sending of the next handshake or a CSM.
843 * However, the peer does not like a certificate and so sends a
844 * fatal alert and closes the TCP session.
845 * The sending of the next handshake or CSM may get terminated because
846 * of the closed TCP session, but there is still an outstanding alert
847 * to be read in and reported on.
848 * In this case, pretend that sending the info was fine so that the
849 * alert can be read (which effectively is what happens with DTLS).
850 */
851 ret = inl;
852 }
853 }
854 }
855 return ret;
856}
857
858static void
859coap_set_user_prefs(WOLFSSL_CTX *ctx) {
860 (void)ctx;
861
862#ifdef COAP_WOLFSSL_SIGALGS
863 wolfSSL_CTX_set1_sigalgs_list(ctx, COAP_WOLFSSL_SIGALGS);
864#endif
865#ifdef COAP_WOLFSSL_GROUPS
866 int ret;
867 ret = wolfSSL_CTX_set1_groups_list(ctx,
868 (char *) COAP_WOLFSSL_GROUPS);
869 if (ret != WOLFSSL_SUCCESS) {
870 coap_log_debug("Failed to set group list\n");
871 }
872#endif
873}
874
875/* Set up DTLS context if not alread done */
876static int
877setup_dtls_context(coap_wolfssl_context_t *w_context) {
878 if (!w_context->dtls.ctx) {
879 uint8_t cookie_secret[32];
880
881 /* Set up DTLS context */
882 w_context->dtls.ctx = wolfSSL_CTX_new(wolfDTLS_method());
883 if (!w_context->dtls.ctx)
884 goto error;
885 wolfSSL_CTX_set_min_proto_version(w_context->dtls.ctx,
886 DTLS1_2_VERSION);
887 wolfSSL_CTX_set_ex_data(w_context->dtls.ctx, 0, &w_context->dtls);
888 coap_set_user_prefs(w_context->dtls.ctx);
889 memset(cookie_secret, 0, sizeof(cookie_secret));
890 if (!wolfSSL_RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
892 "Insufficient entropy for random cookie generation");
893 coap_prng(cookie_secret, sizeof(cookie_secret));
894 }
895 w_context->dtls.cookie_hmac = wolfSSL_HMAC_CTX_new();
896 if (!wolfSSL_HMAC_Init_ex(w_context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
897 wolfSSL_EVP_sha256(), NULL))
898 goto error;
899
900 wolfSSL_CTX_set_info_callback(w_context->dtls.ctx, coap_dtls_info_callback);
901 wolfSSL_CTX_set_options(w_context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
902 wolfSSL_SetIORecv(w_context->dtls.ctx, coap_dgram_read);
903 wolfSSL_SetIOSend(w_context->dtls.ctx, coap_dgram_write);
904#ifdef WOLFSSL_DTLS_MTU
905 wolfSSL_CTX_dtls_set_mtu(w_context->dtls.ctx, COAP_DEFAULT_MTU);
906#endif /* WOLFSSL_DTLS_MTU */
907 if (w_context->root_ca_file || w_context->root_ca_dir) {
908 if (!wolfSSL_CTX_load_verify_locations_ex(w_context->dtls.ctx,
909 w_context->root_ca_file,
910 w_context->root_ca_dir,
911 w_context->setup_data.allow_expired_certs ?
912 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
913 coap_log_warn("Unable to install root CAs (%s/%s)\n",
914 w_context->root_ca_file ? w_context->root_ca_file : "NULL",
915 w_context->root_ca_dir ? w_context->root_ca_dir : "NULL");
916 goto error;
917 }
918 }
919 /* Verify Peer */
920 if (w_context->setup_data.verify_peer_cert)
921 wolfSSL_CTX_set_verify(w_context->dtls.ctx,
922 WOLFSSL_VERIFY_PEER |
923 WOLFSSL_VERIFY_CLIENT_ONCE |
924 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
925 tls_verify_call_back);
926 else
927 wolfSSL_CTX_set_verify(w_context->dtls.ctx, WOLFSSL_VERIFY_NONE, tls_verify_call_back);
928 }
929 return 1;
930
931error:
932 coap_log_warn("wolfssl: unable to set up DTLS context\n");
933 return 0;
934}
935
936#if !COAP_DISABLE_TCP
937
938/* Set up TLS context if not alread done */
939static int
940setup_tls_context(coap_wolfssl_context_t *w_context) {
941 if (!w_context->tls.ctx) {
942 /* Set up TLS context */
943 w_context->tls.ctx = wolfSSL_CTX_new(wolfSSLv23_method());
944 if (!w_context->tls.ctx)
945 goto error;
946 wolfSSL_CTX_set_ex_data(w_context->tls.ctx, 0, &w_context->tls);
947 wolfSSL_CTX_set_min_proto_version(w_context->tls.ctx, TLS1_VERSION);
948 coap_set_user_prefs(w_context->tls.ctx);
949 wolfSSL_CTX_set_info_callback(w_context->tls.ctx, coap_dtls_info_callback);
950 wolfSSL_SetIORecv(w_context->tls.ctx, coap_sock_read);
951 wolfSSL_SetIOSend(w_context->tls.ctx, coap_sock_write);
952#if COAP_CLIENT_SUPPORT
953 if (w_context->psk_pki_enabled & IS_PSK) {
954 wolfSSL_CTX_set_psk_client_cs_callback(w_context->tls.ctx,
955 coap_dtls_psk_client_cs_callback);
956 }
957#endif /* COAP_CLIENT_SUPPORT */
958 if (w_context->root_ca_file || w_context->root_ca_dir) {
959 if (!wolfSSL_CTX_load_verify_locations_ex(w_context->tls.ctx,
960 w_context->root_ca_file,
961 w_context->root_ca_dir,
962 w_context->setup_data.allow_expired_certs ?
963 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
964 coap_log_warn("Unable to install root CAs (%s/%s)\n",
965 w_context->root_ca_file ? w_context->root_ca_file : "NULL",
966 w_context->root_ca_dir ? w_context->root_ca_dir : "NULL");
967 goto error;
968 }
969 }
970 /* Verify Peer */
971 if (w_context->setup_data.verify_peer_cert)
972 wolfSSL_CTX_set_verify(w_context->tls.ctx,
973 WOLFSSL_VERIFY_PEER |
974 WOLFSSL_VERIFY_CLIENT_ONCE |
975 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
976 tls_verify_call_back);
977 else
978 wolfSSL_CTX_set_verify(w_context->tls.ctx, WOLFSSL_VERIFY_NONE, tls_verify_call_back);
979 }
980 return 1;
981
982error:
983 coap_log_warn("wolfssl: unable to set up TLS context\n");
984 return 0;
985}
986#endif /* ! COAP_DISABLE_TCP */
987
988void *
990 coap_wolfssl_context_t *w_context;
991 (void)c_context;
992
993 w_context = (coap_wolfssl_context_t *)wolfssl_malloc(sizeof(coap_wolfssl_context_t));
994 if (w_context) {
995 memset(w_context, 0, sizeof(coap_wolfssl_context_t));
996 }
997
998 return w_context;
999}
1000
1001#if COAP_SERVER_SUPPORT
1002int
1004 coap_dtls_spsk_t *setup_data
1005 ) {
1006 coap_wolfssl_context_t *w_context =
1007 ((coap_wolfssl_context_t *)c_context->dtls_context);
1008
1009 if (!setup_data || !w_context)
1010 return 0;
1011
1012 if (!setup_dtls_context(w_context))
1013 return 0;
1014#if !COAP_DISABLE_TCP
1015 if (!setup_tls_context(w_context))
1016 return 0;
1017#endif /* !COAP_DISABLE_TCP */
1018
1019 wolfSSL_CTX_set_psk_server_callback(w_context->dtls.ctx,
1020 coap_dtls_psk_server_callback);
1021
1022#if !COAP_DISABLE_TCP
1023 wolfSSL_CTX_set_psk_server_callback(w_context->tls.ctx,
1024 coap_dtls_psk_server_callback);
1025#endif /* !COAP_DISABLE_TCP */
1026 if (setup_data->psk_info.hint.s) {
1027 char hint[COAP_DTLS_HINT_LENGTH];
1028 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1029 setup_data->psk_info.hint.s);
1030 wolfSSL_CTX_use_psk_identity_hint(w_context->dtls.ctx, hint);
1031#if !COAP_DISABLE_TCP
1032 wolfSSL_CTX_use_psk_identity_hint(w_context->tls.ctx, hint);
1033#endif /* !COAP_DISABLE_TCP */
1034 }
1035 if (setup_data->validate_sni_call_back) {
1036 wolfSSL_CTX_set_servername_arg(w_context->dtls.ctx,
1037 &c_context->spsk_setup_data);
1038 wolfSSL_CTX_set_tlsext_servername_callback(w_context->dtls.ctx,
1039 psk_tls_server_name_call_back);
1040#if !COAP_DISABLE_TCP
1041 wolfSSL_CTX_set_servername_arg(w_context->tls.ctx,
1042 &c_context->spsk_setup_data);
1043 wolfSSL_CTX_set_tlsext_servername_callback(w_context->tls.ctx,
1044 psk_tls_server_name_call_back);
1045#endif /* !COAP_DISABLE_TCP */
1046 }
1047 w_context->psk_pki_enabled |= IS_PSK;
1048 return 1;
1049}
1050#endif /* COAP_SERVER_SUPPORT */
1051
1052#if COAP_CLIENT_SUPPORT
1053int
1055 coap_dtls_cpsk_t *setup_data
1056 ) {
1057 coap_wolfssl_context_t *w_context =
1058 ((coap_wolfssl_context_t *)c_context->dtls_context);
1059
1060 if (!setup_data || !w_context)
1061 return 0;
1062
1063 w_context->psk_pki_enabled |= IS_PSK;
1064 return 1;
1065}
1066#endif /* COAP_CLIENT_SUPPORT */
1067
1068#if !COAP_DISABLE_TCP
1069static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1070
1071#if COAP_SERVER_SUPPORT
1072static int
1073server_alpn_callback(WOLFSSL *ssl COAP_UNUSED,
1074 const unsigned char **out,
1075 unsigned char *outlen,
1076 const unsigned char *in,
1077 unsigned int inlen,
1078 void *arg COAP_UNUSED
1079 ) {
1080 unsigned char *tout = NULL;
1081 int ret;
1082 if (inlen == 0)
1083 return SSL_TLSEXT_ERR_NOACK;
1084 ret = wolfSSL_select_next_proto(&tout,
1085 outlen,
1086 coap_alpn,
1087 sizeof(coap_alpn),
1088 in,
1089 inlen);
1090 *out = tout;
1091 return (ret != OPENSSL_NPN_NEGOTIATED) ? noack_return : WOLFSSL_TLSEXT_ERR_OK;
1092}
1093#endif /* COAP_SERVER_SUPPORT */
1094#endif /* !COAP_DISABLE_TCP */
1095
1096static int
1097setup_pki_ssl(WOLFSSL *ssl,
1098 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
1099 coap_dtls_key_t key;
1100 WOLFSSL_CTX *ctx = wolfSSL_get_SSL_CTX(ssl);
1101
1102 /* Map over to the new define format to save code duplication */
1103 coap_dtls_map_key_type_to_define(setup_data, &key);
1104
1105 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1106
1107 /*
1108 * Configure the Private Key
1109 */
1110 if (key.key.define.private_key.u_byte &&
1111 key.key.define.private_key.u_byte[0]) {
1112 switch (key.key.define.private_key_def) {
1113 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1114 if (!(wolfSSL_use_PrivateKey_file(ssl,
1116 WOLFSSL_FILETYPE_PEM))) {
1119 &key, role, 0);
1120 }
1121 break;
1122 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1123 if (!(wolfSSL_use_PrivateKey_buffer(ssl,
1125 (long)key.key.define.private_key_len,
1126 WOLFSSL_FILETYPE_PEM))) {
1129 &key, role, 0);
1130 }
1131 break;
1132 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1133#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
1134 if (!(wolfSSL_use_PrivateKey_buffer(ssl,
1136 (long)key.key.define.private_key_len,
1137 WOLFSSL_FILETYPE_PEM))) {
1140 &key, role, 0);
1141 }
1142 break;
1143#else /* ! HAVE_RPK || ! LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1146 &key, role, 0);
1147#endif /* ! HAVE_RPK || ! LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1148 case COAP_PKI_KEY_DEF_DER: /* define private key */
1149 if (!(wolfSSL_use_PrivateKey_file(ssl,
1151 WOLFSSL_FILETYPE_ASN1))) {
1154 &key, role, 0);
1155 }
1156 break;
1157 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1158 if (!(wolfSSL_use_PrivateKey_buffer(ssl,
1160 (long)key.key.define.private_key_len,
1161 WOLFSSL_FILETYPE_ASN1))) {
1164 &key, role, 0);
1165 }
1166 break;
1167 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1168 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1169 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1170 default:
1173 &key, role, 0);
1174 }
1175 } else if (role == COAP_DTLS_ROLE_SERVER ||
1177 key.key.define.public_cert.u_byte[0])) {
1180 &key, role, 0);
1181 }
1182
1183 /*
1184 * Configure the Public Certificate / Key
1185 */
1186 if (key.key.define.public_cert.u_byte &&
1187 key.key.define.public_cert.u_byte[0]) {
1188 switch (key.key.define.public_cert_def) {
1189 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1190 if (!(wolfSSL_use_certificate_chain_file(ssl,
1191 key.key.define.public_cert.s_byte))) {
1194 &key, role, 0);
1195 }
1196 break;
1197 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1198 if (!(wolfSSL_use_certificate_chain_buffer(ssl,
1200 (long)key.key.define.private_key_len))) {
1203 &key, role, 0);
1204 }
1205 break;
1206 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1207#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
1208 {
1209 unsigned char der_buff[512];
1210 int ret = -1;;
1211 char ctype[] = {WOLFSSL_CERT_TYPE_RPK};
1212 char stype[] = {WOLFSSL_CERT_TYPE_RPK};
1213
1214 wolfSSL_set_client_cert_type(ssl, ctype, sizeof(ctype)/sizeof(ctype[0]));
1215 wolfSSL_set_server_cert_type(ssl, stype, sizeof(stype)/sizeof(stype[0]));
1216
1217 ret = wolfSSL_PubKeyPemToDer(key.key.define.public_cert.u_byte,
1218 (int)key.key.define.public_cert_len,
1219 der_buff, (int)sizeof(der_buff));
1220 if (ret <= 0) {
1221 ret = wolfSSL_KeyPemToDer(key.key.define.public_cert.u_byte,
1222 (int)key.key.define.public_cert_len,
1223 der_buff, (int)sizeof(der_buff), NULL);
1224 if (ret > 0) {
1225 coap_binary_t *spki = get_asn1_spki(der_buff, ret);
1226
1227 if (!spki) {
1230 &key, role, 0);
1231 }
1232 if (!wolfSSL_use_PrivateKey_buffer(ssl, der_buff, ret, WOLFSSL_FILETYPE_ASN1)) {
1235 &key, role, 0);
1236 }
1237 if (!wolfSSL_use_certificate_buffer(ssl, spki->s, spki->length, WOLFSSL_FILETYPE_ASN1)) {
1238 coap_delete_binary(spki);
1241 &key, role, 0);
1242 }
1243 coap_delete_binary(spki);
1244 break;
1245 }
1246 }
1247 if (ret <= 0) {
1250 &key, role, 0);
1251 }
1252 if (!wolfSSL_use_certificate_buffer(ssl, der_buff, ret, WOLFSSL_FILETYPE_ASN1)) {
1255 &key, role, 0);
1256 }
1257 }
1258 break;
1259#else /* ! HAVE_RPK || ! LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1262 &key, role, 0);
1263#endif /* ! HAVE_RPK || ! LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1264 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1265 if (!(wolfSSL_use_certificate_file(ssl,
1267 WOLFSSL_FILETYPE_ASN1))) {
1270 &key, role, 0);
1271 }
1272 break;
1273 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1274 if (!(wolfSSL_use_certificate_buffer(ssl,
1276 (int)key.key.define.public_cert_len,
1277 WOLFSSL_FILETYPE_ASN1))) {
1280 &key, role, 0);
1281 }
1282 break;
1283 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1284 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1285 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1286 default:
1289 &key, role, 0);
1290 }
1291 } else if (role == COAP_DTLS_ROLE_SERVER ||
1293 key.key.define.private_key.u_byte[0])) {
1296 &key, role, 0);
1297 }
1298#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
1299 else {
1300 char stype[] = {WOLFSSL_CERT_TYPE_X509, WOLFSSL_CERT_TYPE_RPK};
1301 wolfSSL_set_server_cert_type(ssl, stype, sizeof(stype)/sizeof(stype[0]));
1302 }
1303#endif /* HAVE_RPK && LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1304
1305 /*
1306 * Configure the CA
1307 */
1308 if (setup_data->check_common_ca && key.key.define.ca.u_byte &&
1309 key.key.define.ca.u_byte[0]) {
1310 switch (key.key.define.ca_def) {
1312 if (!wolfSSL_CTX_load_verify_locations_ex(ctx,
1313 key.key.define.ca.s_byte,
1314 NULL,
1315 setup_data->allow_expired_certs ?
1316 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
1319 &key, role, 0);
1320 }
1321 break;
1322 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1323 if (!wolfSSL_CTX_load_verify_buffer_ex(ctx,
1324 key.key.define.ca.u_byte,
1325 key.key.define.ca_len,
1326 SSL_FILETYPE_PEM,
1327 0,
1328 setup_data->allow_expired_certs ?
1329 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
1332 &key, role, 0);
1333 }
1334 break;
1335 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1336 /* Ignore if set */
1337 break;
1338 case COAP_PKI_KEY_DEF_DER: /* define ca */
1339 if (!wolfSSL_CTX_load_verify_locations_ex(ctx,
1340 key.key.define.ca.s_byte,
1341 NULL,
1342 setup_data->allow_expired_certs ?
1343 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
1346 &key, role, 0);
1347 }
1348 break;
1349 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1350 if (!wolfSSL_CTX_load_verify_buffer_ex(ctx,
1351 key.key.define.ca.u_byte,
1352 key.key.define.ca_len,
1353 SSL_FILETYPE_ASN1,
1354 0,
1355 setup_data->allow_expired_certs ?
1356 WOLFSSL_LOAD_FLAG_DATE_ERR_OKAY : 0)) {
1359 &key, role, 0);
1360 }
1361 break;
1362 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1363 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1364 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1365 default:
1368 &key, role, 0);
1369 }
1370 }
1371 return 1;
1372}
1373
1374static char *
1375get_san_or_cn_from_cert(WOLFSSL_X509 *x509) {
1376 if (x509) {
1377 char *cn;
1378 int n;
1379 WOLF_STACK_OF(WOLFSSL_GENERAL_NAME) *san_list;
1380 char buffer[256];
1381
1382 buffer[0] = '\000';
1383 san_list = wolfSSL_X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
1384 if (san_list) {
1385 int san_count = wolfSSL_sk_GENERAL_NAME_num(san_list);
1386
1387 for (n = 0; n < san_count; n++) {
1388 const WOLFSSL_GENERAL_NAME *name = wolfSSL_sk_GENERAL_NAME_value(san_list, n);
1389
1390 if (name->type == GEN_DNS) {
1391 const char *dns_name = (const char *)wolfSSL_ASN1_STRING_get0_data(name->d.dNSName);
1392
1393 /* Make sure that there is not an embedded NUL in the dns_name */
1394 if (wolfSSL_ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
1395 continue;
1396 cn = wolfssl_strdup(dns_name);
1397 wolfSSL_sk_GENERAL_NAME_pop_free(san_list, wolfSSL_GENERAL_NAME_free);
1398 return cn;
1399 }
1400 }
1401 wolfSSL_sk_GENERAL_NAME_pop_free(san_list, wolfSSL_GENERAL_NAME_free);
1402 }
1403 /* Otherwise look for the CN= field */
1404 wolfSSL_X509_NAME_oneline(wolfSSL_X509_get_subject_name((WOLFSSL_X509 *)(x509)), buffer,
1405 sizeof(buffer));
1406
1407 /* Need to emulate strcasestr() here. Looking for CN= */
1408 n = (int)strlen(buffer) - 3;
1409 cn = buffer;
1410 while (n > 0) {
1411 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
1412 ((cn[1] == 'N') || (cn[1] == 'n')) &&
1413 (cn[2] == '=')) {
1414 cn += 3;
1415 break;
1416 }
1417 cn++;
1418 n--;
1419 }
1420 if (n > 0) {
1421 char *ecn = strchr(cn, '/');
1422 if (ecn) {
1423 return wolfssl_strndup(cn, ecn-cn);
1424 } else {
1425 return wolfssl_strdup(cn);
1426 }
1427 }
1428 }
1429 return NULL;
1430}
1431
1432static int
1433tls_verify_call_back(int preverify_ok, WOLFSSL_X509_STORE_CTX *ctx) {
1434 WOLFSSL *ssl = wolfSSL_X509_STORE_CTX_get_ex_data(ctx,
1435 wolfSSL_get_ex_data_X509_STORE_CTX_idx());
1436 coap_session_t *session = wolfSSL_get_app_data(ssl);
1437 coap_wolfssl_context_t *w_context =
1438 ((coap_wolfssl_context_t *)session->context->dtls_context);
1439 coap_dtls_pki_t *setup_data = &w_context->setup_data;
1440 int depth = wolfSSL_X509_STORE_CTX_get_error_depth(ctx);
1441 int err = wolfSSL_X509_STORE_CTX_get_error(ctx);
1442 WOLFSSL_X509 *x509 = wolfSSL_X509_STORE_CTX_get_current_cert(ctx);
1443 char *cn = NULL;
1444 int keep_preverify_ok = preverify_ok;
1445
1446 if (setup_data->is_rpk_not_cert) {
1447 cn = wolfssl_strdup("RPK");
1448 } else {
1449 cn = get_san_or_cn_from_cert(x509);
1450 }
1451 if (!preverify_ok) {
1452 switch (err) {
1453 case X509_V_ERR_CERT_NOT_YET_VALID:
1454 case X509_V_ERR_CERT_HAS_EXPIRED:
1455 case ASN_NO_SIGNER_E:
1456 case ASN_AFTER_DATE_E:
1457 if (setup_data->allow_expired_certs)
1458 preverify_ok = 1;
1459 break;
1460 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1461 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
1462 preverify_ok = 1;
1463 break;
1464 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
1465 if (!setup_data->verify_peer_cert)
1466 preverify_ok = 1;
1467 break;
1468 case X509_V_ERR_UNABLE_TO_GET_CRL:
1469 if (setup_data->allow_no_crl)
1470 preverify_ok = 1;
1471 break;
1472 case X509_V_ERR_CRL_NOT_YET_VALID:
1473 case X509_V_ERR_CRL_HAS_EXPIRED:
1474 if (setup_data->allow_expired_crl)
1475 preverify_ok = 1;
1476 break;
1477 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1478 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1479 case X509_V_ERR_AKID_SKID_MISMATCH:
1480 if (!setup_data->verify_peer_cert)
1481 preverify_ok = 1;
1482 break;
1483 default:
1484 break;
1485 }
1486 if (setup_data->cert_chain_validation &&
1487 depth > (setup_data->cert_chain_verify_depth + 1)) {
1488 preverify_ok = 0;
1489 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
1490 wolfSSL_X509_STORE_CTX_set_error(ctx, err);
1491 }
1492 if (!preverify_ok) {
1493 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
1494 coap_log_warn(" %s: %s: '%s' depth=%d\n",
1495 coap_session_str(session),
1496 "Unknown CA", cn ? cn : "?", depth);
1497 } else {
1498 coap_log_warn(" %s: %s: '%s' depth=%d\n",
1499 coap_session_str(session),
1500 wolfSSL_X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1501 }
1502 } else {
1503 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
1504 coap_session_str(session),
1505 wolfSSL_X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1506 }
1507 }
1508 /* Certificate - depth == 0 is the Client Cert */
1509 if (setup_data->validate_cn_call_back && keep_preverify_ok) {
1510 int length = wolfSSL_i2d_X509(x509, NULL);
1511
1512 if (length > 0) {
1513 uint8_t *base_buf;
1514 uint8_t *base_buf2 = base_buf = wolfssl_malloc(length);
1515
1516 /* base_buf2 gets moved to the end */
1517 wolfSSL_i2d_X509(x509, &base_buf2);
1518 if (!setup_data->validate_cn_call_back(cn, base_buf, length, session,
1519 depth, preverify_ok,
1520 setup_data->cn_call_back_arg)) {
1521 if (depth == 0) {
1522 wolfSSL_X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
1523 } else {
1524 wolfSSL_X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
1525 }
1526 preverify_ok = 0;
1527 }
1528 wolfssl_free(base_buf);
1529 }
1530 }
1531 wolfssl_free(cn);
1532 return preverify_ok;
1533}
1534
1535#if COAP_SERVER_SUPPORT
1536
1537/*
1538 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
1539 * called so it is possible to set up an extra callback to determine whether
1540 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
1541 *
1542 * Set up by SSL_CTX_set_tlsext_servername_callback() in
1543 * coap_dtls_context_set_pki()
1544 */
1545static int
1546tls_server_name_call_back(WOLFSSL *ssl,
1547 int *sd COAP_UNUSED,
1548 void *arg) {
1549 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
1550 coap_session_t *session = (coap_session_t *)wolfSSL_get_app_data(ssl);
1551 coap_wolfssl_context_t *w_context =
1552 ((coap_wolfssl_context_t *)session->context->dtls_context);
1553
1554 if (!ssl) {
1555 return noack_return;
1556 }
1557
1558 if (setup_data->validate_sni_call_back) {
1559 /* SNI checking requested */
1560 const char *sni = wolfSSL_get_servername(ssl, WOLFSSL_SNI_HOST_NAME);
1561 coap_dtls_pki_t sni_setup_data;
1562 coap_dtls_key_t *new_entry;
1563
1564 if (!sni || !sni[0]) {
1565 sni = "";
1566 }
1567 new_entry = setup_data->validate_sni_call_back(sni,
1568 setup_data->sni_call_back_arg);
1569 if (!new_entry) {
1570 return fatal_return;
1571 }
1572 sni_setup_data = *setup_data;
1573 sni_setup_data.pki_key = *new_entry;
1574 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
1575 }
1576
1577 if (w_context->psk_pki_enabled & IS_PSK) {
1578 wolfSSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1579 }
1580 return SSL_TLSEXT_ERR_OK;
1581}
1582
1583/*
1584 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
1585 * called to see if SNI is being used.
1586 *
1587 * Set up by SSL_CTX_set_tlsext_servername_callback()
1588 * in coap_dtls_context_set_spsk()
1589 */
1590static int
1591psk_tls_server_name_call_back(WOLFSSL *ssl,
1592 int *sd COAP_UNUSED,
1593 void *arg
1594 ) {
1595 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
1596 coap_session_t *c_session = (coap_session_t *)wolfSSL_get_app_data(ssl);
1597 coap_wolfssl_context_t *w_context =
1598 ((coap_wolfssl_context_t *)c_session->context->dtls_context);
1599
1600 if (!ssl) {
1601 return noack_return;
1602 }
1603
1604 if (setup_data->validate_sni_call_back) {
1605 /* SNI checking requested */
1606 const char *sni = wolfSSL_get_servername(ssl, WOLFSSL_SNI_HOST_NAME);
1607 char lhint[COAP_DTLS_HINT_LENGTH];
1608 const coap_dtls_spsk_info_t *new_entry;
1609
1610 if (!sni || !sni[0]) {
1611 sni = "";
1612 }
1613 new_entry = setup_data->validate_sni_call_back(sni,
1614 c_session,
1615 setup_data->sni_call_back_arg);
1617 &new_entry->key);
1618 snprintf(lhint, sizeof(lhint), "%.*s",
1619 (int)new_entry->hint.length,
1620 new_entry->hint.s);
1621 wolfSSL_use_psk_identity_hint(ssl, lhint);
1622 }
1623
1624 if (w_context->psk_pki_enabled & IS_PSK) {
1625 wolfSSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
1626 }
1627 return SSL_TLSEXT_ERR_OK;
1628}
1629#endif /* COAP_SERVER_SUPPORT */
1630
1631int
1633 const coap_dtls_pki_t *setup_data,
1634 const coap_dtls_role_t role) {
1635 coap_wolfssl_context_t *w_context =
1636 ((coap_wolfssl_context_t *)ctx->dtls_context);
1637
1638 if (!setup_data)
1639 return 0;
1640
1641 w_context->setup_data = *setup_data;
1642 if (!w_context->setup_data.verify_peer_cert) {
1643 /* Needs to be clear so that no CA DNs are transmitted */
1644 w_context->setup_data.check_common_ca = 0;
1645 if (w_context->setup_data.is_rpk_not_cert) {
1646 /* Disable all of these as they cannot be checked */
1647 w_context->setup_data.allow_self_signed = 0;
1648 w_context->setup_data.allow_expired_certs = 0;
1649 w_context->setup_data.cert_chain_validation = 0;
1650 w_context->setup_data.cert_chain_verify_depth = 0;
1651 w_context->setup_data.check_cert_revocation = 0;
1652 w_context->setup_data.allow_no_crl = 0;
1653 w_context->setup_data.allow_expired_crl = 0;
1654 w_context->setup_data.allow_bad_md_hash = 0;
1655 w_context->setup_data.allow_short_rsa_length = 0;
1656 } else {
1657 /* Allow all of these but warn if issue */
1658 w_context->setup_data.allow_self_signed = 1;
1659 w_context->setup_data.allow_expired_certs = 1;
1660 w_context->setup_data.cert_chain_validation = 1;
1661 w_context->setup_data.cert_chain_verify_depth = 10;
1662 w_context->setup_data.check_cert_revocation = 1;
1663 w_context->setup_data.allow_no_crl = 1;
1664 w_context->setup_data.allow_expired_crl = 1;
1665 w_context->setup_data.allow_bad_md_hash = 1;
1666 w_context->setup_data.allow_short_rsa_length = 1;
1667 }
1668 }
1669#if COAP_SERVER_SUPPORT
1670 if (role == COAP_DTLS_ROLE_SERVER) {
1671 if (!setup_dtls_context(w_context))
1672 return 0;
1673 if (w_context->dtls.ctx) {
1674#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
1675 char ctype[] = {WOLFSSL_CERT_TYPE_RPK};
1676 char stype[] = {WOLFSSL_CERT_TYPE_RPK};
1677#endif /* HAVE_RPK && LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1678
1679 wolfSSL_CTX_set_servername_arg(w_context->dtls.ctx,
1680 &w_context->setup_data);
1681 wolfSSL_CTX_set_tlsext_servername_callback(w_context->dtls.ctx,
1682 tls_server_name_call_back);
1683
1684#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
1685 if (w_context->setup_data.is_rpk_not_cert) {
1686 wolfSSL_CTX_set_client_cert_type(w_context->dtls.ctx, ctype, sizeof(ctype)/sizeof(ctype[0]));
1687 wolfSSL_CTX_set_server_cert_type(w_context->dtls.ctx, stype, sizeof(stype)/sizeof(stype[0]));
1688 }
1689#endif /* HAVE_RPK && LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
1690 }
1691#if !COAP_DISABLE_TCP
1692 if (!setup_tls_context(w_context))
1693 return 0;
1694 if (w_context->tls.ctx) {
1695 wolfSSL_CTX_set_servername_arg(w_context->tls.ctx,
1696 &w_context->setup_data);
1697 wolfSSL_CTX_set_tlsext_servername_callback(w_context->tls.ctx,
1698 tls_server_name_call_back);
1699
1700 /* For TLS only */
1701 wolfSSL_CTX_set_alpn_select_cb(w_context->tls.ctx,
1702 server_alpn_callback, NULL);
1703 }
1704#endif /* !COAP_DISABLE_TCP */
1705 /* Certificate Revocation */
1706 if (w_context->setup_data.check_cert_revocation) {
1707 WOLFSSL_X509_VERIFY_PARAM *param;
1708
1709 param = wolfSSL_X509_VERIFY_PARAM_new();
1710 wolfSSL_X509_VERIFY_PARAM_set_flags(param, WOLFSSL_CRL_CHECK);
1711 wolfSSL_CTX_set1_param(w_context->dtls.ctx, param);
1712#if !COAP_DISABLE_TCP
1713 wolfSSL_CTX_set1_param(w_context->tls.ctx, param);
1714#endif /* !COAP_DISABLE_TCP */
1715 wolfSSL_X509_VERIFY_PARAM_free(param);
1716 }
1717 /* Verify Peer */
1718 if (w_context->setup_data.verify_peer_cert) {
1719 wolfSSL_CTX_set_verify(w_context->dtls.ctx,
1720 WOLFSSL_VERIFY_PEER |
1721 WOLFSSL_VERIFY_CLIENT_ONCE |
1722 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1723 tls_verify_call_back);
1724#if !COAP_DISABLE_TCP
1725 wolfSSL_CTX_set_verify(w_context->tls.ctx,
1726 WOLFSSL_VERIFY_PEER |
1727 WOLFSSL_VERIFY_CLIENT_ONCE |
1728 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1729 tls_verify_call_back);
1730#endif /* !COAP_DISABLE_TCP */
1731 } else {
1732 wolfSSL_CTX_set_verify(w_context->dtls.ctx,
1733 WOLFSSL_VERIFY_NONE, tls_verify_call_back);
1734#if !COAP_DISABLE_TCP
1735 wolfSSL_CTX_set_verify(w_context->tls.ctx,
1736 WOLFSSL_VERIFY_NONE, tls_verify_call_back);
1737#endif /* !COAP_DISABLE_TCP */
1738 }
1739
1740 /* Check CA Chain */
1741 if (w_context->setup_data.cert_chain_validation) {
1742 wolfSSL_CTX_set_verify_depth(w_context->dtls.ctx,
1743 setup_data->cert_chain_verify_depth + 1);
1744#if !COAP_DISABLE_TCP
1745 wolfSSL_CTX_set_verify_depth(w_context->tls.ctx,
1746 setup_data->cert_chain_verify_depth + 1);
1747#endif /* !COAP_DISABLE_TCP */
1748 }
1749 }
1750#else /* ! COAP_SERVER_SUPPORT */
1751 (void)role;
1752#endif /* ! COAP_SERVER_SUPPORT */
1753
1754 w_context->psk_pki_enabled |= IS_PKI;
1755 return 1;
1756}
1757
1758int
1760 const char *ca_file,
1761 const char *ca_dir) {
1762 coap_wolfssl_context_t *w_context =
1763 ((coap_wolfssl_context_t *)ctx->dtls_context);
1764
1765 if (!w_context) {
1766 coap_log_warn("coap_context_set_pki_root_cas: (D)TLS environment "
1767 "not set up\n");
1768 return 0;
1769 }
1770 if (ca_file == NULL && ca_dir == NULL) {
1771 coap_log_warn("coap_context_set_pki_root_cas: ca_file and/or ca_dir "
1772 "not defined\n");
1773 return 0;
1774 }
1775 if (w_context->root_ca_file) {
1776 wolfssl_free(w_context->root_ca_file);
1777 w_context->root_ca_file = NULL;
1778 }
1779 if (ca_file) {
1780 w_context->root_ca_file = wolfssl_strdup(ca_file);
1781 }
1782 if (w_context->root_ca_dir) {
1783 wolfssl_free(w_context->root_ca_dir);
1784 w_context->root_ca_dir = NULL;
1785 }
1786 if (ca_dir) {
1787 w_context->root_ca_dir = wolfssl_strdup(ca_dir);
1788 }
1789 return 1;
1790}
1791
1792int
1794 coap_wolfssl_context_t *w_context =
1795 ((coap_wolfssl_context_t *)ctx->dtls_context);
1796 return w_context->psk_pki_enabled ? 1 : 0;
1797}
1798
1799
1800void
1801coap_dtls_free_context(void *handle) {
1802 coap_wolfssl_context_t *w_context = (coap_wolfssl_context_t *)handle;
1803
1804 if (!w_context)
1805 return;
1806 wolfssl_free(w_context->root_ca_file);
1807 wolfssl_free(w_context->root_ca_dir);
1808
1809 if (w_context->dtls.ctx)
1810 wolfSSL_CTX_free(w_context->dtls.ctx);
1811 if (w_context->dtls.cookie_hmac)
1812 wolfSSL_HMAC_CTX_free(w_context->dtls.cookie_hmac);
1813
1814#if !COAP_DISABLE_TCP
1815 if (w_context->tls.ctx)
1816 wolfSSL_CTX_free(w_context->tls.ctx);
1817#endif /* !COAP_DISABLE_TCP */
1818 wolfssl_free(w_context);
1819}
1820
1821#if COAP_SERVER_SUPPORT
1822void *
1824 coap_wolfssl_context_t *w_context =
1825 ((coap_wolfssl_context_t *)session->context->dtls_context);
1826 coap_dtls_context_t *dtls;
1827 WOLFSSL *ssl = NULL;
1828 int r;
1829 const coap_bin_const_t *psk_hint;
1830 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
1831 coap_tick_t now;
1832
1833 if (!w_env)
1834 goto error;
1835
1836 if (!setup_dtls_context(w_context))
1837 goto error;
1838 dtls = &w_context->dtls;
1839
1840 ssl = wolfSSL_new(dtls->ctx);
1841 if (!ssl) {
1842 goto error;
1843 }
1844 wolfSSL_set_app_data(ssl, NULL);
1845 wolfSSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
1846#ifdef WOLFSSL_DTLS_MTU
1847 wolfSSL_dtls_set_mtu(ssl, (long)session->mtu);
1848#endif /* WOLFSSL_DTLS_MTU */
1849 w_env->ssl = ssl;
1850 wolfSSL_SetIOWriteCtx(ssl, w_env);
1851 wolfSSL_SetIOReadCtx(ssl, w_env);
1852 wolfSSL_set_app_data(ssl, session);
1853 w_env->data.session = session;
1854
1855#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
1856 if (wolfSSL_send_hrr_cookie(ssl, NULL, 0) != WOLFSSL_SUCCESS)
1857 coap_log_debug("Error: Unable to set cookie with Hello Retry Request\n");
1858#endif /* WOLFSSL_DTLS13 && WOLFSSL_SEND_HRR_COOKIE */
1859
1860#ifdef HAVE_SERVER_RENEGOTIATION_INFO
1861 if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) {
1862 coap_log_debug("Error: wolfSSL_UseSecureRenegotiation failed\n");
1863 }
1864#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
1865
1866 if (w_context->psk_pki_enabled & IS_PSK) {
1867 /* hint may get updated if/when handling SNI callback */
1868 psk_hint = coap_get_session_server_psk_hint(session);
1869 if (psk_hint != NULL && psk_hint->length) {
1870 char *hint = wolfssl_malloc(psk_hint->length + 1);
1871
1872 if (hint) {
1873 memcpy(hint, psk_hint->s, psk_hint->length);
1874 hint[psk_hint->length] = '\000';
1875 wolfSSL_use_psk_identity_hint(ssl, hint);
1876 wolfssl_free(hint);
1877 } else {
1878 coap_log_warn("hint malloc failure\n");
1879 }
1880 }
1881 }
1882 if (w_context->psk_pki_enabled & IS_PKI) {
1883 if (!setup_pki_ssl(ssl, &w_context->setup_data, COAP_DTLS_ROLE_SERVER))
1884 goto error;
1885 }
1886
1887#if defined(WOLFSSL_DTLS_CH_FRAG) && defined(WOLFSSL_DTLS13)
1888 if (wolfSSL_dtls13_allow_ch_frag(ssl, 1) != WOLFSSL_SUCCESS) {
1889 coap_log_debug("Error: wolfSSL_dtls13_allow_ch_frag failed\n");
1890 }
1891#endif /* WOLFSSL_DTLS_CH_FRAG && WOLFSSL_DTLS13 */
1892
1893 coap_ticks(&now);
1894 w_env->last_timeout = now;
1895 w_env->ssl = ssl;
1896
1897 r = wolfSSL_accept(ssl);
1898 if (r == -1) {
1899 int err = wolfSSL_get_error(ssl, r);
1900 if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE)
1901 r = 0;
1902 }
1903
1904 if (r == 0) {
1905 goto error;
1906 }
1907
1908 return w_env;
1909
1910error:
1911 if (ssl)
1912 wolfSSL_free(ssl);
1913 coap_dtls_free_wolfssl_env(w_env);
1914 return NULL;
1915}
1916#endif /* COAP_SERVER_SUPPORT */
1917
1918#if COAP_CLIENT_SUPPORT
1919static int
1920setup_client_ssl_session(coap_session_t *session, WOLFSSL *ssl) {
1921 coap_wolfssl_context_t *w_context =
1922 ((coap_wolfssl_context_t *)session->context->dtls_context);
1923
1924 if (w_context->psk_pki_enabled & IS_PSK) {
1925 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
1926
1927 if (setup_data->validate_ih_call_back) {
1928 if (session->proto == COAP_PROTO_DTLS) {
1929 wolfSSL_set_max_proto_version(ssl,
1930 DTLS1_2_VERSION);
1931 }
1932#if !COAP_DISABLE_TCP
1933 else {
1934 wolfSSL_set_max_proto_version(ssl,
1935 TLS1_2_VERSION);
1936 wolfSSL_set_options(ssl, WOLFSSL_OP_NO_TLSv1_3);
1937 }
1938#endif /* !COAP_DISABLE_TCP */
1939 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
1940 }
1941 set_ciphersuites(ssl, COAP_ENC_PSK);
1942
1943 /* Issue SNI if requested */
1944 if (setup_data->client_sni &&
1945 wolfSSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
1946 coap_log_warn("wolfSSL_set_tlsext_host_name: set '%s' failed",
1947 setup_data->client_sni);
1948 }
1949 wolfSSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
1950 }
1951 if (w_context->psk_pki_enabled & IS_PKI) {
1952 coap_dtls_pki_t *setup_data = &w_context->setup_data;
1953
1954 set_ciphersuites(ssl, COAP_ENC_PKI);
1955 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
1956 return 0;
1957 /* libcoap is managing (D)TLS connection based on setup_data options */
1958#if !COAP_DISABLE_TCP
1959 if (session->proto == COAP_PROTO_TLS)
1960 wolfSSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
1961#endif /* !COAP_DISABLE_TCP */
1962
1963 /* Issue SNI if requested */
1964 if (setup_data->client_sni &&
1965 wolfSSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
1966 coap_log_warn("wolfSSL_set_tlsext_host_name: set '%s' failed",
1967 setup_data->client_sni);
1968 }
1969 /* Certificate Revocation */
1970 if (setup_data->check_cert_revocation) {
1971 WOLFSSL_X509_VERIFY_PARAM *param;
1972
1973 param = wolfSSL_X509_VERIFY_PARAM_new();
1974 wolfSSL_X509_VERIFY_PARAM_set_flags(param, WOLFSSL_CRL_CHECK);
1975 WOLFSSL_CTX *ctx = wolfSSL_get_SSL_CTX(ssl);
1976 /* TODO: we cannot set parameters at ssl level with wolfSSL, review*/
1977 wolfSSL_CTX_set1_param(ctx, param);
1978 wolfSSL_X509_VERIFY_PARAM_free(param);
1979 }
1980 /* Verify Peer */
1981 if (setup_data->verify_peer_cert)
1982 wolfSSL_set_verify(ssl,
1983 WOLFSSL_VERIFY_PEER |
1984 WOLFSSL_VERIFY_CLIENT_ONCE |
1985 WOLFSSL_VERIFY_FAIL_IF_NO_PEER_CERT,
1986 tls_verify_call_back);
1987 else
1988 wolfSSL_set_verify(ssl, WOLFSSL_VERIFY_NONE, tls_verify_call_back);
1989
1990 /* Check CA Chain */
1991 if (setup_data->cert_chain_validation)
1992 wolfSSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
1993
1994 }
1995 return 1;
1996}
1997
1998void *
2000 WOLFSSL *ssl = NULL;
2001 int r;
2002 coap_wolfssl_context_t *w_context =
2003 ((coap_wolfssl_context_t *)session->context->dtls_context);
2004 coap_dtls_context_t *dtls;
2005 coap_wolfssl_env_t *w_env =
2006 coap_dtls_new_wolfssl_env(session, COAP_DTLS_ROLE_CLIENT);
2007 coap_tick_t now;
2008
2009 if (!w_env)
2010 goto error;
2011
2012 if (!setup_dtls_context(w_context))
2013 goto error;
2014 dtls = &w_context->dtls;
2015
2016 ssl = wolfSSL_new(dtls->ctx);
2017 if (!ssl) {
2018 goto error;
2019 }
2020 w_env->data.session = session;
2021 wolfSSL_set_app_data(ssl, session);
2022 wolfSSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
2023 wolfSSL_SetIOWriteCtx(ssl, w_env);
2024 wolfSSL_SetIOReadCtx(ssl, w_env);
2025#ifdef WOLFSSL_DTLS_MTU
2026 wolfSSL_dtls_set_mtu(ssl, (long)session->mtu);
2027#endif /* WOLFSSL_DTLS_MTU */
2028
2029 if (!setup_client_ssl_session(session, ssl))
2030 goto error;
2031#ifdef HAVE_SERVER_RENEGOTIATION_INFO
2032 if (wolfSSL_UseSecureRenegotiation(ssl) != WOLFSSL_SUCCESS) {
2033 coap_log_debug("Error: wolfSSL_UseSecureRenegotiation failed\n");
2034 }
2035#endif /* HAVE_SERVER_RENEGOTIATION_INFO */
2036
2037 session->dtls_timeout_count = 0;
2038
2039#if defined(WOLFSSL_DTLS13) && defined(WOLFSSL_SEND_HRR_COOKIE)
2040 wolfSSL_NoKeyShares(ssl);
2041#endif /* WOLFSSL_DTLS13 && WOLFSSL_SEND_HRR_COOKIE */
2042 r = wolfSSL_connect(ssl);
2043 if (r == -1) {
2044 int ret = wolfSSL_get_error(ssl, r);
2045 if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE)
2046 r = 0;
2047 }
2048
2049 if (r == 0)
2050 goto error;
2051
2052 coap_ticks(&now);
2053 w_env->last_timeout = now;
2054 w_env->ssl = ssl;
2055 return w_env;
2056
2057error:
2058 if (ssl)
2059 wolfSSL_free(ssl);
2060 return NULL;
2061}
2062
2063void
2065#ifdef WOLFSSL_DTLS_MTU
2066 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2067 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2068
2069 if (ssl)
2070 wolfSSL_dtls_set_mtu(ssl, (long)session->mtu); /* Instead of SSL_set_mtu */
2071#else /* ! WOLFSSL_DTLS_MTU */
2072 (void)session;
2073#endif /* ! WOLFSSL_DTLS_MTU */
2074}
2075#endif /* COAP_CLIENT_SUPPORT */
2076
2077void
2079 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2080 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2081
2082 if (ssl) {
2083 if (!wolfSSL_SSL_in_init(ssl) && !(wolfSSL_get_shutdown(ssl) & WOLFSSL_SENT_SHUTDOWN)) {
2084 int r = wolfSSL_shutdown(ssl);
2085 if (r == 0)
2086 wolfSSL_shutdown(ssl);
2087 }
2088 w_env->ssl = NULL;
2089 wolfSSL_free(ssl);
2090 if (session->context)
2092 }
2093 coap_dtls_free_wolfssl_env(w_env);
2094}
2095
2096ssize_t
2098 const uint8_t *data, size_t data_len) {
2099 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2100 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2101 int r;
2102
2103 assert(ssl != NULL);
2104
2105 session->dtls_event = -1;
2106 coap_log_debug("* %s: dtls: sent %4d bytes\n",
2107 coap_session_str(session), (int)data_len);
2108 r = wolfSSL_write(ssl, data, (int)data_len);
2109
2110 if (r <= 0) {
2111 int err = wolfSSL_get_error(ssl, r);
2112 if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) {
2113 r = 0;
2114 } else {
2115 coap_log_warn("coap_dtls_send: cannot send PDU\n");
2116 if (err == WOLFSSL_ERROR_ZERO_RETURN)
2118 else if (err == WOLFSSL_ERROR_SSL)
2120 r = -1;
2121 }
2122 }
2123
2124 if (session->dtls_event >= 0) {
2125 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2126 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2127 coap_handle_event_lkd(session->context, session->dtls_event, session);
2128 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2129 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2131 r = -1;
2132 }
2133 }
2134
2135 return r;
2136}
2137
2138int
2140 return 0;
2141}
2142
2144coap_dtls_get_context_timeout(void *dtls_context) {
2145 (void)dtls_context;
2146 return 0;
2147}
2148
2151 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2152 unsigned int scalar;
2153
2154 if (!w_env)
2155 return now;
2156
2157 assert(session->state == COAP_SESSION_STATE_HANDSHAKE);
2158
2159 scalar = 1 << w_env->retry_scalar;
2160 if (w_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
2161 /* Need to indicate remaining timeout time */
2162 return w_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
2163 }
2164 return now;
2165}
2166
2167/*
2168 * return 1 timed out
2169 * 0 still timing out
2170 */
2171int
2173 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2174 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2175
2176 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
2177 w_env->retry_scalar++;
2178 if (++session->dtls_timeout_count > session->max_retransmit) {
2179 /* Too many retries */
2181 return 1;
2182 }
2183 wolfSSL_dtls_retransmit(ssl);
2184 return 0;
2185}
2186
2187#if COAP_SERVER_SUPPORT
2188
2189int
2191 const uint8_t *data, size_t data_len) {
2192 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2193 coap_ssl_data_t *ssl_data;
2194
2195 if (!w_env) {
2196 w_env = coap_dtls_new_wolfssl_env(session, COAP_DTLS_ROLE_SERVER);
2197 if (w_env) {
2198 session->tls = w_env;
2199 } else {
2200 /* error should have already been reported */
2201 return -1;
2202 }
2203 }
2204
2205 ssl_data = w_env ? &w_env->data : NULL;
2206 assert(ssl_data != NULL);
2207
2208 if (ssl_data->pdu_len) {
2209 coap_log_err("** %s: Previous data not read %u bytes\n",
2210 coap_session_str(session), ssl_data->pdu_len);
2211 }
2212
2213 ssl_data->session = session;
2214 ssl_data->pdu = data;
2215 ssl_data->pdu_len = (unsigned)data_len;
2216
2217 return 1;
2218}
2219
2220#endif /* COAP_SERVER_SUPPORT */
2221
2222int
2223coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
2224 coap_ssl_data_t *ssl_data;
2225 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2226 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2227 int r;
2228 int in_init = wolfSSL_SSL_in_init(ssl);
2229 uint8_t pdu[COAP_RXBUFFER_SIZE];
2230
2231 assert(ssl != NULL);
2232
2233 ssl_data = &w_env->data;
2234
2235 if (ssl_data->pdu_len) {
2236 coap_log_err("** %s: Previous data not read %u bytes\n",
2237 coap_session_str(session), ssl_data->pdu_len);
2238 }
2239 ssl_data->pdu = data;
2240 ssl_data->pdu_len = (unsigned)data_len;
2241
2242 session->dtls_event = -1;
2243 r = wolfSSL_read(ssl, pdu, (int)sizeof(pdu));
2244 if (r > 0) {
2245 coap_log_debug("* %s: dtls: recv %4d bytes\n",
2246 coap_session_str(session), r);
2247 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
2248 goto finished;
2249 } else {
2250 int err = wolfSSL_get_error(ssl, r);
2251 if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) {
2252 if (in_init && wolfSSL_is_init_finished(ssl)) {
2253 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
2254 coap_session_str(session), wolfSSL_get_cipher((ssl)));
2256 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2257 }
2258 r = 0;
2259 } else if (err == APP_DATA_READY) {
2260 r = wolfSSL_read(ssl, pdu, (int)sizeof(pdu));
2261 if (r > 0) {
2262 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
2263 goto finished;
2264 }
2266 r = -1;
2267 } else {
2268 if (err == WOLFSSL_ERROR_ZERO_RETURN) {
2269 /* Got a close notify alert from the remote side */
2271 } else {
2273 if (err == FATAL_ERROR) {
2274 WOLFSSL_ALERT_HISTORY h;
2275
2276 if (wolfSSL_get_alert_history(ssl, &h) == WOLFSSL_SUCCESS) {
2277 if (h.last_rx.code != close_notify && h.last_rx.code != -1) {
2278 coap_log_warn("***%s: Alert '%d': %s\n",
2279 coap_session_str(session), h.last_rx.code,
2280 wolfSSL_alert_desc_string_long(h.last_rx.code));
2281 }
2282 }
2283 }
2284 }
2285 r = -1;
2286 }
2287 if (session->dtls_event >= 0) {
2288 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2289 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2290 coap_handle_event_lkd(session->context, session->dtls_event, session);
2291 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2292 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2294 ssl_data = NULL;
2295 r = -1;
2296 }
2297 }
2298 }
2299
2300finished:
2301 if (ssl_data && ssl_data->pdu_len) {
2302 /* pdu data is held on stack which will not stay there */
2303 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
2304 ssl_data->pdu_len = 0;
2305 ssl_data->pdu = NULL;
2306 }
2307 return r;
2308}
2309
2310unsigned int
2312 unsigned int overhead = 37;
2313 const WOLFSSL_CIPHER *s_ciph = NULL;
2314 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2315 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2316
2317 if (ssl != NULL)
2318 s_ciph = wolfSSL_get_current_cipher(ssl);
2319 if (s_ciph) {
2320 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
2321
2322 const WOLFSSL_EVP_CIPHER *e_ciph;
2323 const WOLFSSL_EVP_MD *e_md;
2324 char cipher[128];
2325
2326 e_ciph = wolfSSL_EVP_get_cipherbynid(wolfSSL_CIPHER_get_cipher_nid(s_ciph));
2327
2328 switch (WOLFSSL_EVP_CIPHER_mode(e_ciph)) {
2329
2330 case WOLFSSL_EVP_CIPH_GCM_MODE:
2331#ifndef WOLFSSL_EVP_GCM_TLS_EXPLICIT_IV_LEN
2332#define WOLFSSL_EVP_GCM_TLS_EXPLICIT_IV_LEN 8
2333#endif
2334#ifndef WOLFSSL_EVP_GCM_TLS_TAG_LEN
2335#define WOLFSSL_EVP_GCM_TLS_TAG_LEN 16
2336#endif
2337 ivlen = WOLFSSL_EVP_GCM_TLS_EXPLICIT_IV_LEN;
2338 maclen = WOLFSSL_EVP_GCM_TLS_TAG_LEN;
2339 break;
2340
2341 case WOLFSSL_EVP_CIPH_CCM_MODE:
2342#ifndef WOLFSSL_EVP_CCM_TLS_EXPLICIT_IV_LEN
2343#define WOLFSSL_EVP_CCM_TLS_EXPLICIT_IV_LEN 8
2344#endif
2345 ivlen = WOLFSSL_EVP_CCM_TLS_EXPLICIT_IV_LEN;
2346 wolfSSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
2347 if (strstr(cipher, "CCM8"))
2348 maclen = 8;
2349 else
2350 maclen = 16;
2351 break;
2352
2353 case WOLFSSL_EVP_CIPH_CBC_MODE:
2354 e_md = wolfSSL_EVP_get_digestbynid(wolfSSL_CIPHER_get_digest_nid(s_ciph));
2355 blocksize = wolfSSL_EVP_CIPHER_block_size(e_ciph);
2356 ivlen = wolfSSL_EVP_CIPHER_iv_length(e_ciph);
2357 pad = 1;
2358 maclen = wolfSSL_EVP_MD_size(e_md);
2359 break;
2360
2361 case WOLFSSL_EVP_CIPH_STREAM_CIPHER:
2362 /* Seen with PSK-CHACHA20-POLY1305 */
2363 ivlen = 8;
2364 maclen = 8;
2365 break;
2366
2367 default:
2368 wolfSSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
2369 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
2370 cipher);
2371 ivlen = 8;
2372 maclen = 16;
2373 break;
2374 }
2375#ifndef WOLFSSL_DTLS13_RT_HEADER_LENGTH
2376#define WOLFSSL_DTLS13_RT_HEADER_LENGTH 13
2377#endif
2378 overhead = WOLFSSL_DTLS13_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 +
2379 pad;
2380 }
2381 return overhead;
2382}
2383
2384#if !COAP_DISABLE_TCP
2385#if COAP_CLIENT_SUPPORT
2386void *
2388 WOLFSSL *ssl = NULL;
2389 int r;
2390 coap_wolfssl_context_t *w_context =
2391 ((coap_wolfssl_context_t *)session->context->dtls_context);
2392 coap_tls_context_t *tls;
2393 coap_wolfssl_env_t *w_env =
2394 coap_dtls_new_wolfssl_env(session, COAP_DTLS_ROLE_CLIENT);
2395 coap_tick_t now;
2396
2397 if (!w_env)
2398 goto error;
2399
2400 if (!setup_tls_context(w_context))
2401 goto error;
2402 tls = &w_context->tls;
2403
2404 ssl = wolfSSL_new(tls->ctx);
2405 if (!ssl)
2406 goto error;
2407 wolfSSL_SetIOWriteCtx(ssl, w_env);
2408 wolfSSL_SetIOReadCtx(ssl, w_env);
2409 wolfSSL_set_app_data(ssl, session);
2410 w_env->data.session = session;
2411
2412 if (!setup_client_ssl_session(session, ssl))
2413 return 0;
2414
2415 session->tls = w_env;
2416 w_env->ssl = ssl;
2417 r = wolfSSL_connect(ssl);
2418 if (r == -1) {
2419 int ret = wolfSSL_get_error(ssl, r);
2420 if (ret != WOLFSSL_ERROR_WANT_READ && ret != WOLFSSL_ERROR_WANT_WRITE)
2421 r = 0;
2422 if (ret == WOLFSSL_ERROR_WANT_READ)
2423 session->sock.flags |= COAP_SOCKET_WANT_READ;
2424 if (ret == WOLFSSL_ERROR_WANT_WRITE) {
2425 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2426#ifdef COAP_EPOLL_SUPPORT
2427 coap_epoll_ctl_mod(&session->sock,
2428 EPOLLOUT |
2429 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
2430 EPOLLIN : 0),
2431 __func__);
2432#endif /* COAP_EPOLL_SUPPORT */
2433 }
2434 }
2435
2436 if (r == 0)
2437 goto error;
2438
2439 coap_ticks(&now);
2440 w_env->last_timeout = now;
2441 if (wolfSSL_is_init_finished(ssl)) {
2443 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2444 }
2445
2446 return w_env;
2447
2448error:
2449 coap_dtls_free_wolfssl_env(w_env);
2450 if (ssl)
2451 wolfSSL_free(ssl);
2452 return NULL;
2453}
2454#endif /* COAP_CLIENT_SUPPORT */
2455
2456#if COAP_SERVER_SUPPORT
2457void *
2459 WOLFSSL *ssl = NULL;
2460 coap_wolfssl_context_t *w_context =
2461 ((coap_wolfssl_context_t *)session->context->dtls_context);
2462 coap_tls_context_t *tls;
2463 int r;
2464 const coap_bin_const_t *psk_hint;
2465 coap_wolfssl_env_t *w_env =
2466 coap_dtls_new_wolfssl_env(session, COAP_DTLS_ROLE_SERVER);
2467 coap_tick_t now;
2468
2469 if (!w_env)
2470 goto error;
2471
2472 if (!setup_tls_context(w_context))
2473 goto error;
2474 tls = &w_context->tls;
2475
2476 ssl = wolfSSL_new(tls->ctx);
2477 if (!ssl)
2478 goto error;
2479 wolfSSL_SetIOWriteCtx(ssl, w_env);
2480 wolfSSL_SetIOReadCtx(ssl, w_env);
2481 wolfSSL_set_app_data(ssl, session);
2482
2483 wolfSSL_set_cipher_list(ssl, "ALL");
2484
2485 if (w_context->psk_pki_enabled & IS_PSK) {
2486 psk_hint = coap_get_session_server_psk_hint(session);
2487 if (psk_hint != NULL && psk_hint->length) {
2488 char *hint = wolfssl_malloc(psk_hint->length + 1);
2489
2490 if (hint) {
2491 memcpy(hint, psk_hint->s, psk_hint->length);
2492 hint[psk_hint->length] = '\000';
2493 wolfSSL_use_psk_identity_hint(ssl, hint);
2494 wolfssl_free(hint);
2495 } else {
2496 coap_log_warn("hint malloc failure\n");
2497 }
2498 }
2499 }
2500 if (w_context->psk_pki_enabled & IS_PKI) {
2501 if (!setup_pki_ssl(ssl, &w_context->setup_data, COAP_DTLS_ROLE_SERVER))
2502 goto error;
2503 }
2504#if defined(HAVE_RPK) && LIBWOLFSSL_VERSION_HEX >= 0x05006004
2505 if (w_context->setup_data.is_rpk_not_cert) {
2506 char stype[] = {WOLFSSL_CERT_TYPE_RPK};
2507
2508 wolfSSL_set_server_cert_type(ssl, stype, sizeof(stype)/sizeof(stype[0]));
2509 }
2510#endif /* HAVE_RPK && LIBWOLFSSL_VERSION_HEX >= 0x05006004 */
2511
2512 coap_ticks(&now);
2513 w_env->last_timeout = now;
2514 w_env->ssl = ssl;
2515 w_env->data.session = session;
2516
2517 r = wolfSSL_accept(ssl);
2518 if (r == -1) {
2519 int err = wolfSSL_get_error(ssl, r);
2520 if (err != WOLFSSL_ERROR_WANT_READ && err != WOLFSSL_ERROR_WANT_WRITE) {
2521 r = 0;
2522 }
2523 if (err == WOLFSSL_ERROR_WANT_READ) {
2524 session->sock.flags |= COAP_SOCKET_WANT_READ;
2525 }
2526 if (err == WOLFSSL_ERROR_WANT_WRITE) {
2527 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2528#ifdef COAP_EPOLL_SUPPORT
2529 coap_epoll_ctl_mod(&session->sock,
2530 EPOLLOUT |
2531 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
2532 EPOLLIN : 0),
2533 __func__);
2534#endif /* COAP_EPOLL_SUPPORT */
2535 }
2536 }
2537
2538 if (r == 0)
2539 goto error;
2540
2541 session->tls = w_env;
2542 if (wolfSSL_is_init_finished(ssl)) {
2544 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2545 }
2546
2547 return w_env;
2548
2549error:
2550 if (ssl)
2551 wolfSSL_free(ssl);
2552 coap_dtls_free_wolfssl_env(w_env);
2553 return NULL;
2554}
2555#endif /* COAP_SERVER_SUPPORT */
2556
2557void
2559 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2560 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2561
2562 if (ssl) {
2563 if (!wolfSSL_SSL_in_init(ssl) && !(wolfSSL_get_shutdown(ssl) & WOLFSSL_SENT_SHUTDOWN)) {
2564 int r = wolfSSL_shutdown(ssl);
2565 if (r == 0)
2566 wolfSSL_shutdown(ssl);
2567 }
2568 wolfSSL_free(ssl);
2569 w_env->ssl = NULL;
2570 if (session->context)
2572 }
2573 coap_dtls_free_wolfssl_env(w_env);
2574}
2575
2576/*
2577 * strm
2578 * return +ve Number of bytes written.
2579 * -1 Error (error in errno).
2580 */
2581ssize_t
2582coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
2583 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2584 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2585 int r, in_init;
2586
2587 if (ssl == NULL)
2588 return -1;
2589
2590 in_init = !wolfSSL_is_init_finished(ssl);
2591 session->dtls_event = -1;
2592 r = wolfSSL_write(ssl, data, (int)data_len);
2593
2594 if (r <= 0) {
2595 int err = wolfSSL_get_error(ssl, r);
2596 if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) {
2597 if (in_init && wolfSSL_is_init_finished(ssl)) {
2598 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
2599 coap_session_str(session), wolfSSL_get_cipher((ssl)));
2601 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2602 }
2603 if (err == WOLFSSL_ERROR_WANT_READ)
2604 session->sock.flags |= COAP_SOCKET_WANT_READ;
2605 else if (err == WOLFSSL_ERROR_WANT_WRITE) {
2606 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2607#ifdef COAP_EPOLL_SUPPORT
2608 coap_epoll_ctl_mod(&session->sock,
2609 EPOLLOUT |
2610 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
2611 EPOLLIN : 0),
2612 __func__);
2613#endif /* COAP_EPOLL_SUPPORT */
2614 }
2615 r = 0;
2616 } else {
2617 coap_log_info("***%s: coap_tls_write: cannot send PDU\n",
2618 coap_session_str(session));
2619 if (err == WOLFSSL_ERROR_ZERO_RETURN)
2621 else if (err == WOLFSSL_ERROR_SSL)
2623 r = -1;
2624 }
2625 } else if (in_init && wolfSSL_is_init_finished(ssl)) {
2626 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
2627 coap_session_str(session), wolfSSL_get_cipher((ssl)));
2629 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2630 }
2631
2632 if (session->dtls_event >= 0) {
2633 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2634 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2635 coap_handle_event_lkd(session->context, session->dtls_event, session);
2636 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2637 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2639 r = -1;
2640 }
2641 }
2642
2643 if (r >= 0) {
2644 if (r == (ssize_t)data_len)
2645 coap_log_debug("* %s: tls: sent %4d bytes\n",
2646 coap_session_str(session), r);
2647 else
2648 coap_log_debug("* %s: tls: sent %4d of %4zd bytes\n",
2649 coap_session_str(session), r, data_len);
2650 }
2651 return r;
2652}
2653
2654/*
2655 * strm
2656 * return >=0 Number of bytes read.
2657 * -1 Error (error in errno).
2658 */
2659ssize_t
2660coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
2661 coap_wolfssl_env_t *w_env = (coap_wolfssl_env_t *)session->tls;
2662 WOLFSSL *ssl = w_env ? w_env->ssl : NULL;
2663 int r, in_init;
2664
2665 if (ssl == NULL) {
2666 errno = ENXIO;
2667 return -1;
2668 }
2669
2670 in_init = !wolfSSL_is_init_finished(ssl);
2671 session->dtls_event = -1;
2672 r = wolfSSL_read(ssl, data, (int)data_len);
2673 if (r <= 0) {
2674 int err = wolfSSL_get_error(ssl, r);
2675 if (err == WOLFSSL_ERROR_WANT_READ || err == WOLFSSL_ERROR_WANT_WRITE) {
2676 if (in_init && wolfSSL_is_init_finished(ssl)) {
2677 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
2678 coap_session_str(session), wolfSSL_get_cipher((ssl)));
2680 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2681 }
2682 if (err == WOLFSSL_ERROR_WANT_READ)
2683 session->sock.flags |= COAP_SOCKET_WANT_READ;
2684 if (err == WOLFSSL_ERROR_WANT_WRITE) {
2685 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2686#ifdef COAP_EPOLL_SUPPORT
2687 coap_epoll_ctl_mod(&session->sock,
2688 EPOLLOUT |
2689 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
2690 EPOLLIN : 0),
2691 __func__);
2692#endif /* COAP_EPOLL_SUPPORT */
2693 }
2694 r = 0;
2695 } else {
2696 if (err == WOLFSSL_ERROR_ZERO_RETURN) {
2697 /* Got a close notify alert from the remote side */
2699 } else if (err == WOLFSSL_ERROR_SSL) {
2701 } else if (err == FATAL_ERROR) {
2702 WOLFSSL_ALERT_HISTORY h;
2703
2705 if (wolfSSL_get_alert_history(ssl, &h) == WOLFSSL_SUCCESS) {
2706 if (h.last_rx.code != close_notify && h.last_rx.code != -1) {
2707 coap_log_warn("***%s: Alert '%d': %s\n",
2708 coap_session_str(session), h.last_rx.code,
2709 wolfSSL_alert_desc_string_long(h.last_rx.code));
2710 }
2711 }
2712 }
2713 r = -1;
2714 }
2715 } else if (in_init && wolfSSL_is_init_finished(ssl)) {
2716 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
2717 coap_session_str(session), wolfSSL_get_cipher((ssl)));
2719 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
2720 }
2721
2722 if (session->dtls_event >= 0) {
2723 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2724 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2725 coap_handle_event_lkd(session->context, session->dtls_event, session);
2726 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2727 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2729 r = -1;
2730 }
2731 }
2732
2733 if (r > 0) {
2734 coap_log_debug("* %s: tls: recv %4d bytes\n",
2735 coap_session_str(session), r);
2736 }
2737 return r;
2738}
2739#endif /* !COAP_DISABLE_TCP */
2740
2741#if COAP_SERVER_SUPPORT
2743coap_digest_setup(void) {
2744 WOLFSSL_EVP_MD_CTX *digest_ctx = wolfSSL_EVP_MD_CTX_new();
2745
2746 if (digest_ctx) {
2747 wolfSSL_EVP_DigestInit_ex(digest_ctx, wolfSSL_EVP_sha256(), NULL);
2748 }
2749 return digest_ctx;
2750}
2751
2752void
2754 wolfSSL_EVP_MD_CTX_free(digest_ctx);
2755}
2756
2757int
2759 const uint8_t *data,
2760 size_t data_len) {
2761 return wolfSSL_EVP_DigestUpdate(digest_ctx, data, data_len);
2762}
2763
2764int
2766 coap_digest_t *digest_buffer) {
2767 unsigned int size = sizeof(coap_digest_t);
2768 int ret = wolfSSL_EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
2769
2770 coap_digest_free(digest_ctx);
2771 return ret;
2772}
2773#endif /* COAP_SERVER_SUPPORT */
2774
2775#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
2776static void
2777coap_crypto_output_errors(const char *prefix) {
2778#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
2779 (void)prefix;
2780#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
2781 unsigned long e;
2782
2783 while ((e = wolfSSL_ERR_get_error()))
2784 coap_log_warn("%s: %s%s\n",
2785 prefix,
2786 wolfSSL_ERR_reason_error_string(e),
2787 ssl_function_definition(e));
2788#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
2789}
2790#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
2791
2792#if COAP_WS_SUPPORT
2793/*
2794 * The struct hash_algs and the function get_hash_alg() are used to
2795 * determine which hash type to use for creating the required hash object.
2796 */
2797static struct hash_algs {
2798 cose_alg_t alg;
2799 const WOLFSSL_EVP_MD *(*get_hash)(void);
2800 size_t length; /* in bytes */
2801} hashs[] = {
2802 {COSE_ALGORITHM_SHA_1, wolfSSL_EVP_sha1, 20},
2803 {COSE_ALGORITHM_SHA_256_64, wolfSSL_EVP_sha256, 8},
2804 {COSE_ALGORITHM_SHA_256_256, wolfSSL_EVP_sha256, 32},
2805 {COSE_ALGORITHM_SHA_512, wolfSSL_EVP_sha512, 64},
2806};
2807
2808static const WOLFSSL_EVP_MD *
2809get_hash_alg(cose_alg_t alg, size_t *length) {
2810 size_t idx;
2811
2812 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
2813 if (hashs[idx].alg == alg) {
2814 *length = hashs[idx].length;
2815 return hashs[idx].get_hash();
2816 }
2817 }
2818 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
2819 return NULL;
2820}
2821
2822int
2824 const coap_bin_const_t *data,
2825 coap_bin_const_t **hash) {
2826 unsigned int length;
2827 const WOLFSSL_EVP_MD *evp_md;
2828 WOLFSSL_EVP_MD_CTX *evp_ctx = NULL;
2829 coap_binary_t *dummy = NULL;
2830 size_t hash_length;
2831
2832 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
2833 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
2834 return 0;
2835 }
2836 evp_ctx = wolfSSL_EVP_MD_CTX_new();
2837 if (evp_ctx == NULL)
2838 goto error;
2839 if (wolfSSL_EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
2840 goto error;
2841 ;
2842 if (wolfSSL_EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
2843 goto error;
2844 ;
2845 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
2846 if (dummy == NULL)
2847 goto error;
2848 if (wolfSSL_EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
2849 goto error;
2850 dummy->length = length;
2851 if (hash_length < dummy->length)
2852 dummy->length = hash_length;
2853 *hash = (coap_bin_const_t *)(dummy);
2854 wolfSSL_EVP_MD_CTX_free(evp_ctx);
2855 return 1;
2856
2857error:
2858 coap_crypto_output_errors("coap_crypto_hash");
2860 if (evp_ctx)
2861 wolfSSL_EVP_MD_CTX_free(evp_ctx);
2862 return 0;
2863}
2864#endif /* COAP_WS_SUPPORT */
2865
2866#if COAP_OSCORE_SUPPORT
2867#if LIBWOLFSSL_VERSION_HEX < 0x05006000
2868static const WOLFSSL_EVP_CIPHER *
2869EVP_aes_128_ccm(void) {
2870 return "AES-128-CCM";
2871}
2872
2873static const WOLFSSL_EVP_CIPHER *
2874EVP_aes_256_ccm(void) {
2875 return "AES-256-CCM";
2876}
2877#endif /* LIBWOLFSSL_VERSION_HEX < 0x05006000 */
2878
2879int
2881 return 1;
2882}
2883
2884/*
2885 * The struct cipher_algs and the function get_cipher_alg() are used to
2886 * determine which cipher type to use for creating the required cipher
2887 * suite object.
2888 */
2889static struct cipher_algs {
2890 cose_alg_t alg;
2891 const WOLFSSL_EVP_CIPHER *(*get_cipher)(void);
2892} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
2893 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
2894};
2895
2896static const WOLFSSL_EVP_CIPHER *
2897get_cipher_alg(cose_alg_t alg) {
2898 size_t idx;
2899
2900 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
2901 if (ciphers[idx].alg == alg)
2902 return ciphers[idx].get_cipher();
2903 }
2904 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
2905 return NULL;
2906}
2907
2908/*
2909 * The struct hmac_algs and the function get_hmac_alg() are used to
2910 * determine which hmac type to use for creating the required hmac
2911 * suite object.
2912 */
2913static struct hmac_algs {
2914 cose_hmac_alg_t hmac_alg;
2915 const WOLFSSL_EVP_MD *(*get_hmac)(void);
2916} hmacs[] = {
2917 {COSE_HMAC_ALG_HMAC256_256, wolfSSL_EVP_sha256},
2918 {COSE_HMAC_ALG_HMAC384_384, wolfSSL_EVP_sha384},
2919 {COSE_HMAC_ALG_HMAC512_512, wolfSSL_EVP_sha512},
2920};
2921
2922static const WOLFSSL_EVP_MD *
2923get_hmac_alg(cose_hmac_alg_t hmac_alg) {
2924 size_t idx;
2925
2926 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
2927 if (hmacs[idx].hmac_alg == hmac_alg)
2928 return hmacs[idx].get_hmac();
2929 }
2930 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
2931 return NULL;
2932}
2933
2934int
2936 return get_cipher_alg(alg) != NULL;
2937}
2938
2939int
2941 cose_hmac_alg_t hmac_alg;
2942
2943 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
2944 return 0;
2945 return get_hmac_alg(hmac_alg) != NULL;
2946}
2947
2948#define C(Func) \
2949 if (1 != (Func)) { \
2950 goto error; \
2951 }
2952
2953int
2955 coap_bin_const_t *data,
2956 coap_bin_const_t *aad,
2957 uint8_t *result,
2958 size_t *max_result_len) {
2959
2960 Aes aes;
2961 int ret;
2962 int result_len;
2963 int nonce_length;
2964 byte *authTag = NULL;
2965 const coap_crypto_aes_ccm_t *ccm;
2966
2967 if (data == NULL)
2968 return 0;
2969
2970 assert(params != NULL);
2971 if (!params)
2972 return 0;
2973
2974 ccm = &params->params.aes;
2975
2976 if (ccm->key.s == NULL || ccm->nonce == NULL)
2977 goto error;
2978
2979 result_len = data->length;
2980 nonce_length = 15 - ccm->l;
2981
2982 memset(&aes, 0, sizeof(aes));
2983 ret = wc_AesCcmSetKey(&aes, ccm->key.s, ccm->key.length);
2984 if (ret != 0)
2985 goto error;
2986
2987 authTag = (byte *)malloc(ccm->tag_len * sizeof(byte));
2988 if (!authTag) {
2989 goto error;
2990 }
2991 ret = wc_AesCcmEncrypt(&aes, result, data->s, data->length, ccm->nonce,
2992 nonce_length, authTag, ccm->tag_len,
2993 aad->s, aad->length);
2994
2995 if (ret != 0) {
2996 wolfssl_free(authTag);
2997 goto error;
2998 }
2999
3000 memcpy(result + result_len, authTag, ccm->tag_len);
3001 result_len += sizeof(authTag);
3002 *max_result_len = result_len;
3003 wolfssl_free(authTag);
3004
3005 return 1;
3006error:
3007 coap_crypto_output_errors("coap_crypto_aead_encrypt");
3008 return 0;
3009}
3010
3011
3012int
3014 coap_bin_const_t *data,
3015 coap_bin_const_t *aad,
3016 uint8_t *result,
3017 size_t *max_result_len) {
3018
3019 Aes aes;
3020 int ret;
3021 int len;
3022 const coap_crypto_aes_ccm_t *ccm;
3023
3024 if (data == NULL)
3025 return 0;
3026
3027 if (data == NULL)
3028 return 0;
3029
3030 assert(params != NULL);
3031 if (!params)
3032 return 0;
3033
3034 ccm = &params->params.aes;
3035 byte authTag[ccm->tag_len];
3036
3037 if (data->length < ccm->tag_len) {
3038 return 0;
3039 } else {
3040 memcpy(authTag, data->s + data->length - ccm->tag_len, sizeof(authTag));
3041 data->length -= ccm->tag_len;
3042 }
3043
3044 if (ccm->key.s == NULL || ccm->nonce == NULL)
3045 goto error;
3046
3047 memset(&aes, 0, sizeof(aes));
3048 ret = wc_AesCcmSetKey(&aes, ccm->key.s, ccm->key.length);
3049 if (ret != 0)
3050 goto error;
3051
3052 len = data->length;
3053
3054 ret = wc_AesCcmDecrypt(&aes, result, data->s, len, ccm->nonce,
3055 15 - ccm->l, authTag, sizeof(authTag),
3056 aad->s, aad->length);
3057
3058 if (ret != 0)
3059 goto error;
3060
3061 *max_result_len = len;
3062
3063 return 1;
3064error:
3065 coap_crypto_output_errors("coap_crypto_aead_decrypt");
3066 return 0;
3067}
3068
3069int
3071 coap_bin_const_t *key,
3072 coap_bin_const_t *data,
3073 coap_bin_const_t **hmac) {
3074 unsigned int result_len;
3075 const WOLFSSL_EVP_MD *evp_md;
3076 coap_binary_t *dummy = NULL;
3077
3078 assert(key);
3079 assert(data);
3080 assert(hmac);
3081
3082 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
3083 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
3084 return 0;
3085 }
3086 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
3087 if (dummy == NULL)
3088 return 0;
3089 result_len = (unsigned int)dummy->length;
3090 if (wolfSSL_HMAC(evp_md,
3091 key->s,
3092 (int)key->length,
3093 data->s,
3094 (int)data->length,
3095 dummy->s,
3096 &result_len)) {
3097 dummy->length = result_len;
3098 *hmac = (coap_bin_const_t *)dummy;
3099 return 1;
3100 }
3101
3102 coap_crypto_output_errors("coap_crypto_hmac");
3103 return 0;
3104}
3105
3106#endif /* COAP_OSCORE_SUPPORT */
3107
3108#else /* !COAP_WITH_LIBWOLFSSL */
3109
3110#ifdef __clang__
3111/* Make compilers happy that do not like empty modules. As this function is
3112 * never used, we ignore -Wunused-function at the end of compiling this file
3113 */
3114#pragma GCC diagnostic ignored "-Wunused-function"
3115#endif
3116static inline void
3117dummy(void) {
3118}
3119
3120#endif /* COAP_WITH_LIBWOLFSSL */
static size_t strnlen(const char *s, size_t maxlen)
A length-safe strlen() fake.
Definition coap_debug.c:175
#define COAP_SERVER_SUPPORT
#define COAP_RXBUFFER_SIZE
Definition coap_io.h:29
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:73
#define COAP_SOCKET_WANT_READ
non blocking socket is waiting for reading
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
void coap_epoll_ctl_mod(coap_socket_t *sock, uint32_t events, const char *func)
Epoll specific function to modify the state of events that epoll is tracking on the appropriate file ...
@ COAP_LAYER_TLS
Library specific build wrapper for coap_internal.h.
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition coap_notls.c:90
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:206
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:278
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:201
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:220
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:135
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:238
static coap_log_t dtls_log_level
Definition coap_notls.c:128
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:124
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:189
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:266
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:185
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
Definition coap_notls.c:98
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:215
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:163
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:181
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:158
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:257
static void dummy(void)
coap_binary_t * get_asn1_spki(const uint8_t *data, size_t size)
Abstract SPKI public key from the ASN1.
Definition coap_asn1.c:122
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
struct coap_digest_t coap_digest_t
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
void coap_digest_ctx_t
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
int coap_prng(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition coap_prng.c:140
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:4253
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
Definition coap_net.c:2422
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
void * coap_tls_new_server_session(coap_session_t *coap_session)
Create a TLS new server-side session.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *session)
Get the current client's PSK identity.
Definition coap_net.c:308
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition coap_notls.c:131
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
Definition coap_dtls.c:165
void * coap_dtls_new_client_session(coap_session_t *coap_session)
Create a new client-side session.
void * coap_dtls_new_server_session(coap_session_t *coap_session)
Create a new DTLS server-side session.
int coap_dtls_hello(coap_session_t *coap_session, const uint8_t *data, size_t data_len)
Handling client HELLO messages from a new candiate peer.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition coap_notls.c:196
int coap_dtls_context_set_cpsk(coap_context_t *coap_context, coap_dtls_cpsk_t *setup_data)
Set the DTLS context's default client PSK information.
int coap_dtls_context_set_spsk(coap_context_t *coap_context, coap_dtls_spsk_t *setup_data)
Set the DTLS context's default server PSK information.
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition coap_notls.c:143
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void * coap_tls_new_client_session(coap_session_t *coap_session)
Create a new TLS client-side session.
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
Definition coap_dtls.c:26
const coap_bin_const_t * coap_get_session_server_psk_key(const coap_session_t *coap_session)
Get the current server's PSK key.
const coap_bin_const_t * coap_get_session_server_psk_hint(const coap_session_t *coap_session)
Get the current server's PSK identity hint.
@ COAP_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_KEY_CA
@ COAP_DEFINE_KEY_PUBLIC
@ COAP_DEFINE_FAIL_NONE
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
@ COAP_DEFINE_FAIL_BAD
#define COAP_DTLS_HINT_LENGTH
Definition coap_dtls.h:35
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition coap_notls.c:82
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
coap_dtls_role_t
Definition coap_dtls.h:44
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
coap_tls_library_t
Definition coap_dtls.h:112
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:287
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:284
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:278
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:276
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:293
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:280
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:282
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:290
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition coap_dtls.h:46
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition coap_dtls.h:45
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:214
@ COAP_TLS_LIBRARY_WOLFSSL
Using wolfSSL library.
Definition coap_dtls.h:118
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:39
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:45
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_log_t
Logging type.
Definition coap_debug.h:50
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:153
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:300
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:148
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:108
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log_err(...)
Definition coap_debug.h:96
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:284
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_WARN
Definition coap_debug.h:55
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_64
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_SHA_1
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_SHA_512
@ COSE_ALGORITHM_AES_CCM_16_64_256
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
#define COAP_DEFAULT_MTU
Definition coap_pdu.h:41
@ COAP_PROTO_DTLS
Definition coap_pdu.h:315
@ COAP_PROTO_TLS
Definition coap_pdu.h:317
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_CSM
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:77
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:105
#define COAP_UNUSED
Definition libcoap.h:70
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
CoAP binary data definition.
Definition coap_str.h:56
size_t length
length of binary data
Definition coap_str.h:57
uint8_t * s
binary data
Definition coap_str.h:58
The CoAP stack's global state is stored in a coap_context_t object.
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
The structure that holds the Client PSK information.
Definition coap_dtls.h:417
coap_bin_const_t key
Definition coap_dtls.h:419
coap_bin_const_t identity
Definition coap_dtls.h:418
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:448
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:469
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:472
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:468
The structure that holds the PKI key information.
Definition coap_dtls.h:321
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:328
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:322
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:354
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:368
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:390
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:365
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:367
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:397
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:366
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:364
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:359
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:407
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:362
void * sni_call_back_arg
Passed in to the sni callback function.
Definition coap_dtls.h:398
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:389
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:369
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:372
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
Definition coap_dtls.h:360
coap_dtls_key_t pki_key
PKI key definition.
Definition coap_dtls.h:411
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:484
coap_bin_const_t hint
Definition coap_dtls.h:485
coap_bin_const_t key
Definition coap_dtls.h:486
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:535
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:562
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:554
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:555
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:563
coap_dtls_spsk_info_t psk_info
Server PSK definition.
Definition coap_dtls.h:565
coap_layer_read_t l_read
coap_layer_write_t l_write
coap_layer_establish_t l_establish
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:303
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:304
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:302
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:306
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:305
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:310
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:307
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:308
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:309
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_proto_t proto
protocol used
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
size_t mtu
path or CSM mtu (xmt)
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
uint16_t max_retransmit
maximum re-transmit count (default 4)
coap_context_t * context
session's context
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
CoAP string data definition with const data.
Definition coap_str.h:46
const uint8_t * s
read-only string data
Definition coap_str.h:48
size_t length
length of string
Definition coap_str.h:47
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:125
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:128
coap_tls_library_t type
Library type.
Definition coap_dtls.h:127
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:126
const char * s_byte
signed char ptr
Definition coap_str.h:73
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:74