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