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