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