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