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