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