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