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