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