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