libcoap 4.3.5-develop-83ceb96
Loading...
Searching...
No Matches
coap_openssl.c
Go to the documentation of this file.
1/*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018-2026 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * This file is part of the CoAP library libcoap. Please see README for terms
10 * of use.
11 */
12
19
20#if COAP_WITH_LIBOPENSSL
21
22/*
23 * OpenSSL 1.1.0 has support for making decisions during receipt of
24 * the Client Hello - the call back function is set up using
25 * SSL_CTX_set_tlsext_servername_callback() which is called later in the
26 * Client Hello processing - but called every Client Hello.
27 * Certificates and Preshared Keys have to be set up in the SSL CTX before
28 * SSL_accept() is called, making the code messy to decide whether this is a
29 * PKI or PSK incoming request to handle things accordingly if both are
30 * defined. SNI has to create a new SSL CTX to handle different server names
31 * with different crtificates.
32 *
33 * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
34 * The call back is invoked early on in the Client Hello processing giving
35 * the ability to easily use different Preshared Keys, Certificates etc.
36 * Certificates do not have to be set up in the SSL CTX before SSL_accept is
37 * called.
38 * Later in the Client Hello code, the callback for
39 * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
40 * is being used by the client, so cannot be used for doing things the
41 * OpenSSL 1.1.0 way.
42 *
43 * OpenSSL 1.1.1 supports TLS1.3.
44 *
45 * There is also support for OpenSSL 3.
46 *
47 * Consequently, this code has to have compile time options to include /
48 * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
49 * have additional run time checks.
50 *
51 * It is possible to override the Ciphers, define the Algorithms or Groups,
52 * and/or define the PKCS11 engine id to to use for the SSL negotiations at
53 * compile time. This is done by the adding of the appropriate -D option to
54 * the CPPFLAGS parameter that is used on the ./configure command line.
55 * E.g. ./configure CPPFLAGS="-DXX='\"YY\"' -DUU='\"VV\"'"
56 * The parameter value is case-sensitive.
57 *
58 * The ciphers can be overridden with (example)
59 * -DCOAP_OPENSSL_CIPHERS='\"ECDHE-ECDSA-AES256-GCM-SHA384\"'
60 *
61 * The Algorithms can be defined by (example)
62 * -DCOAP_OPENSSL_SIGALGS='\"ed25519\"'
63 *
64 * The Groups (OpenSSL 1.1.1 or later) can be defined by (example)
65 * -DCOAP_OPENSSL_GROUPS='\"X25519\"'
66 *
67 * The PKCSLL engine ID can be defined by (example)
68 + -DCOAP_OPENSSL_PKCS11_ENGINE_ID='\"pkcs11\"'
69 *
70 * The PSK security level can be defined by (example)
71 + -DCOAP_OPENSSL_PSK_SECURITY_LEVEL=0
72 *
73 */
74#include <openssl/ssl.h>
75#include <openssl/engine.h>
76#include <openssl/err.h>
77#include <openssl/rand.h>
78#include <openssl/hmac.h>
79#include <openssl/x509v3.h>
80
81#if OPENSSL_VERSION_NUMBER >= 0x30000000L
82#ifdef __GNUC__
83/* Ignore OpenSSL 3.0 deprecated warnings for now */
84#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
85#endif
86#if defined(_WIN32)
87#if !defined(__MINGW32__)
88#pragma warning(disable : 4996)
89#endif /* ! __MINGW32__ */
90#endif /* _WIN32 */
91#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
92
93#ifdef COAP_EPOLL_SUPPORT
94# include <sys/epoll.h>
95#endif /* COAP_EPOLL_SUPPORT */
96
97#if OPENSSL_VERSION_NUMBER < 0x10100000L
98#error Must be compiled against OpenSSL 1.1.0 or later
99#endif
100
101#ifdef _WIN32
102#define strcasecmp _stricmp
103#define strncasecmp _strnicmp
104#endif
105
106/* RFC6091/RFC7250 */
107#ifndef TLSEXT_TYPE_client_certificate_type
108#define TLSEXT_TYPE_client_certificate_type 19
109#endif
110#ifndef TLSEXT_TYPE_server_certificate_type
111#define TLSEXT_TYPE_server_certificate_type 20
112#endif
113
114#ifndef COAP_OPENSSL_CIPHERS
115#if OPENSSL_VERSION_NUMBER >= 0x10101000L
116#define COAP_OPENSSL_CIPHERS "TLSv1.3:TLSv1.2:!NULL"
117#else /* OPENSSL_VERSION_NUMBER < 0x10101000L */
118#define COAP_OPENSSL_CIPHERS "TLSv1.2:!NULL"
119#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
120#endif /*COAP_OPENSSL_CIPHERS */
121
122#ifndef COAP_OPENSSL_PSK_CIPHERS
123#define COAP_OPENSSL_PSK_CIPHERS "PSK:!NULL"
124#endif /*COAP_OPENSSL_PSK_CIPHERS */
125
126#ifndef COAP_OPENSSL_PKCS11_ENGINE_ID
127#define COAP_OPENSSL_PKCS11_ENGINE_ID "pkcs11"
128#endif /* COAP_OPENSSL_PKCS11_ENGINE_ID */
129
130/* This structure encapsulates the OpenSSL context object. */
131typedef struct coap_dtls_context_t {
132 SSL_CTX *ctx;
133 SSL *ssl; /* OpenSSL object for listening to connection requests */
134 HMAC_CTX *cookie_hmac;
135 BIO_METHOD *meth;
136 BIO_ADDR *bio_addr;
137} coap_dtls_context_t;
138
139typedef struct coap_tls_context_t {
140 SSL_CTX *ctx;
141 BIO_METHOD *meth;
142} coap_tls_context_t;
143
144#define IS_PSK 0x1
145#define IS_PKI 0x2
146
147typedef struct sni_entry {
148 char *sni;
149#if OPENSSL_VERSION_NUMBER < 0x10101000L
150 SSL_CTX *ctx;
151#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
152 coap_dtls_key_t pki_key;
153#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
154} sni_entry;
155
156typedef struct psk_sni_entry {
157 char *sni;
158#if OPENSSL_VERSION_NUMBER < 0x10101000L
159 SSL_CTX *ctx;
160#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
161 coap_dtls_spsk_info_t psk_info;
162} psk_sni_entry;
163
164typedef struct coap_openssl_context_t {
165 coap_dtls_context_t dtls;
166#if !COAP_DISABLE_TCP
167 coap_tls_context_t tls;
168#endif /* !COAP_DISABLE_TCP */
169 coap_dtls_pki_t setup_data;
170 int psk_pki_enabled;
171 size_t sni_count;
172 sni_entry *sni_entry_list;
173#if OPENSSL_VERSION_NUMBER < 0x10101000L
174 size_t psk_sni_count;
175 psk_sni_entry *psk_sni_entry_list;
176#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
177} coap_openssl_context_t;
178
179#if COAP_SERVER_SUPPORT
180#if OPENSSL_VERSION_NUMBER < 0x10101000L
181static int psk_tls_server_name_call_back(SSL *ssl, int *sd, void *arg);
182#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
183static int psk_tls_client_hello_call_back(SSL *ssl, int *al, void *arg);
184#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
185#endif /* COAP_SERVER_SUPPORT */
186
187int
189 if (SSLeay() < 0x10100000L) {
190 coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
191 return 0;
192 }
193#if OPENSSL_VERSION_NUMBER >= 0x10101000L
194 /*
195 * For 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
196 * which is not in 1.1.0 instead of SSL_CTX_set_tlsext_servername_callback()
197 *
198 * However, there could be a runtime undefined external reference error
199 * as SSL_CTX_set_client_hello_cb() is not there in 1.1.0.
200 */
201 if (SSLeay() < 0x10101000L) {
202 coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
203 return 0;
204 }
205#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
206 return 1;
207}
208
209int
211#if !COAP_DISABLE_TCP
212 if (SSLeay() < 0x10100000L) {
213 coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
214 return 0;
215 }
216#if OPENSSL_VERSION_NUMBER >= 0x10101000L
217 if (SSLeay() < 0x10101000L) {
218 coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
219 return 0;
220 }
221#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
222 return 1;
223#else /* COAP_DISABLE_TCP */
224 return 0;
225#endif /* COAP_DISABLE_TCP */
226}
227
228/*
229 * return 0 failed
230 * 1 passed
231 */
232int
234 return 1;
235}
236
237/*
238 * return 0 failed
239 * 1 passed
240 */
241int
243 return 1;
244}
245
246/*
247 * return 0 failed
248 * 1 passed
249 */
250int
252 return 1;
253}
254
255/*
256 * return 0 failed
257 * 1 passed
258 */
259int
261 return 0;
262}
263
264/*
265 * return 0 failed
266 * 1 passed
267 */
268int
270 return 0;
271}
272
273#if COAP_CLIENT_SUPPORT
274int
275coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
276 (void)c_context;
277 (void)every;
278 return 0;
279}
280#endif /* COAP_CLIENT_SUPPORT */
281
284 static coap_tls_version_t version;
285 version.version = SSLeay();
286 version.built_version = OPENSSL_VERSION_NUMBER;
288 return &version;
289}
290
291static ENGINE *pkcs11_engine = NULL;
292static ENGINE *defined_engine = NULL;
293
294void
295coap_dtls_startup(void) {
296 SSL_load_error_strings();
297 SSL_library_init();
298 ENGINE_load_dynamic();
299}
300
301void
302coap_dtls_shutdown(void) {
303 if (pkcs11_engine) {
304 /* Release the functional reference from ENGINE_init() */
305 ENGINE_finish(pkcs11_engine);
306 pkcs11_engine = NULL;
307 }
308 if (defined_engine) {
309 /* Release the functional reference from ENGINE_init() */
310 ENGINE_finish(defined_engine);
311 defined_engine = NULL;
312 }
313 ERR_free_strings();
315}
316
317void *
318coap_dtls_get_tls(const coap_session_t *c_session,
319 coap_tls_library_t *tls_lib) {
320 if (tls_lib)
321 *tls_lib = COAP_TLS_LIBRARY_OPENSSL;
322 if (c_session) {
323 return c_session->tls;
324 }
325 return NULL;
326}
327
328static int
329get_split_conf_entry(const uint8_t **start, size_t size, const char *get_keyword,
331 const uint8_t *begin = *start;
332 const uint8_t *end;
333 const uint8_t *kend;
334 const uint8_t *split;
335
336 *p1 = NULL;
337 *p2 = NULL;
338
339retry:
340 kend = end = memchr(begin, '\n', size);
341 if (end == NULL)
342 return 0;
343
344 /* Track beginning of next line */
345 *start = end + 1;
346 if (end > begin && end[-1] == '\r')
347 end--;
348
349 if (begin[0] == '#' || (end - begin) == 0) {
350 /* Skip comment / blank line */
351 size -= kend - begin + 1;
352 begin = *start;
353 goto retry;
354 }
355
356 /* Get in the keyword */
357 split = memchr(begin, ':', end - begin);
358 if (split == NULL)
359 goto bad_entry;
360
361 if ((size_t)(split - begin) != strlen(get_keyword)) {
362 size -= kend - begin + 1;
363 begin = *start;
364 goto retry;
365 }
366 if (memcmp(begin, get_keyword, split - begin)) {
367 size -= kend - begin + 1;
368 begin = *start;
369 goto retry;
370 }
371 /* Found entry we are looking for */
372 begin = split + 1;
373
374 /* parameter 1 is mandatory */
375 if ((end - begin) == 0)
376 goto bad_entry;
377 /* Get in paramater #1 */
378 split = memchr(begin, ':', end - begin);
379 if (split == NULL) {
380 /* Single entry - no parameter #2 */
381 *p1 = coap_new_str_const(begin, end - begin);
382 if (!(*p1)) {
383 goto bad_entry;
384 }
385 } else {
386 *p1 = coap_new_str_const(begin, split - begin);
387 if (!(*p1)) {
388 goto bad_entry;
389 }
390 if ((end - split) > 0) {
391 *p2 = coap_new_str_const(split + 1, end - split - 1);
392 if (!(*p2)) {
393 goto bad_entry;
394 }
395 }
396 }
397
398 return 1;
399
400bad_entry:
403 return 0;
404}
405
406/*
407 * Formating of OpenSSL Engine configuration is:-
408 * (Must be in this order)
409 *
410 * engine:XXX
411 * pre-cmd:XXX:YYY
412 * ....
413 * pre-cmd:XXX:YYY
414 * post-cmd:XXX:YYY
415 * ....
416 * post-cmd:XXX:YYY
417 * enable-methods:unsigned-int
418 * OR'd set of ENGINE_METHOD_* or ENGINE_METHOD_ALL
419 *
420 * pre-cmd and post-cmd are optional
421 * YYY does not have to be defined for some pre-cmd or post-cmd
422 */
423int
425 const uint8_t *start;
426 const uint8_t *end;
429 coap_str_const_t *engine_id = NULL;
430 unsigned int defaults = 0;
431 int done_engine_id = 0;
432 int done_engine_init = 0;
433
434 if (!conf_mem)
435 return 0;
436
437 start = conf_mem->s;
438 end = start + conf_mem->length;
439
440 if (defined_engine) {
441 coap_log_warn("coap_tls_engine_configure: Freeing off previous engine definition\n");
442 ENGINE_finish(defined_engine);
443 defined_engine = NULL;
444 }
445
446 /* Set up engine */
447 if (!get_split_conf_entry(&start, end - start, "engine", &engine_id, &p2)) {
448 coap_log_warn("coap_tls_engine_configure: engine not defined\n");
449 return 0;
450 }
451 defined_engine = ENGINE_by_id((const char *)engine_id->s);
452 if (!defined_engine) {
453 coap_log_warn("coap_tls_engine_configure: engine '%s' not known\n", engine_id->s);
454 goto fail_cleanup;
455 } else {
456 done_engine_id = 1;
457 coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: engine '%s' started\n", engine_id->s);
458 }
460
461 start = conf_mem->s;
462 /* process all the pre-cmd defined */
463 while (get_split_conf_entry(&start, end - start, "pre-cmd", &p1, &p2)) {
464 if (!ENGINE_ctrl_cmd_string(defined_engine, (const char *)p1->s, p2 ? (const char *)p2->s : NULL,
465 0)) {
466 coap_log_warn("coap_tls_engine_configure: engine %s pre-cmd '%s:%s' failed\n",
467 (const char *)engine_id->s,
468 (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
469 goto fail_cleanup;
470 } else {
471 coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: engine '%s' pre-cmd '%s:%s' success\n",
472 engine_id->s, p1->s, p2 ? (const char *)p2->s : "(NULL)");
473 }
476 }
477
478 p1 = NULL;
479 p2 = NULL;
480 /* Start up the engine */
481 if (!ENGINE_init(defined_engine)) {
482 coap_log_warn("coap_tls_engine_configure: %s failed initialization\n", (const char *)engine_id->s);
483 goto fail_cleanup;
484 } else {
485 done_engine_init = 1;
486 coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: %s initialized\n",
487 (const char *)engine_id->s);
488 }
489
490 start = conf_mem->s;
491 /* process all the post-cmd defined */
492 while (get_split_conf_entry(&start, end - start, "post-cmd", &p1, &p2)) {
493 if (!ENGINE_ctrl_cmd_string(defined_engine, (const char *)p1->s, p2 ? (const char *)p2->s : NULL,
494 0)) {
495 coap_log_warn("coap_tls_engine_configure: %s post-cmd '%s:%s' failed\n", (const char *)engine_id->s,
496 (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
497 goto fail_cleanup;
498 } else {
499 coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: %s post-cmd '%s:%s' success\n",
500 (const char *)engine_id->s,
501 (const char *)p1->s, p2 ? (const char *)p2->s : "(NULL)");
502 }
505 }
506
507 start = conf_mem->s;
508 /* See what we should be setting as the methods */
509 if (!get_split_conf_entry(&start, end - start, "enable-methods", &p1, &p2)) {
510 coap_log_warn("coap_tls_engine_configure: enable-methods not found\n");
511 goto fail_cleanup;
512 }
513 defaults = strtoul((const char *)p1->s, NULL, 0);
514 if (!ENGINE_set_default(defined_engine, defaults)) {
515 coap_log_warn("coap_tls_engine_configure: enable-methods 0x%x invalid\n", defaults);
516 goto fail_cleanup;
517 } else {
518 coap_dtls_log(COAP_LOG_DEBUG, "coap_tls_engine_configure: enable-methods 0x%x successful\n",
519 defaults);
520 }
521 coap_delete_str_const(engine_id);
524 /* Success */
525
526 return 1;
527
528fail_cleanup:
529 if (done_engine_id)
530 ENGINE_free(defined_engine);
531 if (done_engine_init)
532 ENGINE_finish(defined_engine);
533 defined_engine = NULL;
534 coap_delete_str_const(engine_id);
537 return 0;
538}
539
540int
542 if (defined_engine) {
543 ENGINE_finish(defined_engine);
544 defined_engine = NULL;
545 return 1;
546 }
547 return 0;
548}
549
550/*
551 * Logging levels use the standard CoAP logging levels
552 */
554
555void
557 dtls_log_level = level;
558}
559
562 return dtls_log_level;
563}
564
565typedef struct coap_ssl_data {
566 coap_session_t *session;
567 const void *pdu;
568 unsigned pdu_len;
569 unsigned peekmode;
570 coap_tick_t timeout;
571} coap_ssl_data;
572
573static int
574coap_dgram_create(BIO *a) {
575 coap_ssl_data *data = NULL;
576 data = malloc(sizeof(coap_ssl_data));
577 if (data == NULL)
578 return 0;
579 BIO_set_init(a, 1);
580 BIO_set_data(a, data);
581 memset(data, 0x00, sizeof(coap_ssl_data));
582 return 1;
583}
584
585static int
586coap_dgram_destroy(BIO *a) {
587 coap_ssl_data *data;
588 if (a == NULL)
589 return 0;
590 data = (coap_ssl_data *)BIO_get_data(a);
591 if (data != NULL)
592 free(data);
593 return 1;
594}
595
596static int
597coap_dgram_read(BIO *a, char *out, int outl) {
598 int ret = 0;
599 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
600
601 if (out != NULL) {
602 if (data != NULL && data->pdu_len > 0) {
603 if (outl < (int)data->pdu_len) {
604 memcpy(out, data->pdu, outl);
605 ret = outl;
606 } else {
607 memcpy(out, data->pdu, data->pdu_len);
608 ret = (int)data->pdu_len;
609 }
610 if (!data->peekmode) {
611 data->pdu_len = 0;
612 data->pdu = NULL;
613 }
614 } else {
615 ret = -1;
616 }
617 BIO_clear_retry_flags(a);
618 if (ret < 0)
619 BIO_set_retry_read(a);
620 }
621 return ret;
622}
623
624static int
625coap_dgram_write(BIO *a, const char *in, int inl) {
626 int ret = 0;
627 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
628
629 if (data && data->session) {
630 if (!coap_netif_available(data->session)
631#if COAP_SERVER_SUPPORT
632 && data->session->endpoint == NULL
633#endif /* COAP_SERVER_SUPPORT */
634 ) {
635 /* socket was closed on client due to error */
636 BIO_clear_retry_flags(a);
637 errno = ECONNRESET;
638 return -1;
639 }
640 ret = (int)data->session->sock.lfunc[COAP_LAYER_TLS].l_write(data->session,
641 (const uint8_t *)in,
642 inl);
643 BIO_clear_retry_flags(a);
644 if (ret <= 0) {
645 if (ret < 0 && (errno == ENOTCONN || errno == ECONNREFUSED))
646 data->session->dtls_event = COAP_EVENT_DTLS_ERROR;
647 BIO_set_retry_write(a);
648 }
649 } else {
650 BIO_clear_retry_flags(a);
651 ret = -1;
652 }
653 return ret;
654}
655
656static int
657coap_dgram_puts(BIO *a, const char *pstr) {
658 return coap_dgram_write(a, pstr, (int)strlen(pstr));
659}
660
661static long
662coap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) {
663 long ret = 1;
664 coap_ssl_data *data = BIO_get_data(a);
665
666 (void)ptr;
667
668 switch (cmd) {
669 case BIO_CTRL_GET_CLOSE:
670 ret = BIO_get_shutdown(a);
671 break;
672 case BIO_CTRL_SET_CLOSE:
673 BIO_set_shutdown(a, (int)num);
674 break;
675 case BIO_CTRL_DGRAM_SET_PEEK_MODE:
676 if (data)
677 data->peekmode = (unsigned)num;
678 else
679 ret = 0;
680 break;
681 case BIO_CTRL_DGRAM_CONNECT:
682 case BIO_C_SET_FD:
683 case BIO_C_GET_FD:
684 case BIO_CTRL_DGRAM_SET_DONT_FRAG:
685 case BIO_CTRL_DGRAM_GET_MTU:
686 case BIO_CTRL_DGRAM_SET_MTU:
687 case BIO_CTRL_DGRAM_QUERY_MTU:
688 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
689 ret = -1;
690 break;
691 case BIO_CTRL_DUP:
692 case BIO_CTRL_FLUSH:
693 case BIO_CTRL_DGRAM_MTU_DISCOVER:
694 case BIO_CTRL_DGRAM_SET_CONNECTED:
695 break;
696 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
697 if (data)
698 data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval *)ptr)->tv_sec * 1000000 +
699 ((struct timeval *)ptr)->tv_usec);
700 else
701 ret = 0;
702 break;
703 case BIO_CTRL_RESET:
704 case BIO_C_FILE_SEEK:
705 case BIO_C_FILE_TELL:
706 case BIO_CTRL_INFO:
707 case BIO_CTRL_PENDING:
708 case BIO_CTRL_WPENDING:
709 case BIO_CTRL_DGRAM_GET_PEER:
710 case BIO_CTRL_DGRAM_SET_PEER:
711 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
712 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
713 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
714 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
715 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
716 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
717 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
718 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
719 default:
720 ret = 0;
721 break;
722 }
723 return ret;
724}
725
726static int
727coap_dtls_generate_cookie(SSL *ssl,
728 unsigned char *cookie,
729 unsigned int *cookie_len) {
730 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
731 coap_dtls_context_t *dtls = ctx ? (coap_dtls_context_t *)SSL_CTX_get_app_data(ctx) : NULL;
732 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
733
734 if (dtls && data) {
735 int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
736 r &= HMAC_Update(dtls->cookie_hmac,
737 (const uint8_t *)&data->session->addr_info.local.addr,
738 (size_t)data->session->addr_info.local.size);
739 r &= HMAC_Update(dtls->cookie_hmac,
740 (const uint8_t *)&data->session->addr_info.remote.addr,
741 (size_t)data->session->addr_info.remote.size);
742 r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
743 return r;
744 }
745 return 0;
746}
747
748static int
749coap_dtls_verify_cookie(SSL *ssl,
750 const uint8_t *cookie,
751 unsigned int cookie_len) {
752 uint8_t hmac[32];
753 unsigned len = 32;
754 if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
755 cookie_len == len && memcmp(cookie, hmac, len) == 0)
756 return 1;
757 else
758 return 0;
759}
760
761#if COAP_CLIENT_SUPPORT
762static unsigned int
763coap_dtls_psk_client_callback(SSL *ssl,
764 const char *hint,
765 char *identity,
766 unsigned int max_identity_len,
767 unsigned char *psk,
768 unsigned int max_psk_len) {
769 coap_session_t *c_session;
770 coap_openssl_context_t *o_context;
771 coap_dtls_cpsk_t *setup_data;
772 coap_bin_const_t temp;
773 const coap_dtls_cpsk_info_t *cpsk_info;
774 const coap_bin_const_t *psk_key;
775 const coap_bin_const_t *psk_identity;
776
777 c_session = (coap_session_t *)SSL_get_app_data(ssl);
778 if (c_session == NULL || c_session->context == NULL)
779 return 0;
780 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
781 if (o_context == NULL)
782 return 0;
783 setup_data = &c_session->cpsk_setup_data;
784
785 temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
786 temp.length = strlen((const char *)temp.s);
787 coap_session_refresh_psk_hint(c_session, &temp);
788
789 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
790 (const char *)temp.s);
791
792 if (setup_data->validate_ih_call_back) {
793 coap_str_const_t lhint;
794
795 lhint.s = temp.s;
796 lhint.length = temp.length;
797 coap_lock_callback_ret(cpsk_info,
798 setup_data->validate_ih_call_back(&lhint,
799 c_session,
800 setup_data->ih_call_back_arg));
801
802 if (cpsk_info == NULL)
803 return 0;
804
805 coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
806 coap_session_refresh_psk_key(c_session, &cpsk_info->key);
807 psk_identity = &cpsk_info->identity;
808 psk_key = &cpsk_info->key;
809 } else {
810 psk_identity = coap_get_session_client_psk_identity(c_session);
811 psk_key = coap_get_session_client_psk_key(c_session);
812 }
813
814 if (psk_identity == NULL || psk_key == NULL) {
815 coap_log_warn("no PSK available\n");
816 return 0;
817 }
818
819 /* identity has to be NULL terminated */
820 if (!max_identity_len)
821 return 0;
822 max_identity_len--;
823 if (psk_identity->length > max_identity_len) {
824 coap_log_warn("psk_identity too large, truncated to %d bytes\n",
825 max_identity_len);
826 } else {
827 /* Reduce to match */
828 max_identity_len = (unsigned int)psk_identity->length;
829 }
830 memcpy(identity, psk_identity->s, max_identity_len);
831 identity[max_identity_len] = '\000';
832
833 if (psk_key->length > max_psk_len) {
834 coap_log_warn("psk_key too large, truncated to %d bytes\n",
835 max_psk_len);
836 } else {
837 /* Reduce to match */
838 max_psk_len = (unsigned int)psk_key->length;
839 }
840 memcpy(psk, psk_key->s, max_psk_len);
841 return max_psk_len;
842}
843#endif /* COAP_CLIENT_SUPPORT */
844
845#if COAP_SERVER_SUPPORT
846static unsigned int
847coap_dtls_psk_server_callback(
848 SSL *ssl,
849 const char *identity,
850 unsigned char *psk,
851 unsigned int max_psk_len
852) {
853 coap_session_t *c_session;
854 coap_dtls_spsk_t *setup_data;
855 coap_bin_const_t lidentity;
856 const coap_bin_const_t *psk_key;
857
858 c_session = (coap_session_t *)SSL_get_app_data(ssl);
859 if (c_session == NULL || c_session->context == NULL)
860 return 0;
861
862 setup_data = &c_session->context->spsk_setup_data;
863
864 /* Track the Identity being used */
865 lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
866 lidentity.length = strlen((const char *)lidentity.s);
867 coap_session_refresh_psk_identity(c_session, &lidentity);
868
869 coap_log_debug("got psk_identity: '%.*s'\n",
870 (int)lidentity.length, (const char *)lidentity.s);
871
872 if (setup_data->validate_id_call_back) {
873 psk_key = setup_data->validate_id_call_back(&lidentity,
874 c_session,
875 setup_data->id_call_back_arg);
876
877 coap_session_refresh_psk_key(c_session, psk_key);
878 } else {
879 psk_key = coap_get_session_server_psk_key(c_session);
880 }
881
882 if (psk_key == NULL)
883 return 0;
884
885 if (psk_key->length > max_psk_len) {
886 coap_log_warn("psk_key too large, truncated to %d bytes\n",
887 max_psk_len);
888 } else {
889 /* Reduce to match */
890 max_psk_len = (unsigned int)psk_key->length;
891 }
892 memcpy(psk, psk_key->s, max_psk_len);
893 return max_psk_len;
894}
895#endif /* COAP_SERVER_SUPPORT */
896
897static const char *
898ssl_function_definition(unsigned long e) {
899#if OPENSSL_VERSION_NUMBER >= 0x30000000L
900 (void)e;
901 return "";
902#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
903 static char buff[80];
904
905 snprintf(buff, sizeof(buff), " at %s:%s",
906 ERR_lib_error_string(e), ERR_func_error_string(e));
907 return buff;
908#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
909}
910
911static void
912coap_dtls_info_callback(const SSL *ssl, int where, int ret) {
913 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
914 const char *pstr;
915 int w = where &~SSL_ST_MASK;
916
917 if (!session) {
919 "coap_dtls_info_callback: session not determined, where 0x%0x and ret 0x%0x\n", where, ret);
920 return;
921 }
922 if (w & SSL_ST_CONNECT)
923 pstr = "SSL_connect";
924 else if (w & SSL_ST_ACCEPT)
925 pstr = "SSL_accept";
926 else
927 pstr = "undefined";
928
929 if (where & SSL_CB_LOOP) {
930 coap_dtls_log(COAP_LOG_DEBUG, "* %s: %s:%s\n",
931 coap_session_str(session), pstr, SSL_state_string_long(ssl));
932 } else if (where & SSL_CB_ALERT) {
933 coap_log_t log_level = COAP_LOG_INFO;
934 pstr = (where & SSL_CB_READ) ? "read" : "write";
935 if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
937 if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
938 log_level = COAP_LOG_WARN;
939 }
940 /* Need to let CoAP logging know why this session is dying */
941 coap_log(log_level, "* %s: SSL3 alert %s:%s:%s\n",
942 coap_session_str(session),
943 pstr,
944 SSL_alert_type_string_long(ret),
945 SSL_alert_desc_string_long(ret));
946 } else if (where & SSL_CB_EXIT) {
947 if (ret == 0) {
949 unsigned long e;
950 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:failed in %s\n",
951 coap_session_str(session), pstr, SSL_state_string_long(ssl));
952 while ((e = ERR_get_error()))
953 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
954 coap_session_str(session), ERR_reason_error_string(e),
955 ssl_function_definition(e));
956 }
957 } else if (ret < 0) {
959 int err = SSL_get_error(ssl, ret);
960 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
961 err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
962 err != SSL_ERROR_WANT_X509_LOOKUP) {
963 long e;
964 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:error in %s\n",
965 coap_session_str(session), pstr, SSL_state_string_long(ssl));
966 while ((e = ERR_get_error()))
967 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
968 coap_session_str(session), ERR_reason_error_string(e),
969 ssl_function_definition(e));
970 }
971 }
972 }
973 }
974
975 if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
977}
978
979#if !COAP_DISABLE_TCP
980static int
981coap_sock_create(BIO *a) {
982 BIO_set_init(a, 1);
983 return 1;
984}
985
986static int
987coap_sock_destroy(BIO *a) {
988 (void)a;
989 return 1;
990}
991
992/*
993 * strm
994 * return +ve data amount
995 * 0 no more
996 * -1 error
997 */
998static int
999coap_sock_read(BIO *a, char *out, int outl) {
1000 int ret = 0;
1001 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1002
1003 if (session && out != NULL) {
1004 ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (uint8_t *)out,
1005 outl);
1006 /* Translate layer returns into what OpenSSL expects */
1007 if (ret == 0) {
1008 BIO_set_retry_read(a);
1009 ret = -1;
1010 } else {
1011 BIO_clear_retry_flags(a);
1012 }
1013 }
1014 return ret;
1015}
1016
1017/*
1018 * strm
1019 * return +ve data amount
1020 * 0 no more
1021 * -1 error (error in errno)
1022 */
1023static int
1024coap_sock_write(BIO *a, const char *in, int inl) {
1025 int ret = 0;
1026 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1027
1028 if (!session) {
1029 errno = ENOMEM;
1030 return -1;
1031 } else {
1032 ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
1033 (const uint8_t *)in,
1034 inl);
1035 }
1036 /* Translate layer what returns into what OpenSSL expects */
1037 BIO_clear_retry_flags(a);
1038 if (ret == 0) {
1039 BIO_set_retry_read(a);
1040 ret = -1;
1041 } else {
1042 BIO_clear_retry_flags(a);
1043 if (ret == -1) {
1044 if ((session->state == COAP_SESSION_STATE_CSM ||
1045 session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1046 (errno == EPIPE || errno == ECONNRESET)) {
1047 /*
1048 * Need to handle a TCP timing window where an agent continues with
1049 * the sending of the next handshake or a CSM.
1050 * However, the peer does not like a certificate and so sends a
1051 * fatal alert and closes the TCP session.
1052 * The sending of the next handshake or CSM may get terminated because
1053 * of the closed TCP session, but there is still an outstanding alert
1054 * to be read in and reported on.
1055 * In this case, pretend that sending the info was fine so that the
1056 * alert can be read (which effectively is what happens with DTLS).
1057 */
1058 ret = inl;
1059 }
1060 }
1061 }
1062 return ret;
1063}
1064
1065static int
1066coap_sock_puts(BIO *a, const char *pstr) {
1067 return coap_sock_write(a, pstr, (int)strlen(pstr));
1068}
1069
1070static long
1071coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
1072 int r = 1;
1073 (void)a;
1074 (void)ptr;
1075 (void)num;
1076
1077 switch (cmd) {
1078 case BIO_C_SET_FD:
1079 case BIO_C_GET_FD:
1080 r = -1;
1081 break;
1082 case BIO_CTRL_SET_CLOSE:
1083 case BIO_CTRL_DUP:
1084 case BIO_CTRL_FLUSH:
1085 r = 1;
1086 break;
1087 default:
1088 case BIO_CTRL_GET_CLOSE:
1089 r = 0;
1090 break;
1091 }
1092 return r;
1093}
1094#endif /* !COAP_DISABLE_TCP */
1095
1096static void
1097coap_set_user_prefs(SSL_CTX *ctx) {
1098 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
1099
1100#ifdef COAP_OPENSSL_SIGALGS
1101 SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1102 SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1103#endif
1104
1105#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1106 SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1107#endif
1108}
1109
1110#if COAP_DTLS_RETRANSMIT_MS != 1000
1111#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1112static unsigned int
1113timer_cb(SSL *s, unsigned int timer_us) {
1114 (void)s;
1115 if (timer_us == 0)
1116 return COAP_DTLS_RETRANSMIT_MS * 1000;
1117 else
1118 return 2 * timer_us;
1119}
1120#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1121#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
1122
1123void *
1125 coap_openssl_context_t *context;
1126 (void)coap_context;
1127
1128 context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
1129 if (context) {
1130 uint8_t cookie_secret[32];
1131
1132 memset(context, 0, sizeof(coap_openssl_context_t));
1133
1134 /* Set up DTLS context */
1135 context->dtls.ctx = SSL_CTX_new(DTLS_method());
1136 if (!context->dtls.ctx)
1137 goto error;
1138 SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1139 SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1140 SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1141 coap_set_user_prefs(context->dtls.ctx);
1142 memset(cookie_secret, 0, sizeof(cookie_secret));
1143 if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
1145 "Insufficient entropy for random cookie generation");
1146 coap_prng_lkd(cookie_secret, sizeof(cookie_secret));
1147 }
1148 context->dtls.cookie_hmac = HMAC_CTX_new();
1149 if (!context->dtls.cookie_hmac)
1150 goto error;
1151 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1152 EVP_sha256(), NULL))
1153 goto error;
1154 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1155 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1156 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1157 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1158#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1159 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1160#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1161 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1162 if (!context->dtls.meth)
1163 goto error;
1164 context->dtls.bio_addr = BIO_ADDR_new();
1165 if (!context->dtls.bio_addr)
1166 goto error;
1167 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1168 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1169 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1170 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1171 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1172 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1173
1174#if !COAP_DISABLE_TCP
1175 /* Set up TLS context */
1176 context->tls.ctx = SSL_CTX_new(TLS_method());
1177 if (!context->tls.ctx)
1178 goto error;
1179 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1180 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1181 coap_set_user_prefs(context->tls.ctx);
1182 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1183 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1184 if (!context->tls.meth)
1185 goto error;
1186 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1187 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1188 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1189 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1190 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1191 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1192#endif /* !COAP_DISABLE_TCP */
1193 }
1194
1195 return context;
1196
1197error:
1198 coap_dtls_free_context(context);
1199 return NULL;
1200}
1201
1202#if COAP_SERVER_SUPPORT
1203int
1204coap_dtls_context_set_spsk(coap_context_t *c_context,
1205 coap_dtls_spsk_t *setup_data
1206 ) {
1207 coap_openssl_context_t *o_context =
1208 ((coap_openssl_context_t *)c_context->dtls_context);
1209 BIO *bio;
1210
1211 if (!setup_data || !o_context)
1212 return 0;
1213
1214 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1215 coap_dtls_psk_server_callback);
1216#if !COAP_DISABLE_TCP
1217 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1218 coap_dtls_psk_server_callback);
1219#endif /* !COAP_DISABLE_TCP */
1220 if (setup_data->psk_info.hint.s) {
1221 char hint[COAP_DTLS_HINT_LENGTH];
1222 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1223 setup_data->psk_info.hint.s);
1224 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1225#if !COAP_DISABLE_TCP
1226 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1227#endif /* !COAP_DISABLE_TCP */
1228 }
1229 if (setup_data->validate_sni_call_back) {
1230#if OPENSSL_VERSION_NUMBER < 0x10101000L
1231 SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1232 &c_context->spsk_setup_data);
1233 SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1234 psk_tls_server_name_call_back);
1235#if !COAP_DISABLE_TCP
1236 SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1237 &c_context->spsk_setup_data);
1238 SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1239 psk_tls_server_name_call_back);
1240#endif /* !COAP_DISABLE_TCP */
1241#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1242 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1243 psk_tls_client_hello_call_back,
1244 NULL);
1245#if !COAP_DISABLE_TCP
1246 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1247 psk_tls_client_hello_call_back,
1248 NULL);
1249#endif /* !COAP_DISABLE_TCP */
1250#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1251 }
1252
1253 if (!o_context->dtls.ssl) {
1254 /* This is set up to handle new incoming sessions to a server */
1255 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1256 if (!o_context->dtls.ssl)
1257 return 0;
1258 bio = BIO_new(o_context->dtls.meth);
1259 if (!bio) {
1260 SSL_free(o_context->dtls.ssl);
1261 o_context->dtls.ssl = NULL;
1262 return 0;
1263 }
1264 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1265 SSL_set_app_data(o_context->dtls.ssl, NULL);
1266 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1267 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1268 }
1269 if (setup_data->ec_jpake) {
1270 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1271 }
1272 o_context->psk_pki_enabled |= IS_PSK;
1273 return 1;
1274}
1275#endif /* COAP_SERVER_SUPPORT */
1276
1277#if COAP_CLIENT_SUPPORT
1278int
1279coap_dtls_context_set_cpsk(coap_context_t *c_context,
1280 coap_dtls_cpsk_t *setup_data
1281 ) {
1282 coap_openssl_context_t *o_context =
1283 ((coap_openssl_context_t *)c_context->dtls_context);
1284 BIO *bio;
1285
1286 if (!setup_data || !o_context)
1287 return 0;
1288
1289 if (!o_context->dtls.ssl) {
1290 /* This is set up to handle new incoming sessions to a server */
1291 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1292 if (!o_context->dtls.ssl)
1293 return 0;
1294 bio = BIO_new(o_context->dtls.meth);
1295 if (!bio) {
1296 SSL_free(o_context->dtls.ssl);
1297 o_context->dtls.ssl = NULL;
1298 return 0;
1299 }
1300 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1301 SSL_set_app_data(o_context->dtls.ssl, NULL);
1302 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1303 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1304 }
1305 if (setup_data->ec_jpake) {
1306 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1307 }
1308 if (setup_data->use_cid) {
1309 coap_log_warn("OpenSSL has no Connection-ID support\n");
1310 }
1311 o_context->psk_pki_enabled |= IS_PSK;
1312 return 1;
1313}
1314#endif /* COAP_CLIENT_SUPPORT */
1315
1316static int
1317map_key_type(int asn1_private_key_type
1318 ) {
1319 switch (asn1_private_key_type) {
1321 return EVP_PKEY_NONE;
1322 case COAP_ASN1_PKEY_RSA:
1323 return EVP_PKEY_RSA;
1325 return EVP_PKEY_RSA2;
1326 case COAP_ASN1_PKEY_DSA:
1327 return EVP_PKEY_DSA;
1329 return EVP_PKEY_DSA1;
1331 return EVP_PKEY_DSA2;
1333 return EVP_PKEY_DSA3;
1335 return EVP_PKEY_DSA4;
1336 case COAP_ASN1_PKEY_DH:
1337 return EVP_PKEY_DH;
1338 case COAP_ASN1_PKEY_DHX:
1339 return EVP_PKEY_DHX;
1340 case COAP_ASN1_PKEY_EC:
1341 return EVP_PKEY_EC;
1343 return EVP_PKEY_HMAC;
1345 return EVP_PKEY_CMAC;
1347 return EVP_PKEY_TLS1_PRF;
1349 return EVP_PKEY_HKDF;
1350 default:
1351 coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1352 asn1_private_key_type);
1353 break;
1354 }
1355 return 0;
1356}
1357#if !COAP_DISABLE_TCP
1358static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1359
1360#if COAP_SERVER_SUPPORT
1361static int
1362server_alpn_callback(SSL *ssl COAP_UNUSED,
1363 const unsigned char **out,
1364 unsigned char *outlen,
1365 const unsigned char *in,
1366 unsigned int inlen,
1367 void *arg COAP_UNUSED
1368 ) {
1369 unsigned char *tout = NULL;
1370 int ret;
1371 if (inlen == 0)
1372 return SSL_TLSEXT_ERR_NOACK;
1373 ret = SSL_select_next_proto(&tout,
1374 outlen,
1375 coap_alpn,
1376 sizeof(coap_alpn),
1377 in,
1378 inlen);
1379 *out = tout;
1380 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1381}
1382#endif /* COAP_SERVER_SUPPORT */
1383#endif /* !COAP_DISABLE_TCP */
1384
1385static void
1386add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1387 long e;
1388
1389 /* Flush out existing errors */
1390 while (ERR_get_error() != 0) {
1391 }
1392
1393 if (!X509_STORE_add_cert(st, x509)) {
1394 while ((e = ERR_get_error()) != 0) {
1395 int r = ERR_GET_REASON(e);
1396 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1397 /* Not already added */
1398 coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1399 ERR_reason_error_string(e),
1400 ssl_function_definition(e));
1401 }
1402 }
1403 }
1404}
1405
1406static X509 *
1407missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1408 struct {
1409 const char *cert_id;
1410 X509 *cert;
1411 } params;
1412
1413 params.cert_id = cert_id;
1414 params.cert = NULL;
1415
1416 /* There is no ENGINE_load_cert() */
1417 if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1418 params.cert = NULL;
1419 }
1420 return params.cert;
1421}
1422
1423static int
1424check_pkcs11_engine(void) {
1425 static int already_tried = 0;
1426
1427 if (already_tried)
1428 return 0;
1429
1430 if (!pkcs11_engine) {
1431 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1432 if (!pkcs11_engine) {
1433 coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1434 COAP_OPENSSL_PKCS11_ENGINE_ID);
1435 already_tried = 1;
1436 return 0;
1437 }
1438 if (!ENGINE_init(pkcs11_engine)) {
1439 /* the engine couldn't initialise, release 'pkcs11_engine' */
1440 ENGINE_free(pkcs11_engine);
1441 pkcs11_engine = NULL;
1442 coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1443 already_tried = 1;
1444 return 0;
1445 }
1446 /*
1447 * ENGINE_init() returned a functional reference, so free the structural
1448 * reference from ENGINE_by_id().
1449 */
1450 ENGINE_free(pkcs11_engine);
1451 }
1452 return 1;
1453}
1454
1455#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1456
1457static int
1458install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1459 const char *public_cert) {
1460 X509 *x509;
1461
1462 x509 = missing_ENGINE_load_cert(engine, public_cert);
1463 if (!x509) {
1464 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1465 "%s Certificate\n",
1466 public_cert,
1467 "Server");
1468 return 0;
1469 }
1470 if (!SSL_CTX_use_certificate(ctx, x509)) {
1471 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1472 "%s Certificate\n",
1473 public_cert,
1474 "Server");
1475 X509_free(x509);
1476 return 0;
1477 }
1478 X509_free(x509);
1479 return 1;
1480}
1481
1482static int
1483install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1484 const char *private_key) {
1485 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1486 private_key,
1487 NULL, NULL);
1488
1489 if (!pkey) {
1490 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1491 "%s Private Key\n",
1492 private_key,
1493 "Server");
1494 return 0;
1495 }
1496 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1497 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1498 "%s Private Key\n",
1499 private_key,
1500 "Server");
1501 EVP_PKEY_free(pkey);
1502 return 0;
1503 }
1504 EVP_PKEY_free(pkey);
1505 return 1;
1506}
1507
1508static int
1509install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1510 X509 *x509;
1511 X509_STORE *st;
1512
1513 x509 = missing_ENGINE_load_cert(engine,
1514 ca);
1515 if (!x509) {
1516 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1517 "%s CA Certificate\n",
1518 ca,
1519 "Server");
1520 return 0;
1521 }
1522 if (!SSL_CTX_add_client_CA(ctx, x509)) {
1523 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1524 "%s CA Certificate\n",
1525 ca,
1526 "Server");
1527 X509_free(x509);
1528 return 0;
1529 }
1530 st = SSL_CTX_get_cert_store(ctx);
1531 add_ca_to_cert_store(st, x509);
1532 X509_free(x509);
1533 return 1;
1534}
1535
1536static int
1537load_in_cas_ctx(SSL_CTX *ctx,
1538 const char *ca_file) {
1539 STACK_OF(X509_NAME) *cert_names;
1540 X509_STORE *st;
1541 BIO *in;
1542 X509 *x = NULL;
1543 char *rw_var = NULL;
1544 cert_names = SSL_load_client_CA_file(ca_file);
1545 if (cert_names != NULL)
1546 SSL_CTX_set_client_CA_list(ctx, cert_names);
1547 else {
1548 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1549 "client CA File\n",
1550 ca_file);
1551 return 0;
1552 }
1553
1554 /* Add CA to the trusted root CA store */
1555 st = SSL_CTX_get_cert_store(ctx);
1556 in = BIO_new(BIO_s_file());
1557 if (!in)
1558 return 0;
1559 /* Need to do this to not get a compiler warning about const parameters */
1560 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1561 if (!BIO_read_filename(in, rw_var)) {
1562 BIO_free(in);
1563 return 0;
1564 }
1565
1566 for (;;) {
1567 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1568 break;
1569 add_ca_to_cert_store(st, x);
1570 X509_free(x);
1571 }
1572 BIO_free(in);
1573 return 1;
1574}
1575
1576static int
1577setup_pki_server(SSL_CTX *ctx,
1578 const coap_dtls_pki_t *setup_data) {
1579 coap_dtls_key_t key;
1580
1581 /* Map over to the new define format to save code duplication */
1582 coap_dtls_map_key_type_to_define(setup_data, &key);
1583
1584 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1585
1586 /*
1587 * Configure the Private Key
1588 */
1589 if (key.key.define.private_key.u_byte &&
1590 key.key.define.private_key.u_byte[0]) {
1591 switch (key.key.define.private_key_def) {
1592 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1593 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1595 SSL_FILETYPE_PEM))) {
1598 &key, COAP_DTLS_ROLE_SERVER, 0);
1599 }
1600 break;
1601 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1602 if (key.key.define.private_key_len) {
1603 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1604 (int)key.key.define.private_key_len);
1605 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1606
1607 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1608 if (bp)
1609 BIO_free(bp);
1610 if (pkey)
1611 EVP_PKEY_free(pkey);
1614 &key, COAP_DTLS_ROLE_SERVER, 0);
1615 }
1616 if (bp)
1617 BIO_free(bp);
1618 if (pkey)
1619 EVP_PKEY_free(pkey);
1620 } else {
1623 &key, COAP_DTLS_ROLE_SERVER, 0);
1624 }
1625 break;
1626 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1629 &key, COAP_DTLS_ROLE_SERVER, 0);
1630 case COAP_PKI_KEY_DEF_DER: /* define private key */
1631 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1633 SSL_FILETYPE_ASN1))) {
1636 &key, COAP_DTLS_ROLE_SERVER, 0);
1637 }
1638 break;
1639 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1640 if (key.key.define.private_key_len == 0 ||
1641 !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1642 ctx,
1644 (long)key.key.define.private_key_len))) {
1647 &key, COAP_DTLS_ROLE_SERVER, 0);
1648 }
1649 break;
1650 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1651 if (!check_pkcs11_engine()) {
1652 return 0;
1653 }
1654 if (key.key.define.user_pin) {
1655 /* If not set, pin-value may be held in pkcs11: URI */
1656 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1657 "PIN",
1658 key.key.define.user_pin, 0) == 0) {
1659 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1660 key.key.define.user_pin);
1661 return 0;
1662 }
1663 }
1664 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1668 &key, COAP_DTLS_ROLE_SERVER, 0);
1669 }
1670 break;
1671 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1672 if (!defined_engine ||
1673 !install_engine_private_key_ctx(defined_engine, ctx,
1677 &key, COAP_DTLS_ROLE_SERVER, 0);
1678 }
1679 break;
1680 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1681 default:
1684 &key, COAP_DTLS_ROLE_SERVER, 0);
1685 }
1686 } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1689 &key, COAP_DTLS_ROLE_SERVER, 0);
1690 }
1691
1692 /*
1693 * Configure the Public Certificate / Key
1694 * OpenSSL < 1.1.1 and Server
1695 */
1696 if (key.key.define.public_cert.u_byte &&
1697 key.key.define.public_cert.u_byte[0]) {
1698 switch (key.key.define.public_cert_def) {
1699 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1700 if (key.key.define.ca.u_byte &&
1701 key.key.define.ca.u_byte[0]) {
1702 if (!(SSL_CTX_use_certificate_file(ctx,
1704 SSL_FILETYPE_PEM))) {
1707 &key, COAP_DTLS_ROLE_SERVER, 0);
1708 }
1709 } else {
1710 if (!SSL_CTX_use_certificate_chain_file(ctx,
1714 &key, COAP_DTLS_ROLE_SERVER, 0);
1715 }
1716 }
1717 break;
1718 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1719 if (key.key.define.public_cert_len) {
1720 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1721 (int)key.key.define.public_cert_len);
1722 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1723
1724 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1725 if (bp)
1726 BIO_free(bp);
1727 if (cert)
1728 X509_free(cert);
1731 &key, COAP_DTLS_ROLE_SERVER, 0);
1732 }
1733 if (bp)
1734 BIO_free(bp);
1735 if (cert)
1736 X509_free(cert);
1737 } else {
1740 &key, COAP_DTLS_ROLE_SERVER, 0);
1741 }
1742 break;
1743 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1746 &key, COAP_DTLS_ROLE_SERVER, 0);
1747 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1748 if (!(SSL_CTX_use_certificate_file(ctx,
1750 SSL_FILETYPE_ASN1))) {
1753 &key, COAP_DTLS_ROLE_SERVER, 0);
1754 }
1755 break;
1756 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1757 if (key.key.define.public_cert_len == 0 ||
1758 !(SSL_CTX_use_certificate_ASN1(ctx,
1759 (int)key.key.define.public_cert_len,
1760 key.key.define.public_cert.u_byte))) {
1763 &key, COAP_DTLS_ROLE_SERVER, 0);
1764 }
1765 break;
1766 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1767 if (!check_pkcs11_engine()) {
1768 return 0;
1769 }
1770 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1774 &key, COAP_DTLS_ROLE_SERVER, 0);
1775 }
1776 break;
1777 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1778 if (!defined_engine ||
1779 !install_engine_public_cert_ctx(defined_engine, ctx,
1783 &key, COAP_DTLS_ROLE_SERVER, 0);
1784 }
1785 break;
1786 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1787 default:
1790 &key, COAP_DTLS_ROLE_SERVER, 0);
1791 }
1792 } else if (key.key.define.private_key.u_byte &&
1793 key.key.define.private_key.u_byte[0]) {
1796 &key, COAP_DTLS_ROLE_SERVER, 0);
1797 }
1798
1799 /*
1800 * Configure the CA
1801 */
1802 if (key.key.define.ca.u_byte &&
1803 key.key.define.ca.u_byte[0]) {
1804 switch (key.key.define.ca_def) {
1806 if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1809 &key, COAP_DTLS_ROLE_SERVER, 0);
1810 }
1811 break;
1812 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1813 if (key.key.define.ca_len) {
1814 BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1815 (int)key.key.define.ca_len);
1816 X509 *x;
1817 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1818
1819 if (bp) {
1820 for (;;) {
1821 if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1822 break;
1823 add_ca_to_cert_store(st, x);
1824 SSL_CTX_add_client_CA(ctx, x);
1825 X509_free(x);
1826 }
1827 BIO_free(bp);
1828 }
1829 } else {
1832 &key, COAP_DTLS_ROLE_SERVER, 0);
1833 }
1834 break;
1835 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1838 &key, COAP_DTLS_ROLE_SERVER, 0);
1839 case COAP_PKI_KEY_DEF_DER: /* define ca */
1840 if (!(SSL_CTX_use_certificate_file(ctx,
1841 key.key.define.ca.s_byte,
1842 SSL_FILETYPE_ASN1))) {
1845 &key, COAP_DTLS_ROLE_SERVER, 0);
1846 }
1847 break;
1848 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1849 if (key.key.define.ca_len > 0) {
1850 /* Need to use a temp variable as it gets incremented*/
1851 const uint8_t *p = key.key.define.ca.u_byte;
1852 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1853 X509_STORE *st;
1854
1855 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1856 X509_free(x509);
1859 &key, COAP_DTLS_ROLE_SERVER, 0);
1860 }
1861
1862 /* Add CA to the trusted root CA store */
1863 st = SSL_CTX_get_cert_store(ctx);
1864 add_ca_to_cert_store(st, x509);
1865 X509_free(x509);
1866 }
1867 break;
1868 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1869 if (!check_pkcs11_engine()) {
1870 return 0;
1871 }
1872 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1873 key.key.define.ca.s_byte)) {
1876 &key, COAP_DTLS_ROLE_SERVER, 0);
1877 }
1878 break;
1879 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1880 if (!defined_engine ||
1881 !install_engine_ca_ctx(defined_engine, ctx,
1882 key.key.define.ca.s_byte)) {
1885 &key, COAP_DTLS_ROLE_SERVER, 0);
1886 }
1887 break;
1888 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1889 default:
1892 &key, COAP_DTLS_ROLE_SERVER, 0);
1893 }
1894 }
1895
1896 return 1;
1897}
1898#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1899
1900#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1901
1902static int
1903install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1904 coap_dtls_role_t role) {
1905 X509 *x509;
1906
1907 x509 = missing_ENGINE_load_cert(engine, public_cert);
1908 if (!x509) {
1909 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1910 "%s Certificate\n",
1911 public_cert,
1912 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1913 return 0;
1914 }
1915 if (!SSL_use_certificate(ssl, x509)) {
1916 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1917 "%s Certificate\n",
1918 public_cert,
1919 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1920 X509_free(x509);
1921 return 0;
1922 }
1923 X509_free(x509);
1924 return 1;
1925}
1926
1927static int
1928install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1929 coap_dtls_role_t role) {
1930 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1931 private_key,
1932 NULL, NULL);
1933
1934 if (!pkey) {
1935 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1936 "%s Private Key\n",
1937 private_key,
1938 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1939 return 0;
1940 }
1941 if (!SSL_use_PrivateKey(ssl, pkey)) {
1942 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1943 "%s Private Key\n",
1944 private_key,
1945 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1946 EVP_PKEY_free(pkey);
1947 return 0;
1948 }
1949 EVP_PKEY_free(pkey);
1950 return 1;
1951}
1952
1953static int
1954install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1955 coap_dtls_role_t role) {
1956 X509 *x509;
1957 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1958 X509_STORE *st;
1959
1960 if (!ctx) {
1961 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1962 "%s CA Certificate (no ctx)\n",
1963 ca,
1964 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1965 return 0;
1966 }
1967 x509 = missing_ENGINE_load_cert(engine,
1968 ca);
1969 if (!x509) {
1970 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1971 "%s CA Certificate\n",
1972 ca,
1973 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1974 return 0;
1975 }
1976 if (!SSL_add_client_CA(ssl, x509)) {
1977 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1978 "%s CA Certificate\n",
1979 ca,
1980 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1981 X509_free(x509);
1982 return 0;
1983 }
1984 st = SSL_CTX_get_cert_store(ctx);
1985 add_ca_to_cert_store(st, x509);
1986 X509_free(x509);
1987 return 1;
1988}
1989
1990static int
1991load_in_cas(SSL *ssl,
1992 const char *ca_file, coap_dtls_role_t role) {
1993 X509_STORE *st;
1994 BIO *in;
1995 X509 *x = NULL;
1996 char *rw_var = NULL;
1997 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1998
1999 if (role == COAP_DTLS_ROLE_SERVER) {
2000 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
2001
2002 if (cert_names != NULL)
2003 SSL_set_client_CA_list(ssl, cert_names);
2004 else {
2005 return 0;
2006 }
2007 }
2008
2009 if (!ctx)
2010 return 0;
2011
2012 /* Add CA to the trusted root CA store */
2013 in = BIO_new(BIO_s_file());
2014 if (!in)
2015 return 0;
2016 /* Need to do this to not get a compiler warning about const parameters */
2017 memcpy(&rw_var, &ca_file, sizeof(rw_var));
2018 if (!BIO_read_filename(in, rw_var)) {
2019 BIO_free(in);
2020 return 0;
2021 }
2022 st = SSL_CTX_get_cert_store(ctx);
2023 for (;;) {
2024 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
2025 break;
2026 add_ca_to_cert_store(st, x);
2027 X509_free(x);
2028 }
2029 BIO_free(in);
2030 return 1;
2031}
2032
2033static int
2034setup_pki_ssl(SSL *ssl,
2035 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
2036 coap_dtls_key_t key;
2037
2038 /* Map over to the new define format to save code duplication */
2039 coap_dtls_map_key_type_to_define(setup_data, &key);
2040
2041 assert(key.key_type == COAP_PKI_KEY_DEFINE);
2042
2043 /*
2044 * Configure the Private Key
2045 */
2046 if (key.key.define.private_key.u_byte &&
2047 key.key.define.private_key.u_byte[0]) {
2048 switch (key.key.define.private_key_def) {
2049 case COAP_PKI_KEY_DEF_PEM: /* define private key */
2050 if (!(SSL_use_PrivateKey_file(ssl,
2052 SSL_FILETYPE_PEM))) {
2055 &key, role, 0);
2056 }
2057 break;
2058 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2059 if (key.key.define.private_key_len) {
2060 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2061 (int)key.key.define.private_key_len);
2062 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2063
2064 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2065 if (bp)
2066 BIO_free(bp);
2067 if (pkey)
2068 EVP_PKEY_free(pkey);
2071 &key, role, 0);
2072 }
2073 if (bp)
2074 BIO_free(bp);
2075 if (pkey)
2076 EVP_PKEY_free(pkey);
2077 } else {
2080 &key, role, 0);
2081 }
2082 break;
2083 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2086 &key, role, 0);
2087 case COAP_PKI_KEY_DEF_DER: /* define private key */
2088 if (!(SSL_use_PrivateKey_file(ssl,
2090 SSL_FILETYPE_ASN1))) {
2093 &key, role, 0);
2094 }
2095 break;
2096 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2097 if (key.key.define.private_key_len == 0 ||
2098 !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2099 ssl,
2101 (long)key.key.define.private_key_len))) {
2104 &key, role, 0);
2105 }
2106 break;
2107 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2108 if (!check_pkcs11_engine()) {
2109 return 0;
2110 }
2111 if (key.key.define.user_pin) {
2112 /* If not set, pin-value may be held in pkcs11: URI */
2113 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2114 "PIN",
2115 key.key.define.user_pin, 0) == 0) {
2116 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2117 key.key.define.user_pin);
2118 return 0;
2119 }
2120 }
2121 if (!install_engine_private_key(pkcs11_engine, ssl,
2123 role)) {
2126 &key, role, 0);
2127 }
2128 break;
2129 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2130 if (!defined_engine ||
2131 !install_engine_private_key(defined_engine, ssl,
2133 role)) {
2136 &key, role, 0);
2137 }
2138 break;
2139 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2140 default:
2143 &key, role, 0);
2144 }
2145 } else if (role == COAP_DTLS_ROLE_SERVER ||
2147 key.key.define.public_cert.u_byte[0])) {
2150 &key, role, 0);
2151 }
2152
2153 /*
2154 * Configure the Public Certificate / Key
2155 */
2156 if (key.key.define.public_cert.u_byte &&
2157 key.key.define.public_cert.u_byte[0]) {
2158 switch (key.key.define.public_cert_def) {
2159 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2160 if (key.key.define.ca.u_byte &&
2161 key.key.define.ca.u_byte[0]) {
2162 /* If CA is separately defined */
2163 if (!(SSL_use_certificate_file(ssl,
2165 SSL_FILETYPE_PEM))) {
2168 &key, role, 0);
2169 }
2170 } else {
2171 if (!SSL_use_certificate_chain_file(ssl,
2175 &key, role, 0);
2176 }
2177 }
2178 break;
2179 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2180 if (key.key.define.public_cert_len) {
2181 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2182 (int)key.key.define.public_cert_len);
2183 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2184
2185 if (!cert || !SSL_use_certificate(ssl, cert)) {
2186 if (bp)
2187 BIO_free(bp);
2188 if (cert)
2189 X509_free(cert);
2192 &key, role, 0);
2193 }
2194 if (bp)
2195 BIO_free(bp);
2196 if (cert)
2197 X509_free(cert);
2198 } else {
2201 &key, role, 0);
2202 }
2203 break;
2204 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2207 &key, role, 0);
2208 case COAP_PKI_KEY_DEF_DER: /* define public cert */
2209 if (!(SSL_use_certificate_file(ssl,
2211 SSL_FILETYPE_ASN1))) {
2214 &key, role, 0);
2215 }
2216 break;
2217 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2218 if (key.key.define.public_cert_len == 0 ||
2219 !(SSL_use_certificate_ASN1(ssl,
2221 (int)key.key.define.public_cert_len))) {
2224 &key, role, 0);
2225 }
2226 break;
2227 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2228 if (!check_pkcs11_engine()) {
2229 return 0;
2230 }
2231 if (!install_engine_public_cert(pkcs11_engine, ssl,
2233 role)) {
2236 &key, role, 0);
2237 }
2238 break;
2239 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2240 if (!defined_engine ||
2241 !install_engine_public_cert(defined_engine, ssl,
2243 role)) {
2246 &key, role, 0);
2247 }
2248 break;
2249 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2250 default:
2253 &key, role, 0);
2254 }
2255 } else if (role == COAP_DTLS_ROLE_SERVER ||
2257 key.key.define.private_key.u_byte[0])) {
2260 &key, role, 0);
2261 }
2262
2263 /*
2264 * Configure the CA
2265 */
2266 if (key.key.define.ca.u_byte &&
2267 key.key.define.ca.u_byte[0]) {
2268 switch (key.key.define.ca_def) {
2270 if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2273 &key, role, 0);
2274 }
2275 break;
2276 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2277 if (key.key.define.ca_len) {
2278 BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2279 (int)key.key.define.ca_len);
2280 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2281 X509 *x;
2282 X509_STORE *st = ctx? SSL_CTX_get_cert_store(ctx) : NULL;
2283
2284 if (bp) {
2285 for (;;) {
2286 if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2287 break;
2288 if (st)
2289 add_ca_to_cert_store(st, x);
2290 SSL_add_client_CA(ssl, x);
2291 X509_free(x);
2292 }
2293 BIO_free(bp);
2294 }
2295 } else {
2298 &key, role, 0);
2299 }
2300 break;
2301 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2304 &key, role, 0);
2305 case COAP_PKI_KEY_DEF_DER: /* define ca */
2306 if (!(SSL_use_certificate_file(ssl,
2307 key.key.define.ca.s_byte,
2308 SSL_FILETYPE_ASN1))) {
2311 &key, role, 0);
2312 }
2313 break;
2314 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2315 if (key.key.define.ca_len > 0) {
2316 /* Need to use a temp variable as it gets incremented*/
2317 const uint8_t *p = key.key.define.ca.u_byte;
2318 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2319 X509_STORE *st;
2320 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2321
2322 if (role == COAP_DTLS_ROLE_SERVER) {
2323 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2324 X509_free(x509);
2327 &key, role, 0);
2328 }
2329 }
2330
2331 /* Add CA to the trusted root CA store */
2332 st = ctx ? SSL_CTX_get_cert_store(ctx) : NULL;
2333 if (st)
2334 add_ca_to_cert_store(st, x509);
2335 X509_free(x509);
2336 }
2337 break;
2338 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2339 if (!check_pkcs11_engine()) {
2340 return 0;
2341 }
2342 if (!install_engine_ca(pkcs11_engine, ssl,
2343 key.key.define.ca.s_byte,
2344 role)) {
2347 &key, role, 0);
2348 }
2349 break;
2350 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2351 if (!defined_engine ||
2352 !install_engine_ca(defined_engine, ssl,
2353 key.key.define.ca.s_byte,
2354 role)) {
2357 &key, role, 0);
2358 }
2359 break;
2360 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2361 default:
2364 &key, role, 0);
2365 }
2366 }
2367
2368 return 1;
2369}
2370#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2371
2372static char *
2373get_san_or_cn_from_cert(X509 *x509) {
2374 if (x509) {
2375 char *cn;
2376 int n;
2377 STACK_OF(GENERAL_NAME) *san_list;
2378 char buffer[256];
2379
2380 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2381 if (san_list) {
2382 int san_count = sk_GENERAL_NAME_num(san_list);
2383
2384 for (n = 0; n < san_count; n++) {
2385 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2386
2387 if (name && name->type == GEN_DNS) {
2388 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2389
2390 /* Make sure that there is not an embedded NUL in the dns_name */
2391 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2392 continue;
2393 cn = OPENSSL_strdup(dns_name);
2394 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2395 return cn;
2396 }
2397 }
2398 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2399 }
2400 /* Otherwise look for the CN= field */
2401 X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2402
2403 /* Need to emulate strcasestr() here. Looking for CN= */
2404 n = (int)strlen(buffer) - 3;
2405 cn = buffer;
2406 while (n > 0) {
2407 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2408 ((cn[1] == 'N') || (cn[1] == 'n')) &&
2409 (cn[2] == '=')) {
2410 cn += 3;
2411 break;
2412 }
2413 cn++;
2414 n--;
2415 }
2416 if (n > 0) {
2417 char *ecn = strchr(cn, '/');
2418 if (ecn) {
2419 return OPENSSL_strndup(cn, ecn-cn);
2420 } else {
2421 return OPENSSL_strdup(cn);
2422 }
2423 }
2424 }
2425 return NULL;
2426}
2427
2428static int
2429tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2430 int index = SSL_get_ex_data_X509_STORE_CTX_idx();
2431 SSL *ssl = index >= 0 ? X509_STORE_CTX_get_ex_data(ctx, index) : NULL;
2432 coap_session_t *session = ssl ? SSL_get_app_data(ssl) : NULL;
2433 coap_openssl_context_t *context = (session && session->context) ?
2434 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2435 coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
2436 int depth = X509_STORE_CTX_get_error_depth(ctx);
2437 int err = X509_STORE_CTX_get_error(ctx);
2438 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2439 char *cn = x509 ? get_san_or_cn_from_cert(x509) : NULL;
2440 int keep_preverify_ok = preverify_ok;
2441
2442 coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2443 depth, err, preverify_ok, cn);
2444 if (!setup_data) {
2445 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2446 OPENSSL_free(cn);
2447 return 0;
2448 }
2449 if (!preverify_ok) {
2450 switch (err) {
2451 case X509_V_ERR_CERT_NOT_YET_VALID:
2452 case X509_V_ERR_CERT_HAS_EXPIRED:
2453 if (setup_data->allow_expired_certs)
2454 preverify_ok = 1;
2455 break;
2456 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2457 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2458 preverify_ok = 1;
2459 break;
2460 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2461 if (!setup_data->verify_peer_cert)
2462 preverify_ok = 1;
2463 break;
2464 case X509_V_ERR_UNABLE_TO_GET_CRL:
2465 if (setup_data->allow_no_crl)
2466 preverify_ok = 1;
2467 break;
2468 case X509_V_ERR_CRL_NOT_YET_VALID:
2469 case X509_V_ERR_CRL_HAS_EXPIRED:
2470 if (setup_data->allow_expired_crl)
2471 preverify_ok = 1;
2472 break;
2473 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2474 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2475 case X509_V_ERR_AKID_SKID_MISMATCH:
2476 if (!setup_data->verify_peer_cert)
2477 preverify_ok = 1;
2478 break;
2479 default:
2480 break;
2481 }
2482 if (setup_data->cert_chain_validation &&
2483 depth > (setup_data->cert_chain_verify_depth + 1)) {
2484 preverify_ok = 0;
2485 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2486 X509_STORE_CTX_set_error(ctx, err);
2487 }
2488 if (!preverify_ok) {
2489 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2490 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2491 coap_session_str(session),
2492 "Unknown CA", cn ? cn : "?", depth);
2493 } else {
2494 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2495 coap_session_str(session),
2496 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2497 }
2498 } else {
2499 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
2500 coap_session_str(session),
2501 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2502 }
2503 }
2504 /* Certificate - depth == 0 is the Client Cert */
2505 if (setup_data->validate_cn_call_back && keep_preverify_ok) {
2506 int length = i2d_X509(x509, NULL);
2507 uint8_t *base_buf;
2508 uint8_t *base_buf2 = base_buf = length > 0 ? OPENSSL_malloc(length) : NULL;
2509 int ret;
2510
2511 if (base_buf) {
2512 /* base_buf2 gets moved to the end */
2513 assert(i2d_X509(x509, &base_buf2) > 0);
2514 (void)base_buf2;
2516 setup_data->validate_cn_call_back(cn, base_buf, length, session,
2517 depth, preverify_ok,
2518 setup_data->cn_call_back_arg));
2519 if (!ret) {
2520 if (depth == 0) {
2521 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2522 } else {
2523 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2524 }
2525 preverify_ok = 0;
2526 }
2527 OPENSSL_free(base_buf);
2528 } else {
2529 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2530 preverify_ok = 0;
2531 }
2532 }
2533 OPENSSL_free(cn);
2534 return preverify_ok;
2535}
2536
2537#if COAP_SERVER_SUPPORT
2538#if OPENSSL_VERSION_NUMBER < 0x10101000L
2539/* OpenSSL < 1.1.1 */
2540/*
2541 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2542 * it is possible to determine whether this is a PKI or PSK incoming
2543 * request and adjust the ciphers if necessary
2544 *
2545 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2546 */
2547static int
2548tls_secret_call_back(SSL *ssl,
2549 void *secret,
2550 int *secretlen,
2551 STACK_OF(SSL_CIPHER) *peer_ciphers,
2552 const SSL_CIPHER **cipher COAP_UNUSED,
2553 void *arg) {
2554 int ii;
2555 int psk_requested = 0;
2556 coap_session_t *session;
2557 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2558
2559 session = (coap_session_t *)SSL_get_app_data(ssl);
2560 assert(session != NULL);
2561 assert(session->context != NULL);
2562 if (session == NULL ||
2563 session->context == NULL)
2564 return 0;
2565
2566 if ((session->psk_key) ||
2567 (session->context->spsk_setup_data.psk_info.key.s &&
2568 session->context->spsk_setup_data.psk_info.key.length)) {
2569 /* Is PSK being requested - if so, we need to change algorithms */
2570 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2571 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2572
2573 coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2574 SSL_CIPHER_get_name(peer_cipher));
2575 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2576 psk_requested = 1;
2577 break;
2578 }
2579 }
2580 }
2581 if (!psk_requested) {
2582 coap_log_debug(" %s: Using PKI ciphers\n",
2583 coap_session_str(session));
2584
2585 if (setup_data->verify_peer_cert) {
2586 SSL_set_verify(ssl,
2587 SSL_VERIFY_PEER |
2588 SSL_VERIFY_CLIENT_ONCE |
2589 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2590 tls_verify_call_back);
2591 } else {
2592 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2593 }
2594
2595 /* Check CA Chain */
2596 if (setup_data->cert_chain_validation)
2597 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2598
2599 /* Certificate Revocation */
2600 if (setup_data->check_cert_revocation) {
2601 X509_VERIFY_PARAM *param;
2602
2603 param = X509_VERIFY_PARAM_new();
2604 if (param) {
2605 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2606 SSL_set1_param(ssl, param);
2607 X509_VERIFY_PARAM_free(param);
2608 }
2609 }
2610 if (setup_data->additional_tls_setup_call_back) {
2611 /* Additional application setup wanted */
2612 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2613 return 0;
2614 }
2615 } else {
2616 if (session->psk_key) {
2617 memcpy(secret, session->psk_key->s, session->psk_key->length);
2618 *secretlen = session->psk_key->length;
2619 } else if (session->context->spsk_setup_data.psk_info.key.s &&
2620 session->context->spsk_setup_data.psk_info.key.length) {
2621 memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2622 session->context->spsk_setup_data.psk_info.key.length);
2623 *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2624 }
2625 coap_log_debug(" %s: Setting PSK ciphers\n",
2626 coap_session_str(session));
2627 /*
2628 * Force a PSK algorithm to be used, so we do PSK
2629 */
2630 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2631#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
2632 /*
2633 * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
2634 * Potentially opens up security vulnerabilities.
2635 * Default value is 1.
2636 */
2637 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
2638#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
2639 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2640 }
2641 return 0;
2642}
2643
2644/* OpenSSL < 1.1.1 */
2645/*
2646 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2647 * called so it is possible to set up an extra callback to determine whether
2648 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2649 *
2650 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2651 * coap_dtls_context_set_pki()
2652 */
2653static int
2654tls_server_name_call_back(SSL *ssl,
2655 int *sd COAP_UNUSED,
2656 void *arg) {
2657 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2658
2659 if (!ssl) {
2660 return SSL_TLSEXT_ERR_NOACK;
2661 }
2662
2663 if (setup_data->validate_sni_call_back) {
2664 /* SNI checking requested */
2665 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2666 coap_openssl_context_t *context = (session && session->context) ?
2667 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2668 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2669 size_t i;
2670
2671 if !context)
2672 return SSL_TLSEXT_ERR_NOACK;
2673
2674 if (!sni || !sni[0]) {
2675 sni = "";
2676 }
2677 for (i = 0; i < context->sni_count; i++) {
2678 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2679 break;
2680 }
2681 }
2682 if (i == context->sni_count) {
2683 SSL_CTX *ctx;
2684 coap_dtls_pki_t sni_setup_data;
2685 coap_dtls_key_t *new_entry;
2686
2687 coap_lock_callback_ret(new_entry,
2688 setup_data->validate_sni_call_back(sni,
2689 setup_data->sni_call_back_arg));
2690 if (!new_entry) {
2691 return SSL_TLSEXT_ERR_ALERT_FATAL;
2692 }
2693 /* Need to set up a new SSL_CTX to switch to */
2694 if (session->proto == COAP_PROTO_DTLS) {
2695 /* Set up DTLS context */
2696 ctx = SSL_CTX_new(DTLS_method());
2697 if (!ctx)
2698 goto error;
2699 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2700 SSL_CTX_set_app_data(ctx, &context->dtls);
2701 SSL_CTX_set_read_ahead(ctx, 1);
2702 coap_set_user_prefs(ctx);
2703 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2704 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2705 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2706 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2707 }
2708#if !COAP_DISABLE_TCP
2709 else {
2710 /* Set up TLS context */
2711 ctx = SSL_CTX_new(TLS_method());
2712 if (!ctx)
2713 goto error;
2714 SSL_CTX_set_app_data(ctx, &context->tls);
2715 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2716 coap_set_user_prefs(ctx);
2717 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2718 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2719 }
2720#endif /* !COAP_DISABLE_TCP */
2721 sni_setup_data = *setup_data;
2722 sni_setup_data.pki_key = *new_entry;
2723 setup_pki_server(ctx, &sni_setup_data);
2724
2725 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2726 (context->sni_count+1)*sizeof(sni_entry));
2727 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2728 context->sni_entry_list[context->sni_count].ctx = ctx;
2729 context->sni_count++;
2730 }
2731 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2732 SSL_clear_options(ssl, 0xFFFFFFFFL);
2733 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2734 }
2735
2736 /*
2737 * Have to do extra call back next to get client algorithms
2738 * SSL_get_client_ciphers() does not work this early on
2739 */
2740 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2741 return SSL_TLSEXT_ERR_OK;
2742
2743error:
2744 return SSL_TLSEXT_ERR_ALERT_WARNING;
2745}
2746
2747/* OpenSSL < 1.1.1 */
2748/*
2749 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2750 * called to see if SNI is being used.
2751 *
2752 * Set up by SSL_CTX_set_tlsext_servername_callback()
2753 * in coap_dtls_context_set_spsk()
2754 */
2755static int
2756psk_tls_server_name_call_back(SSL *ssl,
2757 int *sd COAP_UNUSED,
2758 void *arg
2759 ) {
2760 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2761
2762 if (!ssl) {
2763 return SSL_TLSEXT_ERR_NOACK;
2764 }
2765
2766 if (setup_data->validate_sni_call_back) {
2767 /* SNI checking requested */
2768 coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2769 coap_openssl_context_t *o_context = (c_session && c_session->context) ?
2770 ((coap_openssl_context_t *)c_session->context->dtls_context) : NULL;
2771 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2772 size_t i;
2773 char lhint[COAP_DTLS_HINT_LENGTH];
2774
2775 if (!o_context)
2776 return SSL_TLSEXT_ERR_ALERT_FATAL;
2777
2778 if (!sni || !sni[0]) {
2779 sni = "";
2780 }
2781 for (i = 0; i < o_context->psk_sni_count; i++) {
2782 if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2783 break;
2784 }
2785 }
2786 if (i == o_context->psk_sni_count) {
2787 SSL_CTX *ctx;
2788 const coap_dtls_spsk_info_t *new_entry;
2789
2790 coap_lock_callback_ret(new_entry,
2791 setup_data->validate_sni_call_back(sni,
2792 c_session,
2793 setup_data->sni_call_back_arg));
2794 if (!new_entry) {
2795 return SSL_TLSEXT_ERR_ALERT_FATAL;
2796 }
2797 /* Need to set up a new SSL_CTX to switch to */
2798 if (c_session->proto == COAP_PROTO_DTLS) {
2799 /* Set up DTLS context */
2800 ctx = SSL_CTX_new(DTLS_method());
2801 if (!ctx)
2802 goto error;
2803 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2804 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2805 SSL_CTX_set_read_ahead(ctx, 1);
2806 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2807 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2808 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2809 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2810 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2811 }
2812#if !COAP_DISABLE_TCP
2813 else {
2814 /* Set up TLS context */
2815 ctx = SSL_CTX_new(TLS_method());
2816 if (!ctx)
2817 goto error;
2818 SSL_CTX_set_app_data(ctx, &o_context->tls);
2819 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2820 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2821 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2822 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2823 }
2824#endif /* !COAP_DISABLE_TCP */
2825
2826 o_context->psk_sni_entry_list =
2827 OPENSSL_realloc(o_context->psk_sni_entry_list,
2828 (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2829 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2830 OPENSSL_strdup(sni);
2831 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2832 *new_entry;
2833 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2834 ctx;
2835 o_context->psk_sni_count++;
2836 }
2837 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2838 SSL_clear_options(ssl, 0xFFFFFFFFL);
2839 SSL_set_options(ssl,
2840 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2842 &o_context->psk_sni_entry_list[i].psk_info.key);
2843 snprintf(lhint, sizeof(lhint), "%.*s",
2844 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2845 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2846 SSL_use_psk_identity_hint(ssl, lhint);
2847 }
2848
2849 /*
2850 * Have to do extra call back next to get client algorithms
2851 * SSL_get_client_ciphers() does not work this early on
2852 */
2853 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2854 return SSL_TLSEXT_ERR_OK;
2855
2856error:
2857 return SSL_TLSEXT_ERR_ALERT_WARNING;
2858}
2859#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2860/* OpenSSL >= 1.1.1 */
2861/*
2862 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2863 * called early in the Client Hello processing so it is possible to determine
2864 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2865 * necessary.
2866 *
2867 * Set up by SSL_CTX_set_client_hello_cb().
2868 */
2869static int
2870tls_client_hello_call_back(SSL *ssl,
2871 int *al,
2872 void *arg COAP_UNUSED
2873 ) {
2874 coap_session_t *session;
2875 coap_openssl_context_t *dtls_context;
2876 coap_dtls_pki_t *setup_data;
2877 int psk_requested = 0;
2878 const unsigned char *out;
2879 size_t outlen;
2880
2881 if (!ssl) {
2882 *al = SSL_AD_INTERNAL_ERROR;
2883 return SSL_CLIENT_HELLO_ERROR;
2884 }
2885 session = (coap_session_t *)SSL_get_app_data(ssl);
2886 assert(session != NULL);
2887 assert(session->context != NULL);
2888 assert(session->context->dtls_context != NULL);
2889 if (session == NULL ||
2890 session->context == NULL ||
2891 session->context->dtls_context == NULL) {
2892 *al = SSL_AD_INTERNAL_ERROR;
2893 return SSL_CLIENT_HELLO_ERROR;
2894 }
2895 dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2896 setup_data = &dtls_context->setup_data;
2897
2898 /*
2899 * See if PSK being requested
2900 */
2901 if ((session->psk_key) ||
2902 (session->context->spsk_setup_data.psk_info.key.s &&
2903 session->context->spsk_setup_data.psk_info.key.length)) {
2904 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2905 STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2906 STACK_OF(SSL_CIPHER) *scsvc = NULL;
2907
2908 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2909 SSL_client_hello_isv2(ssl),
2910 &peer_ciphers, &scsvc)) {
2911 int ii;
2912 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2913 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2914
2916 "Client cipher: %s (%04x)\n",
2917 SSL_CIPHER_get_name(peer_cipher),
2918 SSL_CIPHER_get_protocol_id(peer_cipher));
2919 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2920 psk_requested = 1;
2921 break;
2922 }
2923 }
2924 }
2925 sk_SSL_CIPHER_free(peer_ciphers);
2926 sk_SSL_CIPHER_free(scsvc);
2927 }
2928
2929 if (psk_requested) {
2930 /*
2931 * Client has requested PSK and it is supported
2932 */
2933 coap_log_debug(" %s: PSK request\n",
2934 coap_session_str(session));
2935 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2936 if (setup_data->additional_tls_setup_call_back) {
2937 /* Additional application setup wanted */
2938 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2939 return 0;
2940 }
2941 return SSL_CLIENT_HELLO_SUCCESS;
2942 }
2943
2944 /*
2945 * Handle Certificate requests
2946 */
2947
2948 /*
2949 * Determine what type of certificate is being requested
2950 */
2951 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
2952 &out, &outlen)) {
2953 size_t ii;
2954 for (ii = 0; ii < outlen; ii++) {
2955 switch (out[ii]) {
2956 case 0:
2957 /* RFC6091 X.509 */
2958 if (outlen >= 2) {
2959 /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
2960 goto is_x509;
2961 }
2962 break;
2963 case 2:
2964 /* RFC7250 RPK - not yet supported */
2965 break;
2966 default:
2967 break;
2968 }
2969 }
2970 *al = SSL_AD_UNSUPPORTED_EXTENSION;
2971 return SSL_CLIENT_HELLO_ERROR;
2972 }
2973
2974is_x509:
2975 if (setup_data->validate_sni_call_back) {
2976 /*
2977 * SNI checking requested
2978 */
2979 coap_dtls_pki_t sni_setup_data;
2980 coap_openssl_context_t *context =
2981 ((coap_openssl_context_t *)session->context->dtls_context);
2982 const char *sni = "";
2983 char *sni_tmp = NULL;
2984 size_t i;
2985
2986 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2987 outlen > 5 &&
2988 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2989 out[2] == TLSEXT_NAMETYPE_host_name &&
2990 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2991 /* Skip over length, type and length */
2992 out += 5;
2993 outlen -= 5;
2994 sni_tmp = OPENSSL_malloc(outlen+1);
2995 sni_tmp[outlen] = '\000';
2996 memcpy(sni_tmp, out, outlen);
2997 sni = sni_tmp;
2998 }
2999 /* Is this a cached entry? */
3000 for (i = 0; i < context->sni_count; i++) {
3001 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
3002 break;
3003 }
3004 }
3005 if (i == context->sni_count) {
3006 /*
3007 * New SNI request
3008 */
3009 coap_dtls_key_t *new_entry;
3010
3011 coap_lock_callback_ret(new_entry,
3012 setup_data->validate_sni_call_back(sni,
3013 setup_data->sni_call_back_arg));
3014 if (!new_entry) {
3015 *al = SSL_AD_UNRECOGNIZED_NAME;
3016 return SSL_CLIENT_HELLO_ERROR;
3017 }
3018
3019
3020 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
3021 (context->sni_count+1)*sizeof(sni_entry));
3022 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
3023 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
3024 context->sni_count++;
3025 }
3026 if (sni_tmp) {
3027 OPENSSL_free(sni_tmp);
3028 }
3029 sni_setup_data = *setup_data;
3030 sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
3031 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
3032 } else {
3033 setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
3034 }
3035
3036 coap_log_debug(" %s: Using PKI ciphers\n",
3037 coap_session_str(session));
3038
3039 if (setup_data->verify_peer_cert) {
3040 SSL_set_verify(ssl,
3041 SSL_VERIFY_PEER |
3042 SSL_VERIFY_CLIENT_ONCE |
3043 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3044 tls_verify_call_back);
3045 } else {
3046 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3047 }
3048
3049 /* Check CA Chain */
3050 if (setup_data->cert_chain_validation)
3051 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
3052
3053 /* Certificate Revocation */
3054 if (setup_data->check_cert_revocation) {
3055 X509_VERIFY_PARAM *param;
3056
3057 param = X509_VERIFY_PARAM_new();
3058 if (param) {
3059 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3060 SSL_set1_param(ssl, param);
3061 X509_VERIFY_PARAM_free(param);
3062 }
3063 }
3064 if (setup_data->additional_tls_setup_call_back) {
3065 /* Additional application setup wanted */
3066 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3067 return 0;
3068 }
3069 return SSL_CLIENT_HELLO_SUCCESS;
3070}
3071
3072/* OpenSSL >= 1.1.1 */
3073/*
3074 * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is
3075 * called early in the Client Hello processing so it is possible to determine
3076 * whether SNI needs to be handled
3077 *
3078 * Set up by SSL_CTX_set_client_hello_cb().
3079 */
3080static int
3081psk_tls_client_hello_call_back(SSL *ssl,
3082 int *al,
3083 void *arg COAP_UNUSED
3084 ) {
3085 coap_session_t *c_session;
3086 coap_openssl_context_t *o_context;
3087 coap_dtls_spsk_t *setup_data;
3088 const unsigned char *out;
3089 size_t outlen;
3090
3091 if (!ssl)
3092 goto int_err;
3093 c_session = (coap_session_t *)SSL_get_app_data(ssl);
3094 if (!c_session || !c_session->context) {
3095 goto int_err;
3096 }
3097 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
3098 if (!o_context) {
3099 goto int_err;
3100 }
3101 setup_data = &c_session->context->spsk_setup_data;
3102
3103 if (setup_data->validate_sni_call_back) {
3104 /*
3105 * SNI checking requested
3106 */
3107 const char *sni = "";
3108 char *sni_tmp = NULL;
3109 char lhint[COAP_DTLS_HINT_LENGTH];
3110
3111 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3112 outlen > 5 &&
3113 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3114 out[2] == TLSEXT_NAMETYPE_host_name &&
3115 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3116 /* Skip over length, type and length */
3117 out += 5;
3118 outlen -= 5;
3119 sni_tmp = OPENSSL_malloc(outlen+1);
3120 if (sni_tmp) {
3121 sni_tmp[outlen] = '\000';
3122 memcpy(sni_tmp, out, outlen);
3123 sni = sni_tmp;
3124 }
3125 }
3126
3127#if OPENSSL_VERSION_NUMBER < 0x10101000L
3128 size_t i;
3129 /* Is this a cached entry? */
3130 for (i = 0; i < o_context->psk_sni_count; i++) {
3131 if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) {
3132 break;
3133 }
3134 }
3135 if (i == o_context->psk_sni_count) {
3136#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3137 /*
3138 * New SNI request
3139 */
3140 const coap_dtls_spsk_info_t *new_entry;
3141
3142 coap_lock_callback_ret(new_entry,
3143 setup_data->validate_sni_call_back(
3144 sni,
3145 c_session,
3146 setup_data->sni_call_back_arg));
3147 if (!new_entry) {
3148 *al = SSL_AD_UNRECOGNIZED_NAME;
3149 return SSL_CLIENT_HELLO_ERROR;
3150 }
3151
3152#if OPENSSL_VERSION_NUMBER < 0x10101000L
3153 psk_sni_entry *tmp_entry;
3154 tmp_entry =
3155 OPENSSL_realloc(o_context->psk_sni_entry_list,
3156 (o_context->psk_sni_count+1)*sizeof(sni_entry));
3157 if (tmp_entry) {
3158 o_context->psk_sni_entry_list = tmp_entry;
3159 o_context->psk_sni_entry_list[o_context->psk_sni_count]
3160 .sni =
3161 OPENSSL_strdup(sni);
3162 if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) {
3163 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
3164 *new_entry;
3165 o_context->psk_sni_count++;
3166 }
3167 }
3168 } else {
3169 new_entry = &o_context->psk_sni_entry_list[i].psk_info;
3170 }
3171#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3172
3173 if (sni_tmp) {
3174 OPENSSL_free(sni_tmp);
3175 }
3176 if (coap_session_refresh_psk_hint(c_session,
3177 &new_entry->hint)
3178 == 0) {
3179 goto int_err;
3180 }
3181 if (coap_session_refresh_psk_key(c_session,
3182 &new_entry->key)
3183 == 0) {
3184 goto int_err;
3185 }
3186 if (new_entry->hint.s) {
3187 snprintf(lhint, sizeof(lhint), "%.*s",
3188 (int)new_entry->hint.length,
3189 new_entry->hint.s);
3190 SSL_use_psk_identity_hint(ssl, lhint);
3191 }
3192 }
3193 return SSL_CLIENT_HELLO_SUCCESS;
3194
3195int_err:
3196 *al = SSL_AD_INTERNAL_ERROR;
3197 return SSL_CLIENT_HELLO_ERROR;
3198}
3199#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3200#endif /* COAP_SERVER_SUPPORT */
3201
3202int
3204 const coap_dtls_pki_t *setup_data,
3205 const coap_dtls_role_t role) {
3206 coap_openssl_context_t *context =
3207 ((coap_openssl_context_t *)ctx->dtls_context);
3208 BIO *bio;
3209 if (!setup_data)
3210 return 0;
3211 context->setup_data = *setup_data;
3212
3213 if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3214 if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3215 context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3216 context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3217 if (!defined_engine) {
3218 coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3219 return 0;
3220 }
3221 }
3222 }
3223
3224 if (!context->setup_data.verify_peer_cert) {
3225 /* Needs to be clear so that no CA DNs are transmitted */
3226 context->setup_data.check_common_ca = 0;
3227 /* Allow all of these but warn if issue */
3228 context->setup_data.allow_self_signed = 1;
3229 context->setup_data.allow_expired_certs = 1;
3230 context->setup_data.cert_chain_validation = 1;
3231 context->setup_data.cert_chain_verify_depth = 10;
3232 context->setup_data.check_cert_revocation = 1;
3233 context->setup_data.allow_no_crl = 1;
3234 context->setup_data.allow_expired_crl = 1;
3235 context->setup_data.allow_bad_md_hash = 1;
3236 context->setup_data.allow_short_rsa_length = 1;
3237 }
3238#if COAP_SERVER_SUPPORT
3239 if (role == COAP_DTLS_ROLE_SERVER) {
3240 if (context->dtls.ctx) {
3241 /* SERVER DTLS */
3242#if OPENSSL_VERSION_NUMBER < 0x10101000L
3243 if (!setup_pki_server(context->dtls.ctx, setup_data))
3244 return 0;
3245#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3246 /* libcoap is managing TLS connection based on setup_data options */
3247 /* Need to set up logic to differentiate between a PSK or PKI session */
3248 /*
3249 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3250 * which is not in 1.1.0
3251 */
3252#if OPENSSL_VERSION_NUMBER < 0x10101000L
3253 if (SSLeay() >= 0x10101000L) {
3254 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3255 "no certificate checking\n",
3256 OPENSSL_VERSION_NUMBER, SSLeay());
3257 }
3258 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3259 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3260 tls_server_name_call_back);
3261#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3262 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3263 tls_client_hello_call_back,
3264 NULL);
3265#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3266 }
3267#if !COAP_DISABLE_TCP
3268 if (context->tls.ctx) {
3269 /* SERVER TLS */
3270#if OPENSSL_VERSION_NUMBER < 0x10101000L
3271 if (!setup_pki_server(context->tls.ctx, setup_data))
3272 return 0;
3273#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3274 /* libcoap is managing TLS connection based on setup_data options */
3275 /* Need to set up logic to differentiate between a PSK or PKI session */
3276 /*
3277 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3278 * which is not in 1.1.0
3279 */
3280#if OPENSSL_VERSION_NUMBER < 0x10101000L
3281 if (SSLeay() >= 0x10101000L) {
3282 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3283 "no certificate checking\n",
3284 OPENSSL_VERSION_NUMBER, SSLeay());
3285 }
3286 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3287 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3288 tls_server_name_call_back);
3289#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3290 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3291 tls_client_hello_call_back,
3292 NULL);
3293#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3294 /* TLS Only */
3295 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3296 }
3297#endif /* !COAP_DISABLE_TCP */
3298 }
3299#else /* ! COAP_SERVER_SUPPORT */
3300 (void)role;
3301#endif /* ! COAP_SERVER_SUPPORT */
3302
3303 if (!context->dtls.ssl) {
3304 /* This is set up to handle new incoming sessions to a server */
3305 context->dtls.ssl = SSL_new(context->dtls.ctx);
3306 if (!context->dtls.ssl)
3307 return 0;
3308 bio = BIO_new(context->dtls.meth);
3309 if (!bio) {
3310 SSL_free(context->dtls.ssl);
3311 context->dtls.ssl = NULL;
3312 return 0;
3313 }
3314 SSL_set_bio(context->dtls.ssl, bio, bio);
3315 SSL_set_app_data(context->dtls.ssl, NULL);
3316 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3317 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3318 }
3319 context->psk_pki_enabled |= IS_PKI;
3320 if (setup_data->use_cid) {
3321 coap_log_warn("OpenSSL has no Connection-ID support\n");
3322 }
3323 return 1;
3324}
3325
3326int
3328 const char *ca_file,
3329 const char *ca_dir
3330 ) {
3331 coap_openssl_context_t *context =
3332 ((coap_openssl_context_t *)ctx->dtls_context);
3333 if (context->dtls.ctx) {
3334 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3335 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3336 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3337 return 0;
3338 }
3339 }
3340#if !COAP_DISABLE_TCP
3341 if (context->tls.ctx) {
3342 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3343 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3344 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3345 return 0;
3346 }
3347 }
3348#endif /* !COAP_DISABLE_TCP */
3349 return 1;
3350}
3351
3352int
3354#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3355 coap_openssl_context_t *context =
3356 ((coap_openssl_context_t *)ctx->dtls_context);
3357 if (context->dtls.ctx) {
3358 if (!SSL_CTX_set_default_verify_store(context->dtls.ctx)) {
3359 coap_log_warn("Unable to load trusted root CAs\n");
3360 return 0;
3361 }
3362 }
3363#if !COAP_DISABLE_TCP
3364 if (context->tls.ctx) {
3365 if (!SSL_CTX_set_default_verify_store(context->tls.ctx)) {
3366 coap_log_warn("Unable to load trusted root CAs\n");
3367 return 0;
3368 }
3369 }
3370#endif /* !COAP_DISABLE_TCP */
3371 return 1;
3372#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3373 (void)ctx;
3374 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3375 "not supported for OpenSSL < v3.0.0\n");
3376 return 0;
3377#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3378}
3379
3380int
3382 coap_openssl_context_t *context =
3383 ((coap_openssl_context_t *)ctx->dtls_context);
3384 return context->psk_pki_enabled ? 1 : 0;
3385}
3386
3387
3388void
3389coap_dtls_free_context(void *handle) {
3390 size_t i;
3391 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3392
3393 if (context->dtls.ssl)
3394 SSL_free(context->dtls.ssl);
3395 if (context->dtls.ctx)
3396 SSL_CTX_free(context->dtls.ctx);
3397 if (context->dtls.cookie_hmac)
3398 HMAC_CTX_free(context->dtls.cookie_hmac);
3399 if (context->dtls.meth)
3400 BIO_meth_free(context->dtls.meth);
3401 if (context->dtls.bio_addr)
3402 BIO_ADDR_free(context->dtls.bio_addr);
3403#if !COAP_DISABLE_TCP
3404 if (context->tls.ctx)
3405 SSL_CTX_free(context->tls.ctx);
3406 if (context->tls.meth)
3407 BIO_meth_free(context->tls.meth);
3408#endif /* !COAP_DISABLE_TCP */
3409 for (i = 0; i < context->sni_count; i++) {
3410 OPENSSL_free(context->sni_entry_list[i].sni);
3411#if OPENSSL_VERSION_NUMBER < 0x10101000L
3412 SSL_CTX_free(context->sni_entry_list[i].ctx);
3413#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3414 }
3415 if (context->sni_count)
3416 OPENSSL_free(context->sni_entry_list);
3417#if OPENSSL_VERSION_NUMBER < 0x10101000L
3418 for (i = 0; i < context->psk_sni_count; i++) {
3419 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3420 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3421 }
3422 if (context->psk_sni_count)
3423 OPENSSL_free(context->psk_sni_entry_list);
3424#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3425 coap_free_type(COAP_STRING, context);
3426}
3427
3428#if COAP_SERVER_SUPPORT
3429void *
3430coap_dtls_new_server_session(coap_session_t *session) {
3431 BIO *nbio = NULL;
3432 SSL *nssl = NULL, *ssl = NULL;
3433 coap_ssl_data *data;
3434 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3435 int r;
3436 const coap_bin_const_t *psk_hint;
3437 BIO *rbio;
3438
3439 nssl = SSL_new(dtls->ctx);
3440 if (!nssl)
3441 goto error;
3442 nbio = BIO_new(dtls->meth);
3443 if (!nbio)
3444 goto error;
3445 SSL_set_bio(nssl, nbio, nbio);
3446 SSL_set_app_data(nssl, NULL);
3447 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3448 SSL_set_mtu(nssl, (long)session->mtu);
3449 ssl = dtls->ssl;
3450 dtls->ssl = nssl;
3451 nssl = NULL;
3452 SSL_set_app_data(ssl, session);
3453
3454 rbio = SSL_get_rbio(ssl);
3455 data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3456 if (!data)
3457 goto error;
3458 data->session = session;
3459
3460 /* hint may get updated if/when handling SNI callback */
3461 psk_hint = coap_get_session_server_psk_hint(session);
3462 if (psk_hint != NULL && psk_hint->length) {
3463 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3464
3465 if (hint) {
3466 memcpy(hint, psk_hint->s, psk_hint->length);
3467 hint[psk_hint->length] = '\000';
3468 SSL_use_psk_identity_hint(ssl, hint);
3469 OPENSSL_free(hint);
3470 } else {
3471 coap_log_warn("hint malloc failure\n");
3472 }
3473 }
3474
3475 r = SSL_accept(ssl);
3476 if (r == -1) {
3477 int err = SSL_get_error(ssl, r);
3478 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3479 r = 0;
3480 }
3481
3482 if (r == 0) {
3483 SSL_free(ssl);
3484 return NULL;
3485 }
3486
3487 return ssl;
3488
3489error:
3490 if (nssl)
3491 SSL_free(nssl);
3492 return NULL;
3493}
3494#endif /* COAP_SERVER_SUPPORT */
3495
3496#if COAP_CLIENT_SUPPORT
3497static int
3498setup_client_ssl_session(coap_session_t *session, SSL *ssl
3499 ) {
3500 coap_openssl_context_t *context =
3501 ((coap_openssl_context_t *)session->context->dtls_context);
3502
3503 if (context->psk_pki_enabled & IS_PSK) {
3504 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3505
3506 /* Issue SNI if requested */
3507 if (setup_data->client_sni &&
3508 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3509 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3510 setup_data->client_sni);
3511 }
3512 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3513#if COAP_SERVER_SUPPORT
3514 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3515#endif /* COAP_SERVER_SUPPORT */
3516 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3517#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
3518 /*
3519 * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
3520 * Potentially opens up security vulnerabilities.
3521 * Default value is 1.
3522 */
3523 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
3524#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
3525 if (setup_data->validate_ih_call_back) {
3526 if (session->proto == COAP_PROTO_DTLS) {
3527 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3528 }
3529#if !COAP_DISABLE_TCP
3530 else {
3531 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3532 }
3533#endif /* !COAP_DISABLE_TCP */
3534 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3535 }
3536 }
3537 if ((context->psk_pki_enabled & IS_PKI) ||
3538 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3539 /*
3540 * If neither PSK or PKI have been set up, use PKI basics.
3541 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3542 */
3543 coap_dtls_pki_t *setup_data = &context->setup_data;
3544
3545 if (!(context->psk_pki_enabled & IS_PKI)) {
3546 /* PKI not defined - set up some defaults */
3547 setup_data->verify_peer_cert = 1;
3548 setup_data->check_common_ca = 0;
3549 setup_data->allow_self_signed = 1;
3550 setup_data->allow_expired_certs = 1;
3551 setup_data->cert_chain_validation = 1;
3552 setup_data->cert_chain_verify_depth = 2;
3553 setup_data->check_cert_revocation = 1;
3554 setup_data->allow_no_crl = 1;
3555 setup_data->allow_expired_crl = 1;
3556 setup_data->is_rpk_not_cert = 0;
3557 setup_data->use_cid = 0;
3558 }
3559 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3560 return 0;
3561 /* libcoap is managing (D)TLS connection based on setup_data options */
3562#if !COAP_DISABLE_TCP
3563 if (session->proto == COAP_PROTO_TLS)
3564 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3565#endif /* !COAP_DISABLE_TCP */
3566
3567 /* Issue SNI if requested */
3568 if (setup_data->client_sni &&
3569 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3570 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3571 setup_data->client_sni);
3572 }
3573 /* Certificate Revocation */
3574 if (setup_data->check_cert_revocation) {
3575 X509_VERIFY_PARAM *param;
3576
3577 param = X509_VERIFY_PARAM_new();
3578 if (param) {
3579 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3580 SSL_set1_param(ssl, param);
3581 X509_VERIFY_PARAM_free(param);
3582 }
3583 }
3584
3585 /* Verify Peer */
3586 if (setup_data->verify_peer_cert)
3587 SSL_set_verify(ssl,
3588 SSL_VERIFY_PEER |
3589 SSL_VERIFY_CLIENT_ONCE |
3590 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3591 tls_verify_call_back);
3592 else
3593 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3594
3595 /* Check CA Chain */
3596 if (setup_data->cert_chain_validation)
3597 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3598
3599 }
3600#if COAP_DTLS_RETRANSMIT_MS != 1000
3601#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3602 if (session->proto == COAP_PROTO_DTLS) {
3603 DTLS_set_timer_cb(ssl, timer_cb);
3604 }
3605#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3606#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3607 return 1;
3608}
3609
3610void *
3611coap_dtls_new_client_session(coap_session_t *session) {
3612 BIO *bio = NULL;
3613 SSL *ssl = NULL;
3614 coap_ssl_data *data;
3615 int r;
3616 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3617 coap_dtls_context_t *dtls = &context->dtls;
3618
3619 ssl = SSL_new(dtls->ctx);
3620 if (!ssl)
3621 goto error;
3622 bio = BIO_new(dtls->meth);
3623 if (!bio)
3624 goto error;
3625 data = (coap_ssl_data *)BIO_get_data(bio);
3626 if (!data)
3627 goto error;
3628 data->session = session;
3629 SSL_set_bio(ssl, bio, bio);
3630 SSL_set_app_data(ssl, session);
3631 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3632 SSL_set_mtu(ssl, (long)session->mtu);
3633
3634 if (!setup_client_ssl_session(session, ssl))
3635 goto error;
3636
3637 session->dtls_timeout_count = 0;
3638
3639 r = SSL_connect(ssl);
3640 if (r == -1) {
3641 int ret = SSL_get_error(ssl, r);
3642 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3643 r = 0;
3644 }
3645
3646 if (r == 0)
3647 goto error;
3648
3649 session->tls = ssl;
3650 return ssl;
3651
3652error:
3653 if (ssl)
3654 SSL_free(ssl);
3655 return NULL;
3656}
3657
3658void
3660 SSL *ssl = (SSL *)session->tls;
3661 if (ssl)
3662 SSL_set_mtu(ssl, (long)session->mtu);
3663}
3664#endif /* COAP_CLIENT_SUPPORT */
3665
3666void
3668 SSL *ssl = (SSL *)session->tls;
3669 if (ssl) {
3670 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3671 int r = SSL_shutdown(ssl);
3672 if (r == 0)
3673 SSL_shutdown(ssl);
3674 }
3675 SSL_free(ssl);
3676 session->tls = NULL;
3677 if (session->context)
3679 }
3680}
3681
3682ssize_t
3684 const uint8_t *data, size_t data_len) {
3685 int r;
3686 SSL *ssl = (SSL *)session->tls;
3687
3688 if (ssl == NULL) {
3690 return -1;
3691 }
3692
3693 session->dtls_event = -1;
3694 ERR_clear_error();
3695 r = SSL_write(ssl, data, (int)data_len);
3696
3697 if (r <= 0) {
3698 int err = SSL_get_error(ssl, r);
3699 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3700 r = 0;
3701 } else {
3702 if (err == SSL_ERROR_ZERO_RETURN)
3704 else if (err == SSL_ERROR_SSL) {
3705 unsigned long e = ERR_get_error();
3706
3707 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3708 coap_session_str(session),
3709 ERR_GET_REASON(e), ERR_reason_error_string(e));
3711 } else {
3712 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3713 coap_session_str(session), err);
3714 }
3715 r = -1;
3716 }
3717 }
3718
3719 if (session->dtls_event >= 0) {
3720 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3721 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3722 coap_handle_event_lkd(session->context, session->dtls_event, session);
3723 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3724 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3726 r = -1;
3727 }
3728 }
3729
3730 if (r > 0) {
3731 if (r == (ssize_t)data_len)
3732 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3733 coap_session_str(session), r);
3734 else
3735 coap_log_debug("* %s: dtls: sent %4d of %4" PRIdS " bytes\n",
3736 coap_session_str(session), r, data_len);
3737 }
3738 return r;
3739}
3740
3741int
3743 return 0;
3744}
3745
3747coap_dtls_get_context_timeout(void *dtls_context) {
3748 (void)dtls_context;
3749 return 0;
3750}
3751
3754 SSL *ssl = (SSL *)session->tls;
3755 coap_ssl_data *ssl_data;
3756 BIO *rbio;
3757
3758 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3759 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3760 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3761 return ssl_data ? ssl_data->timeout : 1000;
3762}
3763
3764/*
3765 * return 1 timed out
3766 * 0 still timing out
3767 */
3768int
3770 SSL *ssl = (SSL *)session->tls;
3771
3772 if (ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE) {
3773 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3774 (DTLSv1_handle_timeout(ssl) < 0)) {
3775 /* Too many retries */
3777 return 1;
3778 }
3779 return 0;
3780 }
3781 return 1;
3782}
3783
3784#if COAP_SERVER_SUPPORT
3785int
3786coap_dtls_hello(coap_session_t *session,
3787 const uint8_t *data, size_t data_len) {
3788 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3789 coap_ssl_data *ssl_data;
3790 int r;
3791 BIO *rbio;
3792
3793 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3794 rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) : NULL;
3795 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3796 assert(ssl_data != NULL);
3797 if (!ssl_data) {
3798 errno = ENOMEM;
3799 return -1;
3800 }
3801 if (ssl_data->pdu_len) {
3802 coap_log_err("** %s: Previous data not read %u bytes\n",
3803 coap_session_str(session), ssl_data->pdu_len);
3804 }
3805 ssl_data->session = session;
3806 ssl_data->pdu = data;
3807 ssl_data->pdu_len = (unsigned)data_len;
3808 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3809 if (r <= 0) {
3810 int err = SSL_get_error(dtls->ssl, r);
3811 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3812 /* Got a ClientHello, sent-out a VerifyRequest */
3813 r = 0;
3814 }
3815 } else {
3816 /* Got a valid answer to a VerifyRequest */
3817 r = 1;
3818 }
3819
3820 /*
3821 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3822 * only does a 'peek' read of the incoming data.
3823 *
3824 */
3825 return r;
3826}
3827#endif /* COAP_SERVER_SUPPORT */
3828
3829int
3830coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3831 coap_ssl_data *ssl_data;
3832 SSL *ssl = (SSL *)session->tls;
3833 int r;
3834 BIO *rbio;
3835#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3836 int retry = 0;
3837#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3838
3839 assert(ssl != NULL);
3840
3841 int in_init = SSL_in_init(ssl);
3842 uint8_t pdu[COAP_RXBUFFER_SIZE];
3843 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3844 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3845 assert(ssl_data != NULL);
3846 if (!ssl_data) {
3847 errno = ENOMEM;
3848 return -1;
3849 }
3850
3851 if (ssl_data->pdu_len) {
3852 coap_log_err("** %s: Previous data not read %u bytes\n",
3853 coap_session_str(session), ssl_data->pdu_len);
3854 }
3855 ssl_data->pdu = data;
3856 ssl_data->pdu_len = (unsigned)data_len;
3857
3858 session->dtls_event = -1;
3859#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3860retry:
3861#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3862 ERR_clear_error();
3863 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3864 if (r > 0) {
3865 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3866 coap_session_str(session), r);
3867 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3868 goto finished;
3869 } else {
3870 int err = SSL_get_error(ssl, r);
3871 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3872 if (in_init && SSL_is_init_finished(ssl)) {
3873 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3874 coap_session_str(session), SSL_get_cipher_name(ssl));
3876 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3877 }
3878 r = 0;
3879 } else {
3880 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3882 else if (err == SSL_ERROR_SSL) {
3883 unsigned long e = ERR_get_error();
3884
3885#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3886#include <openssl/proverr.h>
3887 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3888 /* Loading trust store - first access causes a directory read error */
3889 retry = 1;
3890 goto retry;
3891 }
3892#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3893 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3894 coap_session_str(session),
3895 ERR_GET_REASON(e), ERR_reason_error_string(e));
3897 } else {
3898 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3899 coap_session_str(session), err);
3900 }
3901 r = -1;
3902 }
3903 if (session->dtls_event >= 0) {
3904 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3905 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3906 coap_handle_event_lkd(session->context, session->dtls_event, session);
3907 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3908 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3910 ssl_data = NULL;
3911 r = -1;
3912 }
3913 }
3914 }
3915
3916finished:
3917 if (ssl_data && ssl_data->pdu_len) {
3918 /* pdu data is held on stack which will not stay there */
3919 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3920 ssl_data->pdu_len = 0;
3921 ssl_data->pdu = NULL;
3922 }
3923 return r;
3924}
3925
3926unsigned int
3928 unsigned int overhead = 37;
3929 const SSL_CIPHER *s_ciph = NULL;
3930 if (session->tls != NULL)
3931 s_ciph = SSL_get_current_cipher(session->tls);
3932 if (s_ciph) {
3933 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3934
3935 const EVP_CIPHER *e_ciph;
3936 const EVP_MD *e_md;
3937 char cipher[128];
3938
3939 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3940
3941 switch (EVP_CIPHER_mode(e_ciph)) {
3942 case EVP_CIPH_GCM_MODE:
3943 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3944 maclen = EVP_GCM_TLS_TAG_LEN;
3945 break;
3946
3947 case EVP_CIPH_CCM_MODE:
3948 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3949 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3950 if (strstr(cipher, "CCM8"))
3951 maclen = 8;
3952 else
3953 maclen = 16;
3954 break;
3955
3956 case EVP_CIPH_CBC_MODE:
3957 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3958 blocksize = EVP_CIPHER_block_size(e_ciph);
3959 ivlen = EVP_CIPHER_iv_length(e_ciph);
3960 pad = 1;
3961 maclen = EVP_MD_size(e_md);
3962 break;
3963
3964 case EVP_CIPH_STREAM_CIPHER:
3965 /* Seen with PSK-CHACHA20-POLY1305 */
3966 ivlen = 8;
3967 maclen = 8;
3968 break;
3969
3970 default:
3971 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3972 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3973 cipher);
3974 ivlen = 8;
3975 maclen = 16;
3976 break;
3977 }
3978 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3979 }
3980 return overhead;
3981}
3982
3983#if !COAP_DISABLE_TCP
3984#if COAP_CLIENT_SUPPORT
3985void *
3986coap_tls_new_client_session(coap_session_t *session) {
3987 BIO *bio = NULL;
3988 SSL *ssl = NULL;
3989 int r;
3990 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3991 coap_tls_context_t *tls = &context->tls;
3992
3993 ssl = SSL_new(tls->ctx);
3994 if (!ssl)
3995 goto error;
3996 bio = BIO_new(tls->meth);
3997 if (!bio)
3998 goto error;
3999 BIO_set_data(bio, session);
4000 SSL_set_bio(ssl, bio, bio);
4001 SSL_set_app_data(ssl, session);
4002
4003 if (!setup_client_ssl_session(session, ssl))
4004 return 0;
4005
4006 r = SSL_connect(ssl);
4007 if (r == -1) {
4008 int ret = SSL_get_error(ssl, r);
4009 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
4010 r = 0;
4011 if (ret == SSL_ERROR_WANT_READ)
4012 session->sock.flags |= COAP_SOCKET_WANT_READ;
4013 if (ret == SSL_ERROR_WANT_WRITE) {
4014 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4015#ifdef COAP_EPOLL_SUPPORT
4016 coap_epoll_ctl_mod(&session->sock,
4017 EPOLLOUT |
4018 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4019 EPOLLIN : 0),
4020 __func__);
4021#endif /* COAP_EPOLL_SUPPORT */
4022 }
4023 }
4024
4025 if (r == 0)
4026 goto error;
4027
4028 session->tls = ssl;
4029 if (SSL_is_init_finished(ssl)) {
4031 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4032 }
4033
4034 return ssl;
4035
4036error:
4037 if (ssl)
4038 SSL_free(ssl);
4039 return NULL;
4040}
4041#endif /* COAP_CLIENT_SUPPORT */
4042
4043#if COAP_SERVER_SUPPORT
4044void *
4045coap_tls_new_server_session(coap_session_t *session) {
4046 BIO *bio = NULL;
4047 SSL *ssl = NULL;
4048 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
4049 int r;
4050 const coap_bin_const_t *psk_hint;
4051
4052 ssl = SSL_new(tls->ctx);
4053 if (!ssl)
4054 goto error;
4055 bio = BIO_new(tls->meth);
4056 if (!bio)
4057 goto error;
4058 BIO_set_data(bio, session);
4059 SSL_set_bio(ssl, bio, bio);
4060 SSL_set_app_data(ssl, session);
4061
4062 psk_hint = coap_get_session_server_psk_hint(session);
4063 if (psk_hint != NULL && psk_hint->length) {
4064 char *hint = OPENSSL_malloc(psk_hint->length + 1);
4065
4066 if (hint) {
4067 memcpy(hint, psk_hint->s, psk_hint->length);
4068 hint[psk_hint->length] = '\000';
4069 SSL_use_psk_identity_hint(ssl, hint);
4070 OPENSSL_free(hint);
4071 } else {
4072 coap_log_warn("hint malloc failure\n");
4073 }
4074 }
4075
4076 r = SSL_accept(ssl);
4077 if (r == -1) {
4078 int err = SSL_get_error(ssl, r);
4079 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4080 r = 0;
4081 if (err == SSL_ERROR_WANT_READ)
4082 session->sock.flags |= COAP_SOCKET_WANT_READ;
4083 if (err == SSL_ERROR_WANT_WRITE) {
4084 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4085#ifdef COAP_EPOLL_SUPPORT
4086 coap_epoll_ctl_mod(&session->sock,
4087 EPOLLOUT |
4088 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4089 EPOLLIN : 0),
4090 __func__);
4091#endif /* COAP_EPOLL_SUPPORT */
4092 }
4093 }
4094
4095 if (r == 0)
4096 goto error;
4097
4098 session->tls = ssl;
4099 if (SSL_is_init_finished(ssl)) {
4101 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4102 }
4103
4104#if COAP_DTLS_RETRANSMIT_MS != 1000
4105#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4106 if (session->proto == COAP_PROTO_DTLS) {
4107 DTLS_set_timer_cb(ssl, timer_cb);
4108 }
4109#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4110#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4111
4112 return ssl;
4113
4114error:
4115 if (ssl)
4116 SSL_free(ssl);
4117 return NULL;
4118}
4119#endif /* COAP_SERVER_SUPPORT */
4120
4121void
4123 SSL *ssl = (SSL *)session->tls;
4124 if (ssl) {
4125 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4126 int r = SSL_shutdown(ssl);
4127 if (r == 0)
4128 SSL_shutdown(ssl);
4129 }
4130 SSL_free(ssl);
4131 session->tls = NULL;
4132 if (session->context)
4134 }
4135}
4136
4137/*
4138 * strm
4139 * return +ve Number of bytes written.
4140 * -1 Error (error in errno).
4141 */
4142ssize_t
4143coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4144 SSL *ssl = (SSL *)session->tls;
4145 int r, in_init;
4146
4147 if (ssl == NULL)
4148 return -1;
4149
4150 in_init = !SSL_is_init_finished(ssl);
4151 session->dtls_event = -1;
4152 ERR_clear_error();
4153 r = SSL_write(ssl, data, (int)data_len);
4154
4155 if (r <= 0) {
4156 int err = SSL_get_error(ssl, r);
4157 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4158 if (in_init && SSL_is_init_finished(ssl)) {
4159 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4160 coap_session_str(session), SSL_get_cipher_name(ssl));
4162 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4163 }
4164 if (err == SSL_ERROR_WANT_READ)
4165 session->sock.flags |= COAP_SOCKET_WANT_READ;
4166 else if (err == SSL_ERROR_WANT_WRITE) {
4167 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4168#ifdef COAP_EPOLL_SUPPORT
4169 coap_epoll_ctl_mod(&session->sock,
4170 EPOLLOUT |
4171 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4172 EPOLLIN : 0),
4173 __func__);
4174#endif /* COAP_EPOLL_SUPPORT */
4175 }
4176 r = 0;
4177 } else {
4178 if (err == SSL_ERROR_ZERO_RETURN)
4180 else if (err == SSL_ERROR_SSL) {
4181 unsigned long e = ERR_get_error();
4182
4183 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4184 coap_session_str(session),
4185 ERR_GET_REASON(e), ERR_reason_error_string(e));
4187 } else {
4188 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4189 coap_session_str(session), err);
4190 }
4191 r = -1;
4192 }
4193 } else if (in_init && SSL_is_init_finished(ssl)) {
4194 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4195 coap_session_str(session), SSL_get_cipher_name(ssl));
4197 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4198 }
4199
4200 if (session->dtls_event >= 0) {
4201 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4202 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4203 coap_handle_event_lkd(session->context, session->dtls_event, session);
4204 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4205 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4207 r = -1;
4208 }
4209 }
4210
4211 if (r >= 0) {
4212 if (r == (ssize_t)data_len)
4213 coap_log_debug("* %s: tls: sent %4d bytes\n",
4214 coap_session_str(session), r);
4215 else
4216 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
4217 coap_session_str(session), r, data_len);
4218 }
4219 return r;
4220}
4221
4222/*
4223 * strm
4224 * return >=0 Number of bytes read.
4225 * -1 Error (error in errno).
4226 */
4227ssize_t
4228coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4229 SSL *ssl = (SSL *)session->tls;
4230 int r, in_init;
4231
4232 if (ssl == NULL) {
4233 errno = ENXIO;
4234 return -1;
4235 }
4236
4237 in_init = !SSL_is_init_finished(ssl);
4238 session->dtls_event = -1;
4239 ERR_clear_error();
4240 r = SSL_read(ssl, data, (int)data_len);
4241 if (r <= 0) {
4242 int err = SSL_get_error(ssl, r);
4243 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4244 if (in_init && SSL_is_init_finished(ssl)) {
4245 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4246 coap_session_str(session), SSL_get_cipher_name(ssl));
4248 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4249 }
4250 if (err == SSL_ERROR_WANT_READ)
4251 session->sock.flags |= COAP_SOCKET_WANT_READ;
4252 if (err == SSL_ERROR_WANT_WRITE) {
4253 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4254#ifdef COAP_EPOLL_SUPPORT
4255 coap_epoll_ctl_mod(&session->sock,
4256 EPOLLOUT |
4257 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4258 EPOLLIN : 0),
4259 __func__);
4260#endif /* COAP_EPOLL_SUPPORT */
4261 }
4262 r = 0;
4263 } else {
4264 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4266 else if (err == SSL_ERROR_SSL) {
4267 unsigned long e = ERR_get_error();
4268
4269 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4270 coap_session_str(session),
4271 ERR_GET_REASON(e), ERR_reason_error_string(e));
4273 } else {
4274 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4275 coap_session_str(session), err);
4276 }
4277 r = -1;
4278 }
4279 } else if (in_init && SSL_is_init_finished(ssl)) {
4280 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4281 coap_session_str(session), SSL_get_cipher_name(ssl));
4283 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4284 }
4285
4286 if (session->dtls_event >= 0) {
4287 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4288 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4289 coap_handle_event_lkd(session->context, session->dtls_event, session);
4290 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4291 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4293 r = -1;
4294 }
4295 }
4296
4297 if (r > 0) {
4298 coap_log_debug("* %s: tls: recv %4d bytes\n",
4299 coap_session_str(session), r);
4300 }
4301 return r;
4302}
4303#endif /* !COAP_DISABLE_TCP */
4304
4305#if COAP_SERVER_SUPPORT
4306coap_digest_ctx_t *
4307coap_digest_setup(void) {
4308 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4309
4310 if (digest_ctx) {
4311 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4312 }
4313 return digest_ctx;
4314}
4315
4316void
4317coap_digest_free(coap_digest_ctx_t *digest_ctx) {
4318 if (digest_ctx)
4319 EVP_MD_CTX_free(digest_ctx);
4320}
4321
4322int
4323coap_digest_update(coap_digest_ctx_t *digest_ctx,
4324 const uint8_t *data,
4325 size_t data_len) {
4326 return EVP_DigestUpdate(digest_ctx, data, data_len);
4327}
4328
4329int
4330coap_digest_final(coap_digest_ctx_t *digest_ctx,
4331 coap_digest_t *digest_buffer) {
4332 unsigned int size = sizeof(coap_digest_t);
4333 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4334
4335 coap_digest_free(digest_ctx);
4336 return ret;
4337}
4338#endif /* COAP_SERVER_SUPPORT */
4339
4340#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4341static void
4342coap_crypto_output_errors(const char *prefix) {
4343#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4344 (void)prefix;
4345#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4346 unsigned long e;
4347
4348 while ((e = ERR_get_error()))
4349 coap_log_warn("%s: %s%s\n",
4350 prefix,
4351 ERR_reason_error_string(e),
4352 ssl_function_definition(e));
4353#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4354}
4355#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4356
4357#if COAP_WS_SUPPORT
4358/*
4359 * The struct hash_algs and the function get_hash_alg() are used to
4360 * determine which hash type to use for creating the required hash object.
4361 */
4362static struct hash_algs {
4363 cose_alg_t alg;
4364 const EVP_MD *(*get_hash)(void);
4365 size_t length; /* in bytes */
4366} hashs[] = {
4367 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4368 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4369 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4370 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4371};
4372
4373static const EVP_MD *
4374get_hash_alg(cose_alg_t alg, size_t *length) {
4375 size_t idx;
4376
4377 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
4378 if (hashs[idx].alg == alg) {
4379 *length = hashs[idx].length;
4380 return hashs[idx].get_hash();
4381 }
4382 }
4383 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4384 return NULL;
4385}
4386
4387int
4389 const coap_bin_const_t *data,
4390 coap_bin_const_t **hash) {
4391 unsigned int length;
4392 const EVP_MD *evp_md;
4393 EVP_MD_CTX *evp_ctx = NULL;
4395 size_t hash_length;
4396
4397 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4398 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4399 return 0;
4400 }
4401 evp_ctx = EVP_MD_CTX_new();
4402 if (evp_ctx == NULL)
4403 goto error;
4404 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4405 goto error;
4406 ;
4407 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4408 goto error;
4409 ;
4410 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4411 if (dummy == NULL)
4412 goto error;
4413 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4414 goto error;
4415 dummy->length = length;
4416 if (hash_length < dummy->length)
4417 dummy->length = hash_length;
4418 *hash = (coap_bin_const_t *)(dummy);
4419 EVP_MD_CTX_free(evp_ctx);
4420 return 1;
4421
4422error:
4423 coap_crypto_output_errors("coap_crypto_hash");
4425 if (evp_ctx)
4426 EVP_MD_CTX_free(evp_ctx);
4427 return 0;
4428}
4429#endif /* COAP_WS_SUPPORT */
4430
4431#if COAP_OSCORE_SUPPORT
4432int
4434 return 1;
4435}
4436
4437#include <openssl/evp.h>
4438#include <openssl/hmac.h>
4439
4440/*
4441 * The struct cipher_algs and the function get_cipher_alg() are used to
4442 * determine which cipher type to use for creating the required cipher
4443 * suite object.
4444 */
4445static struct cipher_algs {
4446 cose_alg_t alg;
4447 const EVP_CIPHER *(*get_cipher)(void);
4448} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4449 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4450};
4451
4452static const EVP_CIPHER *
4453get_cipher_alg(cose_alg_t alg) {
4454 size_t idx;
4455
4456 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4457 if (ciphers[idx].alg == alg)
4458 return ciphers[idx].get_cipher();
4459 }
4460 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4461 return NULL;
4462}
4463
4464/*
4465 * The struct hmac_algs and the function get_hmac_alg() are used to
4466 * determine which hmac type to use for creating the required hmac
4467 * suite object.
4468 */
4469static struct hmac_algs {
4470 cose_hmac_alg_t hmac_alg;
4471 const EVP_MD *(*get_hmac)(void);
4472} hmacs[] = {
4473 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4474 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4475 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4476};
4477
4478static const EVP_MD *
4479get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4480 size_t idx;
4481
4482 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4483 if (hmacs[idx].hmac_alg == hmac_alg)
4484 return hmacs[idx].get_hmac();
4485 }
4486 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4487 return NULL;
4488}
4489
4490int
4492 return get_cipher_alg(alg) != NULL;
4493}
4494
4495int
4497 cose_hmac_alg_t hmac_alg;
4498
4499 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4500 return 0;
4501 return get_hmac_alg(hmac_alg) != NULL;
4502}
4503
4504#define C(Func) \
4505 if (1 != (Func)) { \
4506 goto error; \
4507 }
4508
4509int
4511 coap_bin_const_t *data,
4512 coap_bin_const_t *aad,
4513 uint8_t *result,
4514 size_t *max_result_len) {
4515 const EVP_CIPHER *cipher;
4516 const coap_crypto_aes_ccm_t *ccm;
4517 int tmp;
4518 int result_len = (int)(*max_result_len & INT_MAX);
4519 EVP_CIPHER_CTX *ctx;
4520
4521 if (data == NULL)
4522 return 0;
4523
4524 assert(params != NULL);
4525 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4526 return 0;
4527 }
4528
4529 /* TODO: set evp_md depending on params->alg */
4530 ccm = &params->params.aes;
4531
4532 ctx = EVP_CIPHER_CTX_new();
4533 if (!ctx)
4534 return 0;
4535
4536 /* EVP_CIPHER_CTX_init(ctx); */
4537 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4538 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4539 C(EVP_CIPHER_CTX_ctrl(ctx,
4540 EVP_CTRL_AEAD_SET_IVLEN,
4541 (int)(15 - ccm->l),
4542 NULL));
4543 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4544 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4545 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4546
4547 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4548 if (aad && aad->s && (aad->length > 0)) {
4549 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4550 }
4551 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4552 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4553 tmp = result_len;
4554 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4555 result_len += tmp;
4556
4557 /* retrieve the tag */
4558 C(EVP_CIPHER_CTX_ctrl(ctx,
4559 EVP_CTRL_CCM_GET_TAG,
4560 (int)ccm->tag_len,
4561 result + result_len));
4562
4563 *max_result_len = result_len + ccm->tag_len;
4564 EVP_CIPHER_CTX_free(ctx);
4565 return 1;
4566
4567error:
4568 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4569 return 0;
4570}
4571
4572int
4574 coap_bin_const_t *data,
4575 coap_bin_const_t *aad,
4576 uint8_t *result,
4577 size_t *max_result_len) {
4578 const EVP_CIPHER *cipher;
4579 const coap_crypto_aes_ccm_t *ccm;
4580 int tmp;
4581 int len;
4582 const uint8_t *tag;
4583 uint8_t *rwtag;
4584 EVP_CIPHER_CTX *ctx;
4585
4586 if (data == NULL)
4587 return 0;
4588
4589 assert(params != NULL);
4590 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4591 return 0;
4592 }
4593
4594 ccm = &params->params.aes;
4595
4596 if (data->length < ccm->tag_len) {
4597 return 0;
4598 } else {
4599 tag = data->s + data->length - ccm->tag_len;
4600 data->length -= ccm->tag_len;
4601 /* Kludge to stop compiler warning */
4602 memcpy(&rwtag, &tag, sizeof(rwtag));
4603 }
4604
4605 ctx = EVP_CIPHER_CTX_new();
4606 if (!ctx)
4607 return 0;
4608
4609 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4610 C(EVP_CIPHER_CTX_ctrl(ctx,
4611 EVP_CTRL_AEAD_SET_IVLEN,
4612 (int)(15 - ccm->l),
4613 NULL));
4614 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4615 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4616 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4617 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4618
4619 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4620 if (aad && aad->s && (aad->length > 0)) {
4621 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4622 }
4623 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4624 EVP_CIPHER_CTX_free(ctx);
4625 if (tmp <= 0) {
4626 *max_result_len = 0;
4627 return 0;
4628 }
4629 *max_result_len = len;
4630 return 1;
4631
4632error:
4633 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4634 return 0;
4635}
4636
4637int
4639 coap_bin_const_t *key,
4640 coap_bin_const_t *data,
4641 coap_bin_const_t **hmac) {
4642 unsigned int result_len;
4643 const EVP_MD *evp_md;
4645
4646 assert(key);
4647 assert(data);
4648 assert(hmac);
4649
4650 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4651 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4652 return 0;
4653 }
4654 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4655 if (dummy == NULL)
4656 return 0;
4657 result_len = (unsigned int)dummy->length;
4658 if (HMAC(evp_md,
4659 key->s,
4660 (int)key->length,
4661 data->s,
4662 (int)data->length,
4663 dummy->s,
4664 &result_len)) {
4665 dummy->length = result_len;
4666 *hmac = (coap_bin_const_t *)dummy;
4667 return 1;
4668 }
4669
4671 coap_crypto_output_errors("coap_crypto_hmac");
4672 return 0;
4673}
4674
4675#endif /* COAP_OSCORE_SUPPORT */
4676
4677#else /* ! COAP_WITH_LIBOPENSSL */
4678
4679#ifdef __clang__
4680/* Make compilers happy that do not like empty modules. As this function is
4681 * never used, we ignore -Wunused-function at the end of compiling this file
4682 */
4683#pragma GCC diagnostic ignored "-Wunused-function"
4684#endif
4685static inline void
4686dummy(void) {
4687}
4688
4689#endif /* ! COAP_WITH_LIBOPENSSL */
#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.
@ COAP_STRING
Definition coap_mem.h:33
void * coap_malloc_type(coap_memory_tag_t type, size_t size)
Allocates a chunk of size bytes and returns a pointer to the newly allocated memory.
void coap_free_type(coap_memory_tag_t type, void *p)
Releases the memory that was allocated by coap_malloc_type().
int coap_dtls_context_set_pki(coap_context_t *ctx COAP_UNUSED, const coap_dtls_pki_t *setup_data COAP_UNUSED, const coap_dtls_role_t role COAP_UNUSED)
Definition coap_notls.c:108
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:229
ssize_t coap_tls_read(coap_session_t *session COAP_UNUSED, uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:301
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:224
int coap_dtls_receive(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:243
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:158
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:261
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:124
static coap_log_t dtls_log_level
Definition coap_notls.c:151
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:147
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:212
ssize_t coap_tls_write(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:289
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:208
int coap_dtls_context_set_pki_root_cas(coap_context_t *ctx COAP_UNUSED, const char *ca_file COAP_UNUSED, const char *ca_path COAP_UNUSED)
Definition coap_notls.c:116
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:238
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:186
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:204
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:181
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:280
static void dummy(void)
#define NULL
Definition coap_option.h:30
coap_tick_t coap_ticks_from_rt_us(uint64_t t)
Helper function that converts POSIX wallclock time in us to coap ticks.
Definition coap_time.c:133
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:149
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition coap_prng.c:190
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:5023
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:2946
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:154
#define COAP_DTLS_RETRANSMIT_MS
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
Definition coap_dtls.c:165
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every)
Set the Connection ID client tuple frequency change for testing CIDs.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition coap_notls.c:219
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition coap_notls.c:166
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void coap_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
int coap_tls_engine_configure(coap_str_const_t *conf_mem)
Configure an ENGINE for a TLS library.
Definition coap_notls.c:22
coap_tls_version_t * coap_get_tls_library_version(void)
Determine the type and version of the underlying (D)TLS library.
Definition coap_notls.c:100
coap_dtls_role_t
Definition coap_dtls.h:48
int coap_tls_engine_remove(void)
Remove a previously configured ENGINE from a TLS library.
Definition coap_notls.c:28
coap_tls_library_t
Definition coap_dtls.h:74
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:249
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:246
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:240
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:238
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:255
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:242
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:244
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:252
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition coap_dtls.h:50
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition coap_dtls.h:49
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:176
@ COAP_ASN1_PKEY_DH
DH type.
Definition coap_dtls.h:159
@ COAP_ASN1_PKEY_NONE
NONE.
Definition coap_dtls.h:151
@ COAP_ASN1_PKEY_TLS1_PRF
TLS1_PRF type.
Definition coap_dtls.h:164
@ COAP_ASN1_PKEY_RSA2
RSA2 type.
Definition coap_dtls.h:153
@ COAP_ASN1_PKEY_DSA
DSA type.
Definition coap_dtls.h:154
@ COAP_ASN1_PKEY_DHX
DHX type.
Definition coap_dtls.h:160
@ COAP_ASN1_PKEY_DSA4
DSA4 type.
Definition coap_dtls.h:158
@ COAP_ASN1_PKEY_DSA2
DSA2 type.
Definition coap_dtls.h:156
@ COAP_ASN1_PKEY_RSA
RSA type.
Definition coap_dtls.h:152
@ COAP_ASN1_PKEY_DSA1
DSA1 type.
Definition coap_dtls.h:155
@ COAP_ASN1_PKEY_HKDF
HKDF type.
Definition coap_dtls.h:165
@ COAP_ASN1_PKEY_EC
EC type.
Definition coap_dtls.h:161
@ COAP_ASN1_PKEY_DSA3
DSA3 type.
Definition coap_dtls.h:157
@ COAP_ASN1_PKEY_HMAC
HMAC type.
Definition coap_dtls.h:162
@ COAP_ASN1_PKEY_CMAC
CMAC type.
Definition coap_dtls.h:163
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition coap_dtls.h:77
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
Definition coap_event.h:45
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:47
#define coap_lock_callback_ret(r, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:126
coap_log_t
Logging type.
Definition coap_debug.h:56
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:176
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:306
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:171
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:114
#define coap_log_warn(...)
Definition coap_debug.h:108
#define coap_log_err(...)
Definition coap_debug.h:102
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:290
@ COAP_LOG_INFO
Definition coap_debug.h:63
@ COAP_LOG_EMERG
Definition coap_debug.h:57
@ COAP_LOG_DEBUG
Definition coap_debug.h:64
@ COAP_LOG_WARN
Definition coap_debug.h:61
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_64
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_SHA_1
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_SHA_512
@ COSE_ALGORITHM_AES_CCM_16_64_256
#define COAP_DEFAULT_MTU
Definition coap_pdu.h:43
@ COAP_PROTO_DTLS
Definition coap_pdu.h:319
@ COAP_PROTO_TLS
Definition coap_pdu.h:321
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_CSM
void coap_delete_str_const(coap_str_const_t *s)
Deletes the given const string and releases any memory allocated.
Definition coap_str.c:65
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
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
coap_str_const_t * coap_new_str_const(const uint8_t *data, size_t size)
Returns a new const string object with at least size+1 bytes storage allocated, and the provided data...
Definition coap_str.c:55
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
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::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith to use.
The structure that holds the Client PSK information.
Definition coap_dtls.h:383
coap_bin_const_t key
Definition coap_dtls.h:385
coap_bin_const_t identity
Definition coap_dtls.h:384
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:414
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
Definition coap_dtls.h:421
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:438
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:441
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:437
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:419
The structure that holds the PKI key information.
Definition coap_dtls.h:283
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:290
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:284
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:316
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:330
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:355
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:327
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:337
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:329
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:362
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:328
coap_dtls_security_setup_t additional_tls_setup_call_back
Additional Security callback handler that is invoked when libcoap has done the standard,...
Definition coap_dtls.h:370
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:326
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:321
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:372
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:324
void * sni_call_back_arg
Passed in to the sni callback function.
Definition coap_dtls.h:363
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:354
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:331
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:334
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
Definition coap_dtls.h:322
coap_dtls_key_t pki_key
PKI key definition.
Definition coap_dtls.h:377
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:454
coap_bin_const_t hint
Definition coap_dtls.h:455
coap_bin_const_t key
Definition coap_dtls.h:456
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:505
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:534
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:526
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:527
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:510
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:535
coap_dtls_spsk_info_t psk_info
Server PSK definition.
Definition coap_dtls.h:537
coap_layer_read_t l_read
coap_layer_write_t l_write
coap_layer_establish_t l_establish
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:265
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
Definition coap_dtls.h:273
const char * user_pin
define: User pin to access type PKCS11.
Definition coap_dtls.h:275
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:266
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:264
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:268
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:267
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:272
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:269
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:270
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:271
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
coap_bin_const_t * psk_key
If client, this field contains the current pre-shared key for server; When this field is NULL,...
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
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_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:87
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:90
coap_tls_library_t type
Library type.
Definition coap_dtls.h:89
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:88
const char * s_byte
signed char ptr
Definition coap_str.h:84
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:85