libcoap 4.3.5-develop-9b40890
Loading...
Searching...
No Matches
coap_openssl.c
Go to the documentation of this file.
1/*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018-2026 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * This file is part of the CoAP library libcoap. Please see README for terms
10 * of use.
11 */
12
19
20#if COAP_WITH_LIBOPENSSL
21
22/*
23 * OpenSSL 1.1.0 has support for making decisions during receipt of
24 * the Client Hello - the call back function is set up using
25 * SSL_CTX_set_tlsext_servername_callback() which is called later in the
26 * Client Hello processing - but called every Client Hello.
27 * Certificates and Preshared Keys have to be set up in the SSL CTX before
28 * SSL_accept() is called, making the code messy to decide whether this is a
29 * PKI or PSK incoming request to handle things accordingly if both are
30 * defined. SNI has to create a new SSL CTX to handle different server names
31 * with different crtificates.
32 *
33 * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
34 * The call back is invoked early on in the Client Hello processing giving
35 * the ability to easily use different Preshared Keys, Certificates etc.
36 * Certificates do not have to be set up in the SSL CTX before SSL_accept is
37 * called.
38 * Later in the Client Hello code, the callback for
39 * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
40 * is being used by the client, so cannot be used for doing things the
41 * OpenSSL 1.1.0 way.
42 *
43 * OpenSSL 1.1.1 supports TLS1.3.
44 *
45 * There is also support for OpenSSL 3.
46 *
47 * Consequently, this code has to have compile time options to include /
48 * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
49 * have additional run time checks.
50 *
51 * It is possible to override the Ciphers, define the Algorithms or Groups,
52 * and/or define the PKCS11 engine id to to use for the SSL negotiations at
53 * compile time. This is done by the adding of the appropriate -D option to
54 * the CPPFLAGS parameter that is used on the ./configure command line.
55 * E.g. ./configure CPPFLAGS="-DXX='\"YY\"' -DUU='\"VV\"'"
56 * The parameter value is case-sensitive.
57 *
58 * The ciphers can be overridden with (example)
59 * -DCOAP_OPENSSL_CIPHERS='\"ECDHE-ECDSA-AES256-GCM-SHA384\"'
60 *
61 * The Algorithms can be defined by (example)
62 * -DCOAP_OPENSSL_SIGALGS='\"ed25519\"'
63 *
64 * The Groups (OpenSSL 1.1.1 or later) can be defined by (example)
65 * -DCOAP_OPENSSL_GROUPS='\"X25519\"'
66 *
67 * The PKCSLL engine ID can be defined by (example)
68 + -DCOAP_OPENSSL_PKCS11_ENGINE_ID='\"pkcs11\"'
69 *
70 */
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 return -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 (!context->dtls.cookie_hmac)
1147 goto error;
1148 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1149 EVP_sha256(), NULL))
1150 goto error;
1151 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1152 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1153 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1154 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1155#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1156 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1157#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1158 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1159 if (!context->dtls.meth)
1160 goto error;
1161 context->dtls.bio_addr = BIO_ADDR_new();
1162 if (!context->dtls.bio_addr)
1163 goto error;
1164 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1165 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1166 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1167 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1168 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1169 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1170
1171#if !COAP_DISABLE_TCP
1172 /* Set up TLS context */
1173 context->tls.ctx = SSL_CTX_new(TLS_method());
1174 if (!context->tls.ctx)
1175 goto error;
1176 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1177 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1178 coap_set_user_prefs(context->tls.ctx);
1179 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1180 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1181 if (!context->tls.meth)
1182 goto error;
1183 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1184 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1185 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1186 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1187 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1188 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1189#endif /* !COAP_DISABLE_TCP */
1190 }
1191
1192 return context;
1193
1194error:
1195 coap_dtls_free_context(context);
1196 return NULL;
1197}
1198
1199#if COAP_SERVER_SUPPORT
1200int
1202 coap_dtls_spsk_t *setup_data
1203 ) {
1204 coap_openssl_context_t *o_context =
1205 ((coap_openssl_context_t *)c_context->dtls_context);
1206 BIO *bio;
1207
1208 if (!setup_data || !o_context)
1209 return 0;
1210
1211 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1212 coap_dtls_psk_server_callback);
1213#if !COAP_DISABLE_TCP
1214 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1215 coap_dtls_psk_server_callback);
1216#endif /* !COAP_DISABLE_TCP */
1217 if (setup_data->psk_info.hint.s) {
1218 char hint[COAP_DTLS_HINT_LENGTH];
1219 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1220 setup_data->psk_info.hint.s);
1221 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1222#if !COAP_DISABLE_TCP
1223 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1224#endif /* !COAP_DISABLE_TCP */
1225 }
1226 if (setup_data->validate_sni_call_back) {
1227#if OPENSSL_VERSION_NUMBER < 0x10101000L
1228 SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1229 &c_context->spsk_setup_data);
1230 SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1231 psk_tls_server_name_call_back);
1232#if !COAP_DISABLE_TCP
1233 SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1234 &c_context->spsk_setup_data);
1235 SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1236 psk_tls_server_name_call_back);
1237#endif /* !COAP_DISABLE_TCP */
1238#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1239 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1240 psk_tls_client_hello_call_back,
1241 NULL);
1242#if !COAP_DISABLE_TCP
1243 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1244 psk_tls_client_hello_call_back,
1245 NULL);
1246#endif /* !COAP_DISABLE_TCP */
1247#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1248 }
1249
1250 if (!o_context->dtls.ssl) {
1251 /* This is set up to handle new incoming sessions to a server */
1252 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1253 if (!o_context->dtls.ssl)
1254 return 0;
1255 bio = BIO_new(o_context->dtls.meth);
1256 if (!bio) {
1257 SSL_free(o_context->dtls.ssl);
1258 o_context->dtls.ssl = NULL;
1259 return 0;
1260 }
1261 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1262 SSL_set_app_data(o_context->dtls.ssl, NULL);
1263 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1264 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1265 }
1266 if (setup_data->ec_jpake) {
1267 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1268 }
1269 o_context->psk_pki_enabled |= IS_PSK;
1270 return 1;
1271}
1272#endif /* COAP_SERVER_SUPPORT */
1273
1274#if COAP_CLIENT_SUPPORT
1275int
1277 coap_dtls_cpsk_t *setup_data
1278 ) {
1279 coap_openssl_context_t *o_context =
1280 ((coap_openssl_context_t *)c_context->dtls_context);
1281 BIO *bio;
1282
1283 if (!setup_data || !o_context)
1284 return 0;
1285
1286 if (!o_context->dtls.ssl) {
1287 /* This is set up to handle new incoming sessions to a server */
1288 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1289 if (!o_context->dtls.ssl)
1290 return 0;
1291 bio = BIO_new(o_context->dtls.meth);
1292 if (!bio) {
1293 SSL_free(o_context->dtls.ssl);
1294 o_context->dtls.ssl = NULL;
1295 return 0;
1296 }
1297 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1298 SSL_set_app_data(o_context->dtls.ssl, NULL);
1299 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1300 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1301 }
1302 if (setup_data->ec_jpake) {
1303 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1304 }
1305 if (setup_data->use_cid) {
1306 coap_log_warn("OpenSSL has no Connection-ID support\n");
1307 }
1308 o_context->psk_pki_enabled |= IS_PSK;
1309 return 1;
1310}
1311#endif /* COAP_CLIENT_SUPPORT */
1312
1313static int
1314map_key_type(int asn1_private_key_type
1315 ) {
1316 switch (asn1_private_key_type) {
1318 return EVP_PKEY_NONE;
1319 case COAP_ASN1_PKEY_RSA:
1320 return EVP_PKEY_RSA;
1322 return EVP_PKEY_RSA2;
1323 case COAP_ASN1_PKEY_DSA:
1324 return EVP_PKEY_DSA;
1326 return EVP_PKEY_DSA1;
1328 return EVP_PKEY_DSA2;
1330 return EVP_PKEY_DSA3;
1332 return EVP_PKEY_DSA4;
1333 case COAP_ASN1_PKEY_DH:
1334 return EVP_PKEY_DH;
1335 case COAP_ASN1_PKEY_DHX:
1336 return EVP_PKEY_DHX;
1337 case COAP_ASN1_PKEY_EC:
1338 return EVP_PKEY_EC;
1340 return EVP_PKEY_HMAC;
1342 return EVP_PKEY_CMAC;
1344 return EVP_PKEY_TLS1_PRF;
1346 return EVP_PKEY_HKDF;
1347 default:
1348 coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1349 asn1_private_key_type);
1350 break;
1351 }
1352 return 0;
1353}
1354#if !COAP_DISABLE_TCP
1355static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1356
1357#if COAP_SERVER_SUPPORT
1358static int
1359server_alpn_callback(SSL *ssl COAP_UNUSED,
1360 const unsigned char **out,
1361 unsigned char *outlen,
1362 const unsigned char *in,
1363 unsigned int inlen,
1364 void *arg COAP_UNUSED
1365 ) {
1366 unsigned char *tout = NULL;
1367 int ret;
1368 if (inlen == 0)
1369 return SSL_TLSEXT_ERR_NOACK;
1370 ret = SSL_select_next_proto(&tout,
1371 outlen,
1372 coap_alpn,
1373 sizeof(coap_alpn),
1374 in,
1375 inlen);
1376 *out = tout;
1377 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1378}
1379#endif /* COAP_SERVER_SUPPORT */
1380#endif /* !COAP_DISABLE_TCP */
1381
1382static void
1383add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1384 long e;
1385
1386 /* Flush out existing errors */
1387 while (ERR_get_error() != 0) {
1388 }
1389
1390 if (!X509_STORE_add_cert(st, x509)) {
1391 while ((e = ERR_get_error()) != 0) {
1392 int r = ERR_GET_REASON(e);
1393 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1394 /* Not already added */
1395 coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1396 ERR_reason_error_string(e),
1397 ssl_function_definition(e));
1398 }
1399 }
1400 }
1401}
1402
1403static X509 *
1404missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1405 struct {
1406 const char *cert_id;
1407 X509 *cert;
1408 } params;
1409
1410 params.cert_id = cert_id;
1411 params.cert = NULL;
1412
1413 /* There is no ENGINE_load_cert() */
1414 if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1415 params.cert = NULL;
1416 }
1417 return params.cert;
1418}
1419
1420static int
1421check_pkcs11_engine(void) {
1422 static int already_tried = 0;
1423
1424 if (already_tried)
1425 return 0;
1426
1427 if (!pkcs11_engine) {
1428 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1429 if (!pkcs11_engine) {
1430 coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1431 COAP_OPENSSL_PKCS11_ENGINE_ID);
1432 already_tried = 1;
1433 return 0;
1434 }
1435 if (!ENGINE_init(pkcs11_engine)) {
1436 /* the engine couldn't initialise, release 'pkcs11_engine' */
1437 ENGINE_free(pkcs11_engine);
1438 pkcs11_engine = NULL;
1439 coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1440 already_tried = 1;
1441 return 0;
1442 }
1443 /*
1444 * ENGINE_init() returned a functional reference, so free the structural
1445 * reference from ENGINE_by_id().
1446 */
1447 ENGINE_free(pkcs11_engine);
1448 }
1449 return 1;
1450}
1451
1452#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1453
1454static int
1455install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1456 const char *public_cert) {
1457 X509 *x509;
1458
1459 x509 = missing_ENGINE_load_cert(engine, public_cert);
1460 if (!x509) {
1461 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1462 "%s Certificate\n",
1463 public_cert,
1464 "Server");
1465 return 0;
1466 }
1467 if (!SSL_CTX_use_certificate(ctx, x509)) {
1468 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1469 "%s Certificate\n",
1470 public_cert,
1471 "Server");
1472 X509_free(x509);
1473 return 0;
1474 }
1475 X509_free(x509);
1476 return 1;
1477}
1478
1479static int
1480install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1481 const char *private_key) {
1482 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1483 private_key,
1484 NULL, NULL);
1485
1486 if (!pkey) {
1487 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1488 "%s Private Key\n",
1489 private_key,
1490 "Server");
1491 return 0;
1492 }
1493 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1494 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1495 "%s Private Key\n",
1496 private_key,
1497 "Server");
1498 EVP_PKEY_free(pkey);
1499 return 0;
1500 }
1501 EVP_PKEY_free(pkey);
1502 return 1;
1503}
1504
1505static int
1506install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1507 X509 *x509;
1508 X509_STORE *st;
1509
1510 x509 = missing_ENGINE_load_cert(engine,
1511 ca);
1512 if (!x509) {
1513 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1514 "%s CA Certificate\n",
1515 ca,
1516 "Server");
1517 return 0;
1518 }
1519 if (!SSL_CTX_add_client_CA(ctx, x509)) {
1520 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1521 "%s CA Certificate\n",
1522 ca,
1523 "Server");
1524 X509_free(x509);
1525 return 0;
1526 }
1527 st = SSL_CTX_get_cert_store(ctx);
1528 add_ca_to_cert_store(st, x509);
1529 X509_free(x509);
1530 return 1;
1531}
1532
1533static int
1534load_in_cas_ctx(SSL_CTX *ctx,
1535 const char *ca_file) {
1536 STACK_OF(X509_NAME) *cert_names;
1537 X509_STORE *st;
1538 BIO *in;
1539 X509 *x = NULL;
1540 char *rw_var = NULL;
1541 cert_names = SSL_load_client_CA_file(ca_file);
1542 if (cert_names != NULL)
1543 SSL_CTX_set_client_CA_list(ctx, cert_names);
1544 else {
1545 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1546 "client CA File\n",
1547 ca_file);
1548 return 0;
1549 }
1550
1551 /* Add CA to the trusted root CA store */
1552 st = SSL_CTX_get_cert_store(ctx);
1553 in = BIO_new(BIO_s_file());
1554 if (!in)
1555 return 0;
1556 /* Need to do this to not get a compiler warning about const parameters */
1557 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1558 if (!BIO_read_filename(in, rw_var)) {
1559 BIO_free(in);
1560 return 0;
1561 }
1562
1563 for (;;) {
1564 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1565 break;
1566 add_ca_to_cert_store(st, x);
1567 X509_free(x);
1568 }
1569 BIO_free(in);
1570 return 1;
1571}
1572
1573static int
1574setup_pki_server(SSL_CTX *ctx,
1575 const coap_dtls_pki_t *setup_data) {
1576 coap_dtls_key_t key;
1577
1578 /* Map over to the new define format to save code duplication */
1579 coap_dtls_map_key_type_to_define(setup_data, &key);
1580
1581 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1582
1583 /*
1584 * Configure the Private Key
1585 */
1586 if (key.key.define.private_key.u_byte &&
1587 key.key.define.private_key.u_byte[0]) {
1588 switch (key.key.define.private_key_def) {
1589 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1590 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1592 SSL_FILETYPE_PEM))) {
1595 &key, COAP_DTLS_ROLE_SERVER, 0);
1596 }
1597 break;
1598 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1599 if (key.key.define.private_key_len) {
1600 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1601 (int)key.key.define.private_key_len);
1602 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1603
1604 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1605 if (bp)
1606 BIO_free(bp);
1607 if (pkey)
1608 EVP_PKEY_free(pkey);
1611 &key, COAP_DTLS_ROLE_SERVER, 0);
1612 }
1613 if (bp)
1614 BIO_free(bp);
1615 if (pkey)
1616 EVP_PKEY_free(pkey);
1617 } else {
1620 &key, COAP_DTLS_ROLE_SERVER, 0);
1621 }
1622 break;
1623 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1626 &key, COAP_DTLS_ROLE_SERVER, 0);
1627 case COAP_PKI_KEY_DEF_DER: /* define private key */
1628 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1630 SSL_FILETYPE_ASN1))) {
1633 &key, COAP_DTLS_ROLE_SERVER, 0);
1634 }
1635 break;
1636 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1637 if (key.key.define.private_key_len == 0 ||
1638 !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1639 ctx,
1641 (long)key.key.define.private_key_len))) {
1644 &key, COAP_DTLS_ROLE_SERVER, 0);
1645 }
1646 break;
1647 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1648 if (!check_pkcs11_engine()) {
1649 return 0;
1650 }
1651 if (key.key.define.user_pin) {
1652 /* If not set, pin-value may be held in pkcs11: URI */
1653 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1654 "PIN",
1655 key.key.define.user_pin, 0) == 0) {
1656 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1657 key.key.define.user_pin);
1658 return 0;
1659 }
1660 }
1661 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1665 &key, COAP_DTLS_ROLE_SERVER, 0);
1666 }
1667 break;
1668 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1669 if (!defined_engine ||
1670 !install_engine_private_key_ctx(defined_engine, ctx,
1674 &key, COAP_DTLS_ROLE_SERVER, 0);
1675 }
1676 break;
1677 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1678 default:
1681 &key, COAP_DTLS_ROLE_SERVER, 0);
1682 }
1683 } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1686 &key, COAP_DTLS_ROLE_SERVER, 0);
1687 }
1688
1689 /*
1690 * Configure the Public Certificate / Key
1691 * OpenSSL < 1.1.1 and Server
1692 */
1693 if (key.key.define.public_cert.u_byte &&
1694 key.key.define.public_cert.u_byte[0]) {
1695 switch (key.key.define.public_cert_def) {
1696 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1697 if (key.key.define.ca.u_byte &&
1698 key.key.define.ca.u_byte[0]) {
1699 if (!(SSL_CTX_use_certificate_file(ctx,
1701 SSL_FILETYPE_PEM))) {
1704 &key, COAP_DTLS_ROLE_SERVER, 0);
1705 }
1706 } else {
1707 if (!SSL_CTX_use_certificate_chain_file(ctx,
1711 &key, COAP_DTLS_ROLE_SERVER, 0);
1712 }
1713 }
1714 break;
1715 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1716 if (key.key.define.public_cert_len) {
1717 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1718 (int)key.key.define.public_cert_len);
1719 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1720
1721 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1722 if (bp)
1723 BIO_free(bp);
1724 if (cert)
1725 X509_free(cert);
1728 &key, COAP_DTLS_ROLE_SERVER, 0);
1729 }
1730 if (bp)
1731 BIO_free(bp);
1732 if (cert)
1733 X509_free(cert);
1734 } else {
1737 &key, COAP_DTLS_ROLE_SERVER, 0);
1738 }
1739 break;
1740 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1743 &key, COAP_DTLS_ROLE_SERVER, 0);
1744 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1745 if (!(SSL_CTX_use_certificate_file(ctx,
1747 SSL_FILETYPE_ASN1))) {
1750 &key, COAP_DTLS_ROLE_SERVER, 0);
1751 }
1752 break;
1753 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1754 if (key.key.define.public_cert_len == 0 ||
1755 !(SSL_CTX_use_certificate_ASN1(ctx,
1756 (int)key.key.define.public_cert_len,
1757 key.key.define.public_cert.u_byte))) {
1760 &key, COAP_DTLS_ROLE_SERVER, 0);
1761 }
1762 break;
1763 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1764 if (!check_pkcs11_engine()) {
1765 return 0;
1766 }
1767 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1771 &key, COAP_DTLS_ROLE_SERVER, 0);
1772 }
1773 break;
1774 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1775 if (!defined_engine ||
1776 !install_engine_public_cert_ctx(defined_engine, ctx,
1780 &key, COAP_DTLS_ROLE_SERVER, 0);
1781 }
1782 break;
1783 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1784 default:
1787 &key, COAP_DTLS_ROLE_SERVER, 0);
1788 }
1789 } else if (key.key.define.private_key.u_byte &&
1790 key.key.define.private_key.u_byte[0]) {
1793 &key, COAP_DTLS_ROLE_SERVER, 0);
1794 }
1795
1796 /*
1797 * Configure the CA
1798 */
1799 if (key.key.define.ca.u_byte &&
1800 key.key.define.ca.u_byte[0]) {
1801 switch (key.key.define.ca_def) {
1803 if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1806 &key, COAP_DTLS_ROLE_SERVER, 0);
1807 }
1808 break;
1809 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1810 if (key.key.define.ca_len) {
1811 BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1812 (int)key.key.define.ca_len);
1813 X509 *x;
1814 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1815
1816 if (bp) {
1817 for (;;) {
1818 if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1819 break;
1820 add_ca_to_cert_store(st, x);
1821 SSL_CTX_add_client_CA(ctx, x);
1822 X509_free(x);
1823 }
1824 BIO_free(bp);
1825 }
1826 } else {
1829 &key, COAP_DTLS_ROLE_SERVER, 0);
1830 }
1831 break;
1832 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1835 &key, COAP_DTLS_ROLE_SERVER, 0);
1836 case COAP_PKI_KEY_DEF_DER: /* define ca */
1837 if (!(SSL_CTX_use_certificate_file(ctx,
1838 key.key.define.ca.s_byte,
1839 SSL_FILETYPE_ASN1))) {
1842 &key, COAP_DTLS_ROLE_SERVER, 0);
1843 }
1844 break;
1845 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1846 if (key.key.define.ca_len > 0) {
1847 /* Need to use a temp variable as it gets incremented*/
1848 const uint8_t *p = key.key.define.ca.u_byte;
1849 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1850 X509_STORE *st;
1851
1852 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1853 X509_free(x509);
1856 &key, COAP_DTLS_ROLE_SERVER, 0);
1857 }
1858
1859 /* Add CA to the trusted root CA store */
1860 st = SSL_CTX_get_cert_store(ctx);
1861 add_ca_to_cert_store(st, x509);
1862 X509_free(x509);
1863 }
1864 break;
1865 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1866 if (!check_pkcs11_engine()) {
1867 return 0;
1868 }
1869 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1870 key.key.define.ca.s_byte)) {
1873 &key, COAP_DTLS_ROLE_SERVER, 0);
1874 }
1875 break;
1876 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1877 if (!defined_engine ||
1878 !install_engine_ca_ctx(defined_engine, ctx,
1879 key.key.define.ca.s_byte)) {
1882 &key, COAP_DTLS_ROLE_SERVER, 0);
1883 }
1884 break;
1885 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1886 default:
1889 &key, COAP_DTLS_ROLE_SERVER, 0);
1890 }
1891 }
1892
1893 return 1;
1894}
1895#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1896
1897#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1898
1899static int
1900install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1901 coap_dtls_role_t role) {
1902 X509 *x509;
1903
1904 x509 = missing_ENGINE_load_cert(engine, public_cert);
1905 if (!x509) {
1906 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1907 "%s Certificate\n",
1908 public_cert,
1909 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1910 return 0;
1911 }
1912 if (!SSL_use_certificate(ssl, x509)) {
1913 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1914 "%s Certificate\n",
1915 public_cert,
1916 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1917 X509_free(x509);
1918 return 0;
1919 }
1920 X509_free(x509);
1921 return 1;
1922}
1923
1924static int
1925install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1926 coap_dtls_role_t role) {
1927 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1928 private_key,
1929 NULL, NULL);
1930
1931 if (!pkey) {
1932 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1933 "%s Private Key\n",
1934 private_key,
1935 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1936 return 0;
1937 }
1938 if (!SSL_use_PrivateKey(ssl, pkey)) {
1939 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1940 "%s Private Key\n",
1941 private_key,
1942 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1943 EVP_PKEY_free(pkey);
1944 return 0;
1945 }
1946 EVP_PKEY_free(pkey);
1947 return 1;
1948}
1949
1950static int
1951install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1952 coap_dtls_role_t role) {
1953 X509 *x509;
1954 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1955 X509_STORE *st;
1956
1957 if (!ctx) {
1958 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1959 "%s CA Certificate (no ctx)\n",
1960 ca,
1961 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1962 return 0;
1963 }
1964 x509 = missing_ENGINE_load_cert(engine,
1965 ca);
1966 if (!x509) {
1967 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1968 "%s CA Certificate\n",
1969 ca,
1970 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1971 return 0;
1972 }
1973 if (!SSL_add_client_CA(ssl, x509)) {
1974 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1975 "%s CA Certificate\n",
1976 ca,
1977 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1978 X509_free(x509);
1979 return 0;
1980 }
1981 st = SSL_CTX_get_cert_store(ctx);
1982 add_ca_to_cert_store(st, x509);
1983 X509_free(x509);
1984 return 1;
1985}
1986
1987static int
1988load_in_cas(SSL *ssl,
1989 const char *ca_file, coap_dtls_role_t role) {
1990 X509_STORE *st;
1991 BIO *in;
1992 X509 *x = NULL;
1993 char *rw_var = NULL;
1994 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1995
1996 if (role == COAP_DTLS_ROLE_SERVER) {
1997 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
1998
1999 if (cert_names != NULL)
2000 SSL_set_client_CA_list(ssl, cert_names);
2001 else {
2002 return 0;
2003 }
2004 }
2005
2006 if (!ctx)
2007 return 0;
2008
2009 /* Add CA to the trusted root CA store */
2010 in = BIO_new(BIO_s_file());
2011 if (!in)
2012 return 0;
2013 /* Need to do this to not get a compiler warning about const parameters */
2014 memcpy(&rw_var, &ca_file, sizeof(rw_var));
2015 if (!BIO_read_filename(in, rw_var)) {
2016 BIO_free(in);
2017 return 0;
2018 }
2019 st = SSL_CTX_get_cert_store(ctx);
2020 for (;;) {
2021 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
2022 break;
2023 add_ca_to_cert_store(st, x);
2024 X509_free(x);
2025 }
2026 BIO_free(in);
2027 return 1;
2028}
2029
2030static int
2031setup_pki_ssl(SSL *ssl,
2032 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
2033 coap_dtls_key_t key;
2034
2035 /* Map over to the new define format to save code duplication */
2036 coap_dtls_map_key_type_to_define(setup_data, &key);
2037
2038 assert(key.key_type == COAP_PKI_KEY_DEFINE);
2039
2040 /*
2041 * Configure the Private Key
2042 */
2043 if (key.key.define.private_key.u_byte &&
2044 key.key.define.private_key.u_byte[0]) {
2045 switch (key.key.define.private_key_def) {
2046 case COAP_PKI_KEY_DEF_PEM: /* define private key */
2047 if (!(SSL_use_PrivateKey_file(ssl,
2049 SSL_FILETYPE_PEM))) {
2052 &key, role, 0);
2053 }
2054 break;
2055 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2056 if (key.key.define.private_key_len) {
2057 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2058 (int)key.key.define.private_key_len);
2059 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2060
2061 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2062 if (bp)
2063 BIO_free(bp);
2064 if (pkey)
2065 EVP_PKEY_free(pkey);
2068 &key, role, 0);
2069 }
2070 if (bp)
2071 BIO_free(bp);
2072 if (pkey)
2073 EVP_PKEY_free(pkey);
2074 } else {
2077 &key, role, 0);
2078 }
2079 break;
2080 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2083 &key, role, 0);
2084 case COAP_PKI_KEY_DEF_DER: /* define private key */
2085 if (!(SSL_use_PrivateKey_file(ssl,
2087 SSL_FILETYPE_ASN1))) {
2090 &key, role, 0);
2091 }
2092 break;
2093 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2094 if (key.key.define.private_key_len == 0 ||
2095 !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2096 ssl,
2098 (long)key.key.define.private_key_len))) {
2101 &key, role, 0);
2102 }
2103 break;
2104 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2105 if (!check_pkcs11_engine()) {
2106 return 0;
2107 }
2108 if (key.key.define.user_pin) {
2109 /* If not set, pin-value may be held in pkcs11: URI */
2110 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2111 "PIN",
2112 key.key.define.user_pin, 0) == 0) {
2113 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2114 key.key.define.user_pin);
2115 return 0;
2116 }
2117 }
2118 if (!install_engine_private_key(pkcs11_engine, ssl,
2120 role)) {
2123 &key, role, 0);
2124 }
2125 break;
2126 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2127 if (!defined_engine ||
2128 !install_engine_private_key(defined_engine, ssl,
2130 role)) {
2133 &key, role, 0);
2134 }
2135 break;
2136 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2137 default:
2140 &key, role, 0);
2141 }
2142 } else if (role == COAP_DTLS_ROLE_SERVER ||
2144 key.key.define.public_cert.u_byte[0])) {
2147 &key, role, 0);
2148 }
2149
2150 /*
2151 * Configure the Public Certificate / Key
2152 */
2153 if (key.key.define.public_cert.u_byte &&
2154 key.key.define.public_cert.u_byte[0]) {
2155 switch (key.key.define.public_cert_def) {
2156 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2157 if (key.key.define.ca.u_byte &&
2158 key.key.define.ca.u_byte[0]) {
2159 /* If CA is separately defined */
2160 if (!(SSL_use_certificate_file(ssl,
2162 SSL_FILETYPE_PEM))) {
2165 &key, role, 0);
2166 }
2167 } else {
2168 if (!SSL_use_certificate_chain_file(ssl,
2172 &key, role, 0);
2173 }
2174 }
2175 break;
2176 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2177 if (key.key.define.public_cert_len) {
2178 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2179 (int)key.key.define.public_cert_len);
2180 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2181
2182 if (!cert || !SSL_use_certificate(ssl, cert)) {
2183 if (bp)
2184 BIO_free(bp);
2185 if (cert)
2186 X509_free(cert);
2189 &key, role, 0);
2190 }
2191 if (bp)
2192 BIO_free(bp);
2193 if (cert)
2194 X509_free(cert);
2195 } else {
2198 &key, role, 0);
2199 }
2200 break;
2201 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2204 &key, role, 0);
2205 case COAP_PKI_KEY_DEF_DER: /* define public cert */
2206 if (!(SSL_use_certificate_file(ssl,
2208 SSL_FILETYPE_ASN1))) {
2211 &key, role, 0);
2212 }
2213 break;
2214 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2215 if (key.key.define.public_cert_len == 0 ||
2216 !(SSL_use_certificate_ASN1(ssl,
2218 (int)key.key.define.public_cert_len))) {
2221 &key, role, 0);
2222 }
2223 break;
2224 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2225 if (!check_pkcs11_engine()) {
2226 return 0;
2227 }
2228 if (!install_engine_public_cert(pkcs11_engine, ssl,
2230 role)) {
2233 &key, role, 0);
2234 }
2235 break;
2236 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2237 if (!defined_engine ||
2238 !install_engine_public_cert(defined_engine, ssl,
2240 role)) {
2243 &key, role, 0);
2244 }
2245 break;
2246 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2247 default:
2250 &key, role, 0);
2251 }
2252 } else if (role == COAP_DTLS_ROLE_SERVER ||
2254 key.key.define.private_key.u_byte[0])) {
2257 &key, role, 0);
2258 }
2259
2260 /*
2261 * Configure the CA
2262 */
2263 if (key.key.define.ca.u_byte &&
2264 key.key.define.ca.u_byte[0]) {
2265 switch (key.key.define.ca_def) {
2267 if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2270 &key, role, 0);
2271 }
2272 break;
2273 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2274 if (key.key.define.ca_len) {
2275 BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2276 (int)key.key.define.ca_len);
2277 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2278 X509 *x;
2279 X509_STORE *st = ctx? SSL_CTX_get_cert_store(ctx) : NULL;
2280
2281 if (bp) {
2282 for (;;) {
2283 if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2284 break;
2285 if (st)
2286 add_ca_to_cert_store(st, x);
2287 SSL_add_client_CA(ssl, x);
2288 X509_free(x);
2289 }
2290 BIO_free(bp);
2291 }
2292 } else {
2295 &key, role, 0);
2296 }
2297 break;
2298 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2301 &key, role, 0);
2302 case COAP_PKI_KEY_DEF_DER: /* define ca */
2303 if (!(SSL_use_certificate_file(ssl,
2304 key.key.define.ca.s_byte,
2305 SSL_FILETYPE_ASN1))) {
2308 &key, role, 0);
2309 }
2310 break;
2311 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2312 if (key.key.define.ca_len > 0) {
2313 /* Need to use a temp variable as it gets incremented*/
2314 const uint8_t *p = key.key.define.ca.u_byte;
2315 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2316 X509_STORE *st;
2317 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2318
2319 if (role == COAP_DTLS_ROLE_SERVER) {
2320 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2321 X509_free(x509);
2324 &key, role, 0);
2325 }
2326 }
2327
2328 /* Add CA to the trusted root CA store */
2329 st = ctx ? SSL_CTX_get_cert_store(ctx) : NULL;
2330 if (st)
2331 add_ca_to_cert_store(st, x509);
2332 X509_free(x509);
2333 }
2334 break;
2335 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2336 if (!check_pkcs11_engine()) {
2337 return 0;
2338 }
2339 if (!install_engine_ca(pkcs11_engine, ssl,
2340 key.key.define.ca.s_byte,
2341 role)) {
2344 &key, role, 0);
2345 }
2346 break;
2347 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2348 if (!defined_engine ||
2349 !install_engine_ca(defined_engine, ssl,
2350 key.key.define.ca.s_byte,
2351 role)) {
2354 &key, role, 0);
2355 }
2356 break;
2357 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2358 default:
2361 &key, role, 0);
2362 }
2363 }
2364
2365 return 1;
2366}
2367#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2368
2369static char *
2370get_san_or_cn_from_cert(X509 *x509) {
2371 if (x509) {
2372 char *cn;
2373 int n;
2374 STACK_OF(GENERAL_NAME) *san_list;
2375 char buffer[256];
2376
2377 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2378 if (san_list) {
2379 int san_count = sk_GENERAL_NAME_num(san_list);
2380
2381 for (n = 0; n < san_count; n++) {
2382 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2383
2384 if (name && name->type == GEN_DNS) {
2385 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2386
2387 /* Make sure that there is not an embedded NUL in the dns_name */
2388 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2389 continue;
2390 cn = OPENSSL_strdup(dns_name);
2391 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2392 return cn;
2393 }
2394 }
2395 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2396 }
2397 /* Otherwise look for the CN= field */
2398 X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2399
2400 /* Need to emulate strcasestr() here. Looking for CN= */
2401 n = (int)strlen(buffer) - 3;
2402 cn = buffer;
2403 while (n > 0) {
2404 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2405 ((cn[1] == 'N') || (cn[1] == 'n')) &&
2406 (cn[2] == '=')) {
2407 cn += 3;
2408 break;
2409 }
2410 cn++;
2411 n--;
2412 }
2413 if (n > 0) {
2414 char *ecn = strchr(cn, '/');
2415 if (ecn) {
2416 return OPENSSL_strndup(cn, ecn-cn);
2417 } else {
2418 return OPENSSL_strdup(cn);
2419 }
2420 }
2421 }
2422 return NULL;
2423}
2424
2425static int
2426tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2427 int index = SSL_get_ex_data_X509_STORE_CTX_idx();
2428 SSL *ssl = index >= 0 ? X509_STORE_CTX_get_ex_data(ctx, index) : NULL;
2429 coap_session_t *session = ssl ? SSL_get_app_data(ssl) : NULL;
2430 coap_openssl_context_t *context = (session && session->context) ?
2431 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2432 coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
2433 int depth = X509_STORE_CTX_get_error_depth(ctx);
2434 int err = X509_STORE_CTX_get_error(ctx);
2435 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2436 char *cn = x509 ? get_san_or_cn_from_cert(x509) : NULL;
2437 int keep_preverify_ok = preverify_ok;
2438
2439 coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2440 depth, err, preverify_ok, cn);
2441 if (!setup_data) {
2442 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2443 OPENSSL_free(cn);
2444 return 0;
2445 }
2446 if (!preverify_ok) {
2447 switch (err) {
2448 case X509_V_ERR_CERT_NOT_YET_VALID:
2449 case X509_V_ERR_CERT_HAS_EXPIRED:
2450 if (setup_data->allow_expired_certs)
2451 preverify_ok = 1;
2452 break;
2453 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2454 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2455 preverify_ok = 1;
2456 break;
2457 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2458 if (!setup_data->verify_peer_cert)
2459 preverify_ok = 1;
2460 break;
2461 case X509_V_ERR_UNABLE_TO_GET_CRL:
2462 if (setup_data->allow_no_crl)
2463 preverify_ok = 1;
2464 break;
2465 case X509_V_ERR_CRL_NOT_YET_VALID:
2466 case X509_V_ERR_CRL_HAS_EXPIRED:
2467 if (setup_data->allow_expired_crl)
2468 preverify_ok = 1;
2469 break;
2470 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2471 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2472 case X509_V_ERR_AKID_SKID_MISMATCH:
2473 if (!setup_data->verify_peer_cert)
2474 preverify_ok = 1;
2475 break;
2476 default:
2477 break;
2478 }
2479 if (setup_data->cert_chain_validation &&
2480 depth > (setup_data->cert_chain_verify_depth + 1)) {
2481 preverify_ok = 0;
2482 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2483 X509_STORE_CTX_set_error(ctx, err);
2484 }
2485 if (!preverify_ok) {
2486 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2487 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2488 coap_session_str(session),
2489 "Unknown CA", cn ? cn : "?", depth);
2490 } else {
2491 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2492 coap_session_str(session),
2493 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2494 }
2495 } else {
2496 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
2497 coap_session_str(session),
2498 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2499 }
2500 }
2501 /* Certificate - depth == 0 is the Client Cert */
2502 if (setup_data->validate_cn_call_back && keep_preverify_ok) {
2503 int length = i2d_X509(x509, NULL);
2504 uint8_t *base_buf;
2505 uint8_t *base_buf2 = base_buf = length > 0 ? OPENSSL_malloc(length) : NULL;
2506 int ret;
2507
2508 if (base_buf) {
2509 /* base_buf2 gets moved to the end */
2510 assert(i2d_X509(x509, &base_buf2) > 0);
2511 (void)base_buf2;
2513 setup_data->validate_cn_call_back(cn, base_buf, length, session,
2514 depth, preverify_ok,
2515 setup_data->cn_call_back_arg));
2516 if (!ret) {
2517 if (depth == 0) {
2518 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2519 } else {
2520 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2521 }
2522 preverify_ok = 0;
2523 }
2524 OPENSSL_free(base_buf);
2525 } else {
2526 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2527 preverify_ok = 0;
2528 }
2529 }
2530 OPENSSL_free(cn);
2531 return preverify_ok;
2532}
2533
2534#if COAP_SERVER_SUPPORT
2535#if OPENSSL_VERSION_NUMBER < 0x10101000L
2536/* OpenSSL < 1.1.1 */
2537/*
2538 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2539 * it is possible to determine whether this is a PKI or PSK incoming
2540 * request and adjust the ciphers if necessary
2541 *
2542 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2543 */
2544static int
2545tls_secret_call_back(SSL *ssl,
2546 void *secret,
2547 int *secretlen,
2548 STACK_OF(SSL_CIPHER) *peer_ciphers,
2549 const SSL_CIPHER **cipher COAP_UNUSED,
2550 void *arg) {
2551 int ii;
2552 int psk_requested = 0;
2553 coap_session_t *session;
2554 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2555
2556 session = (coap_session_t *)SSL_get_app_data(ssl);
2557 assert(session != NULL);
2558 assert(session->context != NULL);
2559 if (session == NULL ||
2560 session->context == NULL)
2561 return 0;
2562
2563 if ((session->psk_key) ||
2564 (session->context->spsk_setup_data.psk_info.key.s &&
2566 /* Is PSK being requested - if so, we need to change algorithms */
2567 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2568 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2569
2570 coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2571 SSL_CIPHER_get_name(peer_cipher));
2572 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2573 psk_requested = 1;
2574 break;
2575 }
2576 }
2577 }
2578 if (!psk_requested) {
2579 coap_log_debug(" %s: Using PKI ciphers\n",
2580 coap_session_str(session));
2581
2582 if (setup_data->verify_peer_cert) {
2583 SSL_set_verify(ssl,
2584 SSL_VERIFY_PEER |
2585 SSL_VERIFY_CLIENT_ONCE |
2586 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2587 tls_verify_call_back);
2588 } else {
2589 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2590 }
2591
2592 /* Check CA Chain */
2593 if (setup_data->cert_chain_validation)
2594 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2595
2596 /* Certificate Revocation */
2597 if (setup_data->check_cert_revocation) {
2598 X509_VERIFY_PARAM *param;
2599
2600 param = X509_VERIFY_PARAM_new();
2601 if (param) {
2602 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2603 SSL_set1_param(ssl, param);
2604 X509_VERIFY_PARAM_free(param);
2605 }
2606 }
2607 if (setup_data->additional_tls_setup_call_back) {
2608 /* Additional application setup wanted */
2609 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2610 return 0;
2611 }
2612 } else {
2613 if (session->psk_key) {
2614 memcpy(secret, session->psk_key->s, session->psk_key->length);
2615 *secretlen = session->psk_key->length;
2616 } else if (session->context->spsk_setup_data.psk_info.key.s &&
2618 memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2620 *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2621 }
2622 coap_log_debug(" %s: Setting PSK ciphers\n",
2623 coap_session_str(session));
2624 /*
2625 * Force a PSK algorithm to be used, so we do PSK
2626 */
2627 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2628 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2629 }
2630 return 0;
2631}
2632
2633/* OpenSSL < 1.1.1 */
2634/*
2635 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2636 * called so it is possible to set up an extra callback to determine whether
2637 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2638 *
2639 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2640 * coap_dtls_context_set_pki()
2641 */
2642static int
2643tls_server_name_call_back(SSL *ssl,
2644 int *sd COAP_UNUSED,
2645 void *arg) {
2646 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2647
2648 if (!ssl) {
2649 return SSL_TLSEXT_ERR_NOACK;
2650 }
2651
2652 if (setup_data->validate_sni_call_back) {
2653 /* SNI checking requested */
2654 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2655 coap_openssl_context_t *context = (session && session->context) ?
2656 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2657 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2658 size_t i;
2659
2660 if !context)
2661 return SSL_TLSEXT_ERR_NOACK;
2662
2663 if (!sni || !sni[0]) {
2664 sni = "";
2665 }
2666 for (i = 0; i < context->sni_count; i++) {
2667 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2668 break;
2669 }
2670 }
2671 if (i == context->sni_count) {
2672 SSL_CTX *ctx;
2673 coap_dtls_pki_t sni_setup_data;
2674 coap_dtls_key_t *new_entry;
2675
2676 coap_lock_callback_ret(new_entry,
2677 setup_data->validate_sni_call_back(sni,
2678 setup_data->sni_call_back_arg));
2679 if (!new_entry) {
2680 return SSL_TLSEXT_ERR_ALERT_FATAL;
2681 }
2682 /* Need to set up a new SSL_CTX to switch to */
2683 if (session->proto == COAP_PROTO_DTLS) {
2684 /* Set up DTLS context */
2685 ctx = SSL_CTX_new(DTLS_method());
2686 if (!ctx)
2687 goto error;
2688 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2689 SSL_CTX_set_app_data(ctx, &context->dtls);
2690 SSL_CTX_set_read_ahead(ctx, 1);
2691 coap_set_user_prefs(ctx);
2692 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2693 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2694 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2695 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2696 }
2697#if !COAP_DISABLE_TCP
2698 else {
2699 /* Set up TLS context */
2700 ctx = SSL_CTX_new(TLS_method());
2701 if (!ctx)
2702 goto error;
2703 SSL_CTX_set_app_data(ctx, &context->tls);
2704 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2705 coap_set_user_prefs(ctx);
2706 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2707 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2708 }
2709#endif /* !COAP_DISABLE_TCP */
2710 sni_setup_data = *setup_data;
2711 sni_setup_data.pki_key = *new_entry;
2712 setup_pki_server(ctx, &sni_setup_data);
2713
2714 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2715 (context->sni_count+1)*sizeof(sni_entry));
2716 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2717 context->sni_entry_list[context->sni_count].ctx = ctx;
2718 context->sni_count++;
2719 }
2720 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2721 SSL_clear_options(ssl, 0xFFFFFFFFL);
2722 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2723 }
2724
2725 /*
2726 * Have to do extra call back next to get client algorithms
2727 * SSL_get_client_ciphers() does not work this early on
2728 */
2729 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2730 return SSL_TLSEXT_ERR_OK;
2731
2732error:
2733 return SSL_TLSEXT_ERR_ALERT_WARNING;
2734}
2735
2736/* OpenSSL < 1.1.1 */
2737/*
2738 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2739 * called to see if SNI is being used.
2740 *
2741 * Set up by SSL_CTX_set_tlsext_servername_callback()
2742 * in coap_dtls_context_set_spsk()
2743 */
2744static int
2745psk_tls_server_name_call_back(SSL *ssl,
2746 int *sd COAP_UNUSED,
2747 void *arg
2748 ) {
2749 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2750
2751 if (!ssl) {
2752 return SSL_TLSEXT_ERR_NOACK;
2753 }
2754
2755 if (setup_data->validate_sni_call_back) {
2756 /* SNI checking requested */
2757 coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2758 coap_openssl_context_t *o_context = (c_session && c_session->context) ?
2759 ((coap_openssl_context_t *)c_session->context->dtls_context) : NULL;
2760 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2761 size_t i;
2762 char lhint[COAP_DTLS_HINT_LENGTH];
2763
2764 if (!o_context)
2765 return SSL_TLSEXT_ERR_ALERT_FATAL;
2766
2767 if (!sni || !sni[0]) {
2768 sni = "";
2769 }
2770 for (i = 0; i < o_context->psk_sni_count; i++) {
2771 if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2772 break;
2773 }
2774 }
2775 if (i == o_context->psk_sni_count) {
2776 SSL_CTX *ctx;
2777 const coap_dtls_spsk_info_t *new_entry;
2778
2779 coap_lock_callback_ret(new_entry,
2780 setup_data->validate_sni_call_back(sni,
2781 c_session,
2782 setup_data->sni_call_back_arg));
2783 if (!new_entry) {
2784 return SSL_TLSEXT_ERR_ALERT_FATAL;
2785 }
2786 /* Need to set up a new SSL_CTX to switch to */
2787 if (c_session->proto == COAP_PROTO_DTLS) {
2788 /* Set up DTLS context */
2789 ctx = SSL_CTX_new(DTLS_method());
2790 if (!ctx)
2791 goto error;
2792 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2793 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2794 SSL_CTX_set_read_ahead(ctx, 1);
2795 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2796 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2797 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2798 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2799 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2800 }
2801#if !COAP_DISABLE_TCP
2802 else {
2803 /* Set up TLS context */
2804 ctx = SSL_CTX_new(TLS_method());
2805 if (!ctx)
2806 goto error;
2807 SSL_CTX_set_app_data(ctx, &o_context->tls);
2808 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2809 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2810 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2811 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2812 }
2813#endif /* !COAP_DISABLE_TCP */
2814
2815 o_context->psk_sni_entry_list =
2816 OPENSSL_realloc(o_context->psk_sni_entry_list,
2817 (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2818 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2819 OPENSSL_strdup(sni);
2820 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2821 *new_entry;
2822 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2823 ctx;
2824 o_context->psk_sni_count++;
2825 }
2826 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2827 SSL_clear_options(ssl, 0xFFFFFFFFL);
2828 SSL_set_options(ssl,
2829 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2831 &o_context->psk_sni_entry_list[i].psk_info.key);
2832 snprintf(lhint, sizeof(lhint), "%.*s",
2833 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2834 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2835 SSL_use_psk_identity_hint(ssl, lhint);
2836 }
2837
2838 /*
2839 * Have to do extra call back next to get client algorithms
2840 * SSL_get_client_ciphers() does not work this early on
2841 */
2842 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2843 return SSL_TLSEXT_ERR_OK;
2844
2845error:
2846 return SSL_TLSEXT_ERR_ALERT_WARNING;
2847}
2848#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2849/* OpenSSL >= 1.1.1 */
2850/*
2851 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2852 * called early in the Client Hello processing so it is possible to determine
2853 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2854 * necessary.
2855 *
2856 * Set up by SSL_CTX_set_client_hello_cb().
2857 */
2858static int
2859tls_client_hello_call_back(SSL *ssl,
2860 int *al,
2861 void *arg COAP_UNUSED
2862 ) {
2863 coap_session_t *session;
2864 coap_openssl_context_t *dtls_context;
2865 coap_dtls_pki_t *setup_data;
2866 int psk_requested = 0;
2867 const unsigned char *out;
2868 size_t outlen;
2869
2870 if (!ssl) {
2871 *al = SSL_AD_INTERNAL_ERROR;
2872 return SSL_CLIENT_HELLO_ERROR;
2873 }
2874 session = (coap_session_t *)SSL_get_app_data(ssl);
2875 assert(session != NULL);
2876 assert(session->context != NULL);
2877 assert(session->context->dtls_context != NULL);
2878 if (session == NULL ||
2879 session->context == NULL ||
2880 session->context->dtls_context == NULL) {
2881 *al = SSL_AD_INTERNAL_ERROR;
2882 return SSL_CLIENT_HELLO_ERROR;
2883 }
2884 dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2885 setup_data = &dtls_context->setup_data;
2886
2887 /*
2888 * See if PSK being requested
2889 */
2890 if ((session->psk_key) ||
2891 (session->context->spsk_setup_data.psk_info.key.s &&
2893 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2894 STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2895 STACK_OF(SSL_CIPHER) *scsvc = NULL;
2896
2897 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2898 SSL_client_hello_isv2(ssl),
2899 &peer_ciphers, &scsvc)) {
2900 int ii;
2901 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2902 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2903
2905 "Client cipher: %s (%04x)\n",
2906 SSL_CIPHER_get_name(peer_cipher),
2907 SSL_CIPHER_get_protocol_id(peer_cipher));
2908 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2909 psk_requested = 1;
2910 break;
2911 }
2912 }
2913 }
2914 sk_SSL_CIPHER_free(peer_ciphers);
2915 sk_SSL_CIPHER_free(scsvc);
2916 }
2917
2918 if (psk_requested) {
2919 /*
2920 * Client has requested PSK and it is supported
2921 */
2922 coap_log_debug(" %s: PSK request\n",
2923 coap_session_str(session));
2924 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2925 if (setup_data->additional_tls_setup_call_back) {
2926 /* Additional application setup wanted */
2927 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2928 return 0;
2929 }
2930 return SSL_CLIENT_HELLO_SUCCESS;
2931 }
2932
2933 /*
2934 * Handle Certificate requests
2935 */
2936
2937 /*
2938 * Determine what type of certificate is being requested
2939 */
2940 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
2941 &out, &outlen)) {
2942 size_t ii;
2943 for (ii = 0; ii < outlen; ii++) {
2944 switch (out[ii]) {
2945 case 0:
2946 /* RFC6091 X.509 */
2947 if (outlen >= 2) {
2948 /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
2949 goto is_x509;
2950 }
2951 break;
2952 case 2:
2953 /* RFC7250 RPK - not yet supported */
2954 break;
2955 default:
2956 break;
2957 }
2958 }
2959 *al = SSL_AD_UNSUPPORTED_EXTENSION;
2960 return SSL_CLIENT_HELLO_ERROR;
2961 }
2962
2963is_x509:
2964 if (setup_data->validate_sni_call_back) {
2965 /*
2966 * SNI checking requested
2967 */
2968 coap_dtls_pki_t sni_setup_data;
2969 coap_openssl_context_t *context =
2970 ((coap_openssl_context_t *)session->context->dtls_context);
2971 const char *sni = "";
2972 char *sni_tmp = NULL;
2973 size_t i;
2974
2975 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2976 outlen > 5 &&
2977 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2978 out[2] == TLSEXT_NAMETYPE_host_name &&
2979 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2980 /* Skip over length, type and length */
2981 out += 5;
2982 outlen -= 5;
2983 sni_tmp = OPENSSL_malloc(outlen+1);
2984 sni_tmp[outlen] = '\000';
2985 memcpy(sni_tmp, out, outlen);
2986 sni = sni_tmp;
2987 }
2988 /* Is this a cached entry? */
2989 for (i = 0; i < context->sni_count; i++) {
2990 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2991 break;
2992 }
2993 }
2994 if (i == context->sni_count) {
2995 /*
2996 * New SNI request
2997 */
2998 coap_dtls_key_t *new_entry;
2999
3000 coap_lock_callback_ret(new_entry,
3001 setup_data->validate_sni_call_back(sni,
3002 setup_data->sni_call_back_arg));
3003 if (!new_entry) {
3004 *al = SSL_AD_UNRECOGNIZED_NAME;
3005 return SSL_CLIENT_HELLO_ERROR;
3006 }
3007
3008
3009 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
3010 (context->sni_count+1)*sizeof(sni_entry));
3011 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
3012 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
3013 context->sni_count++;
3014 }
3015 if (sni_tmp) {
3016 OPENSSL_free(sni_tmp);
3017 }
3018 sni_setup_data = *setup_data;
3019 sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
3020 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
3021 } else {
3022 setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
3023 }
3024
3025 coap_log_debug(" %s: Using PKI ciphers\n",
3026 coap_session_str(session));
3027
3028 if (setup_data->verify_peer_cert) {
3029 SSL_set_verify(ssl,
3030 SSL_VERIFY_PEER |
3031 SSL_VERIFY_CLIENT_ONCE |
3032 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3033 tls_verify_call_back);
3034 } else {
3035 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3036 }
3037
3038 /* Check CA Chain */
3039 if (setup_data->cert_chain_validation)
3040 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
3041
3042 /* Certificate Revocation */
3043 if (setup_data->check_cert_revocation) {
3044 X509_VERIFY_PARAM *param;
3045
3046 param = X509_VERIFY_PARAM_new();
3047 if (param) {
3048 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3049 SSL_set1_param(ssl, param);
3050 X509_VERIFY_PARAM_free(param);
3051 }
3052 }
3053 if (setup_data->additional_tls_setup_call_back) {
3054 /* Additional application setup wanted */
3055 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3056 return 0;
3057 }
3058 return SSL_CLIENT_HELLO_SUCCESS;
3059}
3060
3061/* OpenSSL >= 1.1.1 */
3062/*
3063 * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is
3064 * called early in the Client Hello processing so it is possible to determine
3065 * whether SNI needs to be handled
3066 *
3067 * Set up by SSL_CTX_set_client_hello_cb().
3068 */
3069static int
3070psk_tls_client_hello_call_back(SSL *ssl,
3071 int *al,
3072 void *arg COAP_UNUSED
3073 ) {
3074 coap_session_t *c_session;
3075 coap_openssl_context_t *o_context;
3076 coap_dtls_spsk_t *setup_data;
3077 const unsigned char *out;
3078 size_t outlen;
3079
3080 if (!ssl)
3081 goto int_err;
3082 c_session = (coap_session_t *)SSL_get_app_data(ssl);
3083 if (!c_session || !c_session->context) {
3084 goto int_err;
3085 }
3086 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
3087 if (!o_context) {
3088 goto int_err;
3089 }
3090 setup_data = &c_session->context->spsk_setup_data;
3091
3092 if (setup_data->validate_sni_call_back) {
3093 /*
3094 * SNI checking requested
3095 */
3096 const char *sni = "";
3097 char *sni_tmp = NULL;
3098 char lhint[COAP_DTLS_HINT_LENGTH];
3099
3100 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3101 outlen > 5 &&
3102 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3103 out[2] == TLSEXT_NAMETYPE_host_name &&
3104 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3105 /* Skip over length, type and length */
3106 out += 5;
3107 outlen -= 5;
3108 sni_tmp = OPENSSL_malloc(outlen+1);
3109 if (sni_tmp) {
3110 sni_tmp[outlen] = '\000';
3111 memcpy(sni_tmp, out, outlen);
3112 sni = sni_tmp;
3113 }
3114 }
3115
3116#if OPENSSL_VERSION_NUMBER < 0x10101000L
3117 size_t i;
3118 /* Is this a cached entry? */
3119 for (i = 0; i < o_context->psk_sni_count; i++) {
3120 if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) {
3121 break;
3122 }
3123 }
3124 if (i == o_context->psk_sni_count) {
3125#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3126 /*
3127 * New SNI request
3128 */
3129 const coap_dtls_spsk_info_t *new_entry;
3130
3131 coap_lock_callback_ret(new_entry,
3132 setup_data->validate_sni_call_back(
3133 sni,
3134 c_session,
3135 setup_data->sni_call_back_arg));
3136 if (!new_entry) {
3137 *al = SSL_AD_UNRECOGNIZED_NAME;
3138 return SSL_CLIENT_HELLO_ERROR;
3139 }
3140
3141#if OPENSSL_VERSION_NUMBER < 0x10101000L
3142 psk_sni_entry *tmp_entry;
3143 tmp_entry =
3144 OPENSSL_realloc(o_context->psk_sni_entry_list,
3145 (o_context->psk_sni_count+1)*sizeof(sni_entry));
3146 if (tmp_entry) {
3147 o_context->psk_sni_entry_list = tmp_entry;
3148 o_context->psk_sni_entry_list[o_context->psk_sni_count]
3149 .sni =
3150 OPENSSL_strdup(sni);
3151 if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) {
3152 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
3153 *new_entry;
3154 o_context->psk_sni_count++;
3155 }
3156 }
3157 } else {
3158 new_entry = &o_context->psk_sni_entry_list[i].psk_info;
3159 }
3160#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3161
3162 if (sni_tmp) {
3163 OPENSSL_free(sni_tmp);
3164 }
3165 if (coap_session_refresh_psk_hint(c_session,
3166 &new_entry->hint)
3167 == 0) {
3168 goto int_err;
3169 }
3170 if (coap_session_refresh_psk_key(c_session,
3171 &new_entry->key)
3172 == 0) {
3173 goto int_err;
3174 }
3175 if (new_entry->hint.s) {
3176 snprintf(lhint, sizeof(lhint), "%.*s",
3177 (int)new_entry->hint.length,
3178 new_entry->hint.s);
3179 SSL_use_psk_identity_hint(ssl, lhint);
3180 }
3181 }
3182 return SSL_CLIENT_HELLO_SUCCESS;
3183
3184int_err:
3185 *al = SSL_AD_INTERNAL_ERROR;
3186 return SSL_CLIENT_HELLO_ERROR;
3187}
3188#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3189#endif /* COAP_SERVER_SUPPORT */
3190
3191int
3193 const coap_dtls_pki_t *setup_data,
3194 const coap_dtls_role_t role) {
3195 coap_openssl_context_t *context =
3196 ((coap_openssl_context_t *)ctx->dtls_context);
3197 BIO *bio;
3198 if (!setup_data)
3199 return 0;
3200 context->setup_data = *setup_data;
3201
3202 if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3203 if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3204 context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3205 context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3206 if (!defined_engine) {
3207 coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3208 return 0;
3209 }
3210 }
3211 }
3212
3213 if (!context->setup_data.verify_peer_cert) {
3214 /* Needs to be clear so that no CA DNs are transmitted */
3215 context->setup_data.check_common_ca = 0;
3216 /* Allow all of these but warn if issue */
3217 context->setup_data.allow_self_signed = 1;
3218 context->setup_data.allow_expired_certs = 1;
3219 context->setup_data.cert_chain_validation = 1;
3220 context->setup_data.cert_chain_verify_depth = 10;
3221 context->setup_data.check_cert_revocation = 1;
3222 context->setup_data.allow_no_crl = 1;
3223 context->setup_data.allow_expired_crl = 1;
3224 context->setup_data.allow_bad_md_hash = 1;
3225 context->setup_data.allow_short_rsa_length = 1;
3226 }
3227#if COAP_SERVER_SUPPORT
3228 if (role == COAP_DTLS_ROLE_SERVER) {
3229 if (context->dtls.ctx) {
3230 /* SERVER DTLS */
3231#if OPENSSL_VERSION_NUMBER < 0x10101000L
3232 if (!setup_pki_server(context->dtls.ctx, setup_data))
3233 return 0;
3234#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3235 /* libcoap is managing TLS connection based on setup_data options */
3236 /* Need to set up logic to differentiate between a PSK or PKI session */
3237 /*
3238 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3239 * which is not in 1.1.0
3240 */
3241#if OPENSSL_VERSION_NUMBER < 0x10101000L
3242 if (SSLeay() >= 0x10101000L) {
3243 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3244 "no certificate checking\n",
3245 OPENSSL_VERSION_NUMBER, SSLeay());
3246 }
3247 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3248 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3249 tls_server_name_call_back);
3250#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3251 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3252 tls_client_hello_call_back,
3253 NULL);
3254#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3255 }
3256#if !COAP_DISABLE_TCP
3257 if (context->tls.ctx) {
3258 /* SERVER TLS */
3259#if OPENSSL_VERSION_NUMBER < 0x10101000L
3260 if (!setup_pki_server(context->tls.ctx, setup_data))
3261 return 0;
3262#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3263 /* libcoap is managing TLS connection based on setup_data options */
3264 /* Need to set up logic to differentiate between a PSK or PKI session */
3265 /*
3266 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3267 * which is not in 1.1.0
3268 */
3269#if OPENSSL_VERSION_NUMBER < 0x10101000L
3270 if (SSLeay() >= 0x10101000L) {
3271 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3272 "no certificate checking\n",
3273 OPENSSL_VERSION_NUMBER, SSLeay());
3274 }
3275 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3276 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3277 tls_server_name_call_back);
3278#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3279 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3280 tls_client_hello_call_back,
3281 NULL);
3282#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3283 /* TLS Only */
3284 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3285 }
3286#endif /* !COAP_DISABLE_TCP */
3287 }
3288#else /* ! COAP_SERVER_SUPPORT */
3289 (void)role;
3290#endif /* ! COAP_SERVER_SUPPORT */
3291
3292 if (!context->dtls.ssl) {
3293 /* This is set up to handle new incoming sessions to a server */
3294 context->dtls.ssl = SSL_new(context->dtls.ctx);
3295 if (!context->dtls.ssl)
3296 return 0;
3297 bio = BIO_new(context->dtls.meth);
3298 if (!bio) {
3299 SSL_free(context->dtls.ssl);
3300 context->dtls.ssl = NULL;
3301 return 0;
3302 }
3303 SSL_set_bio(context->dtls.ssl, bio, bio);
3304 SSL_set_app_data(context->dtls.ssl, NULL);
3305 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3306 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3307 }
3308 context->psk_pki_enabled |= IS_PKI;
3309 if (setup_data->use_cid) {
3310 coap_log_warn("OpenSSL has no Connection-ID support\n");
3311 }
3312 return 1;
3313}
3314
3315int
3317 const char *ca_file,
3318 const char *ca_dir
3319 ) {
3320 coap_openssl_context_t *context =
3321 ((coap_openssl_context_t *)ctx->dtls_context);
3322 if (context->dtls.ctx) {
3323 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3324 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3325 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3326 return 0;
3327 }
3328 }
3329#if !COAP_DISABLE_TCP
3330 if (context->tls.ctx) {
3331 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3332 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3333 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3334 return 0;
3335 }
3336 }
3337#endif /* !COAP_DISABLE_TCP */
3338 return 1;
3339}
3340
3341int
3343#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3344 coap_openssl_context_t *context =
3345 ((coap_openssl_context_t *)ctx->dtls_context);
3346 if (context->dtls.ctx) {
3347 if (!SSL_CTX_set_default_verify_store(context->dtls.ctx)) {
3348 coap_log_warn("Unable to load trusted root CAs\n");
3349 return 0;
3350 }
3351 }
3352#if !COAP_DISABLE_TCP
3353 if (context->tls.ctx) {
3354 if (!SSL_CTX_set_default_verify_store(context->tls.ctx)) {
3355 coap_log_warn("Unable to load trusted root CAs\n");
3356 return 0;
3357 }
3358 }
3359#endif /* !COAP_DISABLE_TCP */
3360 return 1;
3361#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3362 (void)ctx;
3363 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3364 "not supported for OpenSSL < v3.0.0\n");
3365 return 0;
3366#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3367}
3368
3369int
3371 coap_openssl_context_t *context =
3372 ((coap_openssl_context_t *)ctx->dtls_context);
3373 return context->psk_pki_enabled ? 1 : 0;
3374}
3375
3376
3377void
3378coap_dtls_free_context(void *handle) {
3379 size_t i;
3380 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3381
3382 if (context->dtls.ssl)
3383 SSL_free(context->dtls.ssl);
3384 if (context->dtls.ctx)
3385 SSL_CTX_free(context->dtls.ctx);
3386 if (context->dtls.cookie_hmac)
3387 HMAC_CTX_free(context->dtls.cookie_hmac);
3388 if (context->dtls.meth)
3389 BIO_meth_free(context->dtls.meth);
3390 if (context->dtls.bio_addr)
3391 BIO_ADDR_free(context->dtls.bio_addr);
3392#if !COAP_DISABLE_TCP
3393 if (context->tls.ctx)
3394 SSL_CTX_free(context->tls.ctx);
3395 if (context->tls.meth)
3396 BIO_meth_free(context->tls.meth);
3397#endif /* !COAP_DISABLE_TCP */
3398 for (i = 0; i < context->sni_count; i++) {
3399 OPENSSL_free(context->sni_entry_list[i].sni);
3400#if OPENSSL_VERSION_NUMBER < 0x10101000L
3401 SSL_CTX_free(context->sni_entry_list[i].ctx);
3402#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3403 }
3404 if (context->sni_count)
3405 OPENSSL_free(context->sni_entry_list);
3406#if OPENSSL_VERSION_NUMBER < 0x10101000L
3407 for (i = 0; i < context->psk_sni_count; i++) {
3408 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3409 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3410 }
3411 if (context->psk_sni_count)
3412 OPENSSL_free(context->psk_sni_entry_list);
3413#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3414 coap_free_type(COAP_STRING, context);
3415}
3416
3417#if COAP_SERVER_SUPPORT
3418void *
3420 BIO *nbio = NULL;
3421 SSL *nssl = NULL, *ssl = NULL;
3422 coap_ssl_data *data;
3423 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3424 int r;
3425 const coap_bin_const_t *psk_hint;
3426 BIO *rbio;
3427
3428 nssl = SSL_new(dtls->ctx);
3429 if (!nssl)
3430 goto error;
3431 nbio = BIO_new(dtls->meth);
3432 if (!nbio)
3433 goto error;
3434 SSL_set_bio(nssl, nbio, nbio);
3435 SSL_set_app_data(nssl, NULL);
3436 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3437 SSL_set_mtu(nssl, (long)session->mtu);
3438 ssl = dtls->ssl;
3439 dtls->ssl = nssl;
3440 nssl = NULL;
3441 SSL_set_app_data(ssl, session);
3442
3443 rbio = SSL_get_rbio(ssl);
3444 data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3445 if (!data)
3446 goto error;
3447 data->session = session;
3448
3449 /* hint may get updated if/when handling SNI callback */
3450 psk_hint = coap_get_session_server_psk_hint(session);
3451 if (psk_hint != NULL && psk_hint->length) {
3452 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3453
3454 if (hint) {
3455 memcpy(hint, psk_hint->s, psk_hint->length);
3456 hint[psk_hint->length] = '\000';
3457 SSL_use_psk_identity_hint(ssl, hint);
3458 OPENSSL_free(hint);
3459 } else {
3460 coap_log_warn("hint malloc failure\n");
3461 }
3462 }
3463
3464 r = SSL_accept(ssl);
3465 if (r == -1) {
3466 int err = SSL_get_error(ssl, r);
3467 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3468 r = 0;
3469 }
3470
3471 if (r == 0) {
3472 SSL_free(ssl);
3473 return NULL;
3474 }
3475
3476 return ssl;
3477
3478error:
3479 if (nssl)
3480 SSL_free(nssl);
3481 return NULL;
3482}
3483#endif /* COAP_SERVER_SUPPORT */
3484
3485#if COAP_CLIENT_SUPPORT
3486static int
3487setup_client_ssl_session(coap_session_t *session, SSL *ssl
3488 ) {
3489 coap_openssl_context_t *context =
3490 ((coap_openssl_context_t *)session->context->dtls_context);
3491
3492 if (context->psk_pki_enabled & IS_PSK) {
3493 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3494
3495 /* Issue SNI if requested */
3496 if (setup_data->client_sni &&
3497 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3498 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3499 setup_data->client_sni);
3500 }
3501 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3502#if COAP_SERVER_SUPPORT
3503 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3504#endif /* COAP_SERVER_SUPPORT */
3505 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3506 if (setup_data->validate_ih_call_back) {
3507 if (session->proto == COAP_PROTO_DTLS) {
3508 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3509 }
3510#if !COAP_DISABLE_TCP
3511 else {
3512 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3513 }
3514#endif /* !COAP_DISABLE_TCP */
3515 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3516 }
3517 }
3518 if ((context->psk_pki_enabled & IS_PKI) ||
3519 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3520 /*
3521 * If neither PSK or PKI have been set up, use PKI basics.
3522 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3523 */
3524 coap_dtls_pki_t *setup_data = &context->setup_data;
3525
3526 if (!(context->psk_pki_enabled & IS_PKI)) {
3527 /* PKI not defined - set up some defaults */
3528 setup_data->verify_peer_cert = 1;
3529 setup_data->check_common_ca = 0;
3530 setup_data->allow_self_signed = 1;
3531 setup_data->allow_expired_certs = 1;
3532 setup_data->cert_chain_validation = 1;
3533 setup_data->cert_chain_verify_depth = 2;
3534 setup_data->check_cert_revocation = 1;
3535 setup_data->allow_no_crl = 1;
3536 setup_data->allow_expired_crl = 1;
3537 setup_data->is_rpk_not_cert = 0;
3538 setup_data->use_cid = 0;
3539 }
3540 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3541 return 0;
3542 /* libcoap is managing (D)TLS connection based on setup_data options */
3543#if !COAP_DISABLE_TCP
3544 if (session->proto == COAP_PROTO_TLS)
3545 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3546#endif /* !COAP_DISABLE_TCP */
3547
3548 /* Issue SNI if requested */
3549 if (setup_data->client_sni &&
3550 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3551 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3552 setup_data->client_sni);
3553 }
3554 /* Certificate Revocation */
3555 if (setup_data->check_cert_revocation) {
3556 X509_VERIFY_PARAM *param;
3557
3558 param = X509_VERIFY_PARAM_new();
3559 if (param) {
3560 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3561 SSL_set1_param(ssl, param);
3562 X509_VERIFY_PARAM_free(param);
3563 }
3564 }
3565
3566 /* Verify Peer */
3567 if (setup_data->verify_peer_cert)
3568 SSL_set_verify(ssl,
3569 SSL_VERIFY_PEER |
3570 SSL_VERIFY_CLIENT_ONCE |
3571 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3572 tls_verify_call_back);
3573 else
3574 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3575
3576 /* Check CA Chain */
3577 if (setup_data->cert_chain_validation)
3578 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3579
3580 }
3581#if COAP_DTLS_RETRANSMIT_MS != 1000
3582#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3583 if (session->proto == COAP_PROTO_DTLS) {
3584 DTLS_set_timer_cb(ssl, timer_cb);
3585 }
3586#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3587#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3588 return 1;
3589}
3590
3591void *
3593 BIO *bio = NULL;
3594 SSL *ssl = NULL;
3595 coap_ssl_data *data;
3596 int r;
3597 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3598 coap_dtls_context_t *dtls = &context->dtls;
3599
3600 ssl = SSL_new(dtls->ctx);
3601 if (!ssl)
3602 goto error;
3603 bio = BIO_new(dtls->meth);
3604 if (!bio)
3605 goto error;
3606 data = (coap_ssl_data *)BIO_get_data(bio);
3607 if (!data)
3608 goto error;
3609 data->session = session;
3610 SSL_set_bio(ssl, bio, bio);
3611 SSL_set_app_data(ssl, session);
3612 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3613 SSL_set_mtu(ssl, (long)session->mtu);
3614
3615 if (!setup_client_ssl_session(session, ssl))
3616 goto error;
3617
3618 session->dtls_timeout_count = 0;
3619
3620 r = SSL_connect(ssl);
3621 if (r == -1) {
3622 int ret = SSL_get_error(ssl, r);
3623 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3624 r = 0;
3625 }
3626
3627 if (r == 0)
3628 goto error;
3629
3630 session->tls = ssl;
3631 return ssl;
3632
3633error:
3634 if (ssl)
3635 SSL_free(ssl);
3636 return NULL;
3637}
3638
3639void
3641 SSL *ssl = (SSL *)session->tls;
3642 if (ssl)
3643 SSL_set_mtu(ssl, (long)session->mtu);
3644}
3645#endif /* COAP_CLIENT_SUPPORT */
3646
3647void
3649 SSL *ssl = (SSL *)session->tls;
3650 if (ssl) {
3651 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3652 int r = SSL_shutdown(ssl);
3653 if (r == 0)
3654 SSL_shutdown(ssl);
3655 }
3656 SSL_free(ssl);
3657 session->tls = NULL;
3658 if (session->context)
3660 }
3661}
3662
3663ssize_t
3665 const uint8_t *data, size_t data_len) {
3666 int r;
3667 SSL *ssl = (SSL *)session->tls;
3668
3669 if (ssl == NULL) {
3671 return -1;
3672 }
3673
3674 session->dtls_event = -1;
3675 ERR_clear_error();
3676 r = SSL_write(ssl, data, (int)data_len);
3677
3678 if (r <= 0) {
3679 int err = SSL_get_error(ssl, r);
3680 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3681 r = 0;
3682 } else {
3683 if (err == SSL_ERROR_ZERO_RETURN)
3685 else if (err == SSL_ERROR_SSL) {
3686 unsigned long e = ERR_get_error();
3687
3688 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3689 coap_session_str(session),
3690 ERR_GET_REASON(e), ERR_reason_error_string(e));
3692 } else {
3693 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3694 coap_session_str(session), err);
3695 }
3696 r = -1;
3697 }
3698 }
3699
3700 if (session->dtls_event >= 0) {
3701 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3702 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3703 coap_handle_event_lkd(session->context, session->dtls_event, session);
3704 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3705 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3707 r = -1;
3708 }
3709 }
3710
3711 if (r > 0) {
3712 if (r == (ssize_t)data_len)
3713 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3714 coap_session_str(session), r);
3715 else
3716 coap_log_debug("* %s: dtls: sent %4d of %4" PRIdS " bytes\n",
3717 coap_session_str(session), r, data_len);
3718 }
3719 return r;
3720}
3721
3722int
3724 return 0;
3725}
3726
3728coap_dtls_get_context_timeout(void *dtls_context) {
3729 (void)dtls_context;
3730 return 0;
3731}
3732
3735 SSL *ssl = (SSL *)session->tls;
3736 coap_ssl_data *ssl_data;
3737 BIO *rbio;
3738
3739 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3740 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3741 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3742 return ssl_data ? ssl_data->timeout : 1000;
3743}
3744
3745/*
3746 * return 1 timed out
3747 * 0 still timing out
3748 */
3749int
3751 SSL *ssl = (SSL *)session->tls;
3752
3753 if (ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE) {
3754 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3755 (DTLSv1_handle_timeout(ssl) < 0)) {
3756 /* Too many retries */
3758 return 1;
3759 }
3760 return 0;
3761 }
3762 return 1;
3763}
3764
3765#if COAP_SERVER_SUPPORT
3766int
3768 const uint8_t *data, size_t data_len) {
3769 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3770 coap_ssl_data *ssl_data;
3771 int r;
3772 BIO *rbio;
3773
3774 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3775 rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) : NULL;
3776 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3777 assert(ssl_data != NULL);
3778 if (!ssl_data) {
3779 errno = ENOMEM;
3780 return -1;
3781 }
3782 if (ssl_data->pdu_len) {
3783 coap_log_err("** %s: Previous data not read %u bytes\n",
3784 coap_session_str(session), ssl_data->pdu_len);
3785 }
3786 ssl_data->session = session;
3787 ssl_data->pdu = data;
3788 ssl_data->pdu_len = (unsigned)data_len;
3789 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3790 if (r <= 0) {
3791 int err = SSL_get_error(dtls->ssl, r);
3792 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3793 /* Got a ClientHello, sent-out a VerifyRequest */
3794 r = 0;
3795 }
3796 } else {
3797 /* Got a valid answer to a VerifyRequest */
3798 r = 1;
3799 }
3800
3801 /*
3802 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3803 * only does a 'peek' read of the incoming data.
3804 *
3805 */
3806 return r;
3807}
3808#endif /* COAP_SERVER_SUPPORT */
3809
3810int
3811coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3812 coap_ssl_data *ssl_data;
3813 SSL *ssl = (SSL *)session->tls;
3814 int r;
3815 BIO *rbio;
3816#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3817 int retry = 0;
3818#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3819
3820 assert(ssl != NULL);
3821
3822 int in_init = SSL_in_init(ssl);
3823 uint8_t pdu[COAP_RXBUFFER_SIZE];
3824 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3825 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3826 assert(ssl_data != NULL);
3827 if (!ssl_data) {
3828 errno = ENOMEM;
3829 return -1;
3830 }
3831
3832 if (ssl_data->pdu_len) {
3833 coap_log_err("** %s: Previous data not read %u bytes\n",
3834 coap_session_str(session), ssl_data->pdu_len);
3835 }
3836 ssl_data->pdu = data;
3837 ssl_data->pdu_len = (unsigned)data_len;
3838
3839 session->dtls_event = -1;
3840#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3841retry:
3842#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3843 ERR_clear_error();
3844 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3845 if (r > 0) {
3846 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3847 coap_session_str(session), r);
3848 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3849 goto finished;
3850 } else {
3851 int err = SSL_get_error(ssl, r);
3852 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3853 if (in_init && SSL_is_init_finished(ssl)) {
3854 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3855 coap_session_str(session), SSL_get_cipher_name(ssl));
3857 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3858 }
3859 r = 0;
3860 } else {
3861 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3863 else if (err == SSL_ERROR_SSL) {
3864 unsigned long e = ERR_get_error();
3865
3866#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3867#include <openssl/proverr.h>
3868 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3869 /* Loading trust store - first access causes a directory read error */
3870 retry = 1;
3871 goto retry;
3872 }
3873#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3874 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3875 coap_session_str(session),
3876 ERR_GET_REASON(e), ERR_reason_error_string(e));
3878 } else {
3879 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3880 coap_session_str(session), err);
3881 }
3882 r = -1;
3883 }
3884 if (session->dtls_event >= 0) {
3885 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3886 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3887 coap_handle_event_lkd(session->context, session->dtls_event, session);
3888 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3889 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3891 ssl_data = NULL;
3892 r = -1;
3893 }
3894 }
3895 }
3896
3897finished:
3898 if (ssl_data && ssl_data->pdu_len) {
3899 /* pdu data is held on stack which will not stay there */
3900 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3901 ssl_data->pdu_len = 0;
3902 ssl_data->pdu = NULL;
3903 }
3904 return r;
3905}
3906
3907unsigned int
3909 unsigned int overhead = 37;
3910 const SSL_CIPHER *s_ciph = NULL;
3911 if (session->tls != NULL)
3912 s_ciph = SSL_get_current_cipher(session->tls);
3913 if (s_ciph) {
3914 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3915
3916 const EVP_CIPHER *e_ciph;
3917 const EVP_MD *e_md;
3918 char cipher[128];
3919
3920 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3921
3922 switch (EVP_CIPHER_mode(e_ciph)) {
3923 case EVP_CIPH_GCM_MODE:
3924 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3925 maclen = EVP_GCM_TLS_TAG_LEN;
3926 break;
3927
3928 case EVP_CIPH_CCM_MODE:
3929 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3930 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3931 if (strstr(cipher, "CCM8"))
3932 maclen = 8;
3933 else
3934 maclen = 16;
3935 break;
3936
3937 case EVP_CIPH_CBC_MODE:
3938 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3939 blocksize = EVP_CIPHER_block_size(e_ciph);
3940 ivlen = EVP_CIPHER_iv_length(e_ciph);
3941 pad = 1;
3942 maclen = EVP_MD_size(e_md);
3943 break;
3944
3945 case EVP_CIPH_STREAM_CIPHER:
3946 /* Seen with PSK-CHACHA20-POLY1305 */
3947 ivlen = 8;
3948 maclen = 8;
3949 break;
3950
3951 default:
3952 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3953 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3954 cipher);
3955 ivlen = 8;
3956 maclen = 16;
3957 break;
3958 }
3959 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3960 }
3961 return overhead;
3962}
3963
3964#if !COAP_DISABLE_TCP
3965#if COAP_CLIENT_SUPPORT
3966void *
3968 BIO *bio = NULL;
3969 SSL *ssl = NULL;
3970 int r;
3971 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3972 coap_tls_context_t *tls = &context->tls;
3973
3974 ssl = SSL_new(tls->ctx);
3975 if (!ssl)
3976 goto error;
3977 bio = BIO_new(tls->meth);
3978 if (!bio)
3979 goto error;
3980 BIO_set_data(bio, session);
3981 SSL_set_bio(ssl, bio, bio);
3982 SSL_set_app_data(ssl, session);
3983
3984 if (!setup_client_ssl_session(session, ssl))
3985 return 0;
3986
3987 r = SSL_connect(ssl);
3988 if (r == -1) {
3989 int ret = SSL_get_error(ssl, r);
3990 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3991 r = 0;
3992 if (ret == SSL_ERROR_WANT_READ)
3993 session->sock.flags |= COAP_SOCKET_WANT_READ;
3994 if (ret == SSL_ERROR_WANT_WRITE) {
3995 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3996#ifdef COAP_EPOLL_SUPPORT
3997 coap_epoll_ctl_mod(&session->sock,
3998 EPOLLOUT |
3999 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4000 EPOLLIN : 0),
4001 __func__);
4002#endif /* COAP_EPOLL_SUPPORT */
4003 }
4004 }
4005
4006 if (r == 0)
4007 goto error;
4008
4009 session->tls = ssl;
4010 if (SSL_is_init_finished(ssl)) {
4012 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4013 }
4014
4015 return ssl;
4016
4017error:
4018 if (ssl)
4019 SSL_free(ssl);
4020 return NULL;
4021}
4022#endif /* COAP_CLIENT_SUPPORT */
4023
4024#if COAP_SERVER_SUPPORT
4025void *
4027 BIO *bio = NULL;
4028 SSL *ssl = NULL;
4029 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
4030 int r;
4031 const coap_bin_const_t *psk_hint;
4032
4033 ssl = SSL_new(tls->ctx);
4034 if (!ssl)
4035 goto error;
4036 bio = BIO_new(tls->meth);
4037 if (!bio)
4038 goto error;
4039 BIO_set_data(bio, session);
4040 SSL_set_bio(ssl, bio, bio);
4041 SSL_set_app_data(ssl, session);
4042
4043 psk_hint = coap_get_session_server_psk_hint(session);
4044 if (psk_hint != NULL && psk_hint->length) {
4045 char *hint = OPENSSL_malloc(psk_hint->length + 1);
4046
4047 if (hint) {
4048 memcpy(hint, psk_hint->s, psk_hint->length);
4049 hint[psk_hint->length] = '\000';
4050 SSL_use_psk_identity_hint(ssl, hint);
4051 OPENSSL_free(hint);
4052 } else {
4053 coap_log_warn("hint malloc failure\n");
4054 }
4055 }
4056
4057 r = SSL_accept(ssl);
4058 if (r == -1) {
4059 int err = SSL_get_error(ssl, r);
4060 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4061 r = 0;
4062 if (err == SSL_ERROR_WANT_READ)
4063 session->sock.flags |= COAP_SOCKET_WANT_READ;
4064 if (err == SSL_ERROR_WANT_WRITE) {
4065 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4066#ifdef COAP_EPOLL_SUPPORT
4067 coap_epoll_ctl_mod(&session->sock,
4068 EPOLLOUT |
4069 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4070 EPOLLIN : 0),
4071 __func__);
4072#endif /* COAP_EPOLL_SUPPORT */
4073 }
4074 }
4075
4076 if (r == 0)
4077 goto error;
4078
4079 session->tls = ssl;
4080 if (SSL_is_init_finished(ssl)) {
4082 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4083 }
4084
4085#if COAP_DTLS_RETRANSMIT_MS != 1000
4086#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4087 if (session->proto == COAP_PROTO_DTLS) {
4088 DTLS_set_timer_cb(ssl, timer_cb);
4089 }
4090#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4091#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4092
4093 return ssl;
4094
4095error:
4096 if (ssl)
4097 SSL_free(ssl);
4098 return NULL;
4099}
4100#endif /* COAP_SERVER_SUPPORT */
4101
4102void
4104 SSL *ssl = (SSL *)session->tls;
4105 if (ssl) {
4106 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4107 int r = SSL_shutdown(ssl);
4108 if (r == 0)
4109 SSL_shutdown(ssl);
4110 }
4111 SSL_free(ssl);
4112 session->tls = NULL;
4113 if (session->context)
4115 }
4116}
4117
4118/*
4119 * strm
4120 * return +ve Number of bytes written.
4121 * -1 Error (error in errno).
4122 */
4123ssize_t
4124coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4125 SSL *ssl = (SSL *)session->tls;
4126 int r, in_init;
4127
4128 if (ssl == NULL)
4129 return -1;
4130
4131 in_init = !SSL_is_init_finished(ssl);
4132 session->dtls_event = -1;
4133 ERR_clear_error();
4134 r = SSL_write(ssl, data, (int)data_len);
4135
4136 if (r <= 0) {
4137 int err = SSL_get_error(ssl, r);
4138 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4139 if (in_init && SSL_is_init_finished(ssl)) {
4140 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4141 coap_session_str(session), SSL_get_cipher_name(ssl));
4143 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4144 }
4145 if (err == SSL_ERROR_WANT_READ)
4146 session->sock.flags |= COAP_SOCKET_WANT_READ;
4147 else if (err == SSL_ERROR_WANT_WRITE) {
4148 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4149#ifdef COAP_EPOLL_SUPPORT
4150 coap_epoll_ctl_mod(&session->sock,
4151 EPOLLOUT |
4152 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4153 EPOLLIN : 0),
4154 __func__);
4155#endif /* COAP_EPOLL_SUPPORT */
4156 }
4157 r = 0;
4158 } else {
4159 if (err == SSL_ERROR_ZERO_RETURN)
4161 else if (err == SSL_ERROR_SSL) {
4162 unsigned long e = ERR_get_error();
4163
4164 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4165 coap_session_str(session),
4166 ERR_GET_REASON(e), ERR_reason_error_string(e));
4168 } else {
4169 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4170 coap_session_str(session), err);
4171 }
4172 r = -1;
4173 }
4174 } else if (in_init && SSL_is_init_finished(ssl)) {
4175 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4176 coap_session_str(session), SSL_get_cipher_name(ssl));
4178 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4179 }
4180
4181 if (session->dtls_event >= 0) {
4182 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4183 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4184 coap_handle_event_lkd(session->context, session->dtls_event, session);
4185 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4186 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4188 r = -1;
4189 }
4190 }
4191
4192 if (r >= 0) {
4193 if (r == (ssize_t)data_len)
4194 coap_log_debug("* %s: tls: sent %4d bytes\n",
4195 coap_session_str(session), r);
4196 else
4197 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
4198 coap_session_str(session), r, data_len);
4199 }
4200 return r;
4201}
4202
4203/*
4204 * strm
4205 * return >=0 Number of bytes read.
4206 * -1 Error (error in errno).
4207 */
4208ssize_t
4209coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4210 SSL *ssl = (SSL *)session->tls;
4211 int r, in_init;
4212
4213 if (ssl == NULL) {
4214 errno = ENXIO;
4215 return -1;
4216 }
4217
4218 in_init = !SSL_is_init_finished(ssl);
4219 session->dtls_event = -1;
4220 ERR_clear_error();
4221 r = SSL_read(ssl, data, (int)data_len);
4222 if (r <= 0) {
4223 int err = SSL_get_error(ssl, r);
4224 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4225 if (in_init && SSL_is_init_finished(ssl)) {
4226 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4227 coap_session_str(session), SSL_get_cipher_name(ssl));
4229 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4230 }
4231 if (err == SSL_ERROR_WANT_READ)
4232 session->sock.flags |= COAP_SOCKET_WANT_READ;
4233 if (err == SSL_ERROR_WANT_WRITE) {
4234 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4235#ifdef COAP_EPOLL_SUPPORT
4236 coap_epoll_ctl_mod(&session->sock,
4237 EPOLLOUT |
4238 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4239 EPOLLIN : 0),
4240 __func__);
4241#endif /* COAP_EPOLL_SUPPORT */
4242 }
4243 r = 0;
4244 } else {
4245 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4247 else if (err == SSL_ERROR_SSL) {
4248 unsigned long e = ERR_get_error();
4249
4250 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4251 coap_session_str(session),
4252 ERR_GET_REASON(e), ERR_reason_error_string(e));
4254 } else {
4255 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4256 coap_session_str(session), err);
4257 }
4258 r = -1;
4259 }
4260 } else if (in_init && SSL_is_init_finished(ssl)) {
4261 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4262 coap_session_str(session), SSL_get_cipher_name(ssl));
4264 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4265 }
4266
4267 if (session->dtls_event >= 0) {
4268 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4269 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4270 coap_handle_event_lkd(session->context, session->dtls_event, session);
4271 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4272 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4274 r = -1;
4275 }
4276 }
4277
4278 if (r > 0) {
4279 coap_log_debug("* %s: tls: recv %4d bytes\n",
4280 coap_session_str(session), r);
4281 }
4282 return r;
4283}
4284#endif /* !COAP_DISABLE_TCP */
4285
4286#if COAP_SERVER_SUPPORT
4288coap_digest_setup(void) {
4289 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4290
4291 if (digest_ctx) {
4292 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4293 }
4294 return digest_ctx;
4295}
4296
4297void
4299 if (digest_ctx)
4300 EVP_MD_CTX_free(digest_ctx);
4301}
4302
4303int
4305 const uint8_t *data,
4306 size_t data_len) {
4307 return EVP_DigestUpdate(digest_ctx, data, data_len);
4308}
4309
4310int
4312 coap_digest_t *digest_buffer) {
4313 unsigned int size = sizeof(coap_digest_t);
4314 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4315
4316 coap_digest_free(digest_ctx);
4317 return ret;
4318}
4319#endif /* COAP_SERVER_SUPPORT */
4320
4321#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4322static void
4323coap_crypto_output_errors(const char *prefix) {
4324#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4325 (void)prefix;
4326#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4327 unsigned long e;
4328
4329 while ((e = ERR_get_error()))
4330 coap_log_warn("%s: %s%s\n",
4331 prefix,
4332 ERR_reason_error_string(e),
4333 ssl_function_definition(e));
4334#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4335}
4336#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4337
4338#if COAP_WS_SUPPORT
4339/*
4340 * The struct hash_algs and the function get_hash_alg() are used to
4341 * determine which hash type to use for creating the required hash object.
4342 */
4343static struct hash_algs {
4344 cose_alg_t alg;
4345 const EVP_MD *(*get_hash)(void);
4346 size_t length; /* in bytes */
4347} hashs[] = {
4348 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4349 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4350 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4351 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4352};
4353
4354static const EVP_MD *
4355get_hash_alg(cose_alg_t alg, size_t *length) {
4356 size_t idx;
4357
4358 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
4359 if (hashs[idx].alg == alg) {
4360 *length = hashs[idx].length;
4361 return hashs[idx].get_hash();
4362 }
4363 }
4364 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4365 return NULL;
4366}
4367
4368int
4370 const coap_bin_const_t *data,
4371 coap_bin_const_t **hash) {
4372 unsigned int length;
4373 const EVP_MD *evp_md;
4374 EVP_MD_CTX *evp_ctx = NULL;
4375 coap_binary_t *dummy = NULL;
4376 size_t hash_length;
4377
4378 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4379 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4380 return 0;
4381 }
4382 evp_ctx = EVP_MD_CTX_new();
4383 if (evp_ctx == NULL)
4384 goto error;
4385 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4386 goto error;
4387 ;
4388 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4389 goto error;
4390 ;
4391 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4392 if (dummy == NULL)
4393 goto error;
4394 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4395 goto error;
4396 dummy->length = length;
4397 if (hash_length < dummy->length)
4398 dummy->length = hash_length;
4399 *hash = (coap_bin_const_t *)(dummy);
4400 EVP_MD_CTX_free(evp_ctx);
4401 return 1;
4402
4403error:
4404 coap_crypto_output_errors("coap_crypto_hash");
4406 if (evp_ctx)
4407 EVP_MD_CTX_free(evp_ctx);
4408 return 0;
4409}
4410#endif /* COAP_WS_SUPPORT */
4411
4412#if COAP_OSCORE_SUPPORT
4413int
4415 return 1;
4416}
4417
4418#include <openssl/evp.h>
4419#include <openssl/hmac.h>
4420
4421/*
4422 * The struct cipher_algs and the function get_cipher_alg() are used to
4423 * determine which cipher type to use for creating the required cipher
4424 * suite object.
4425 */
4426static struct cipher_algs {
4427 cose_alg_t alg;
4428 const EVP_CIPHER *(*get_cipher)(void);
4429} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4430 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4431};
4432
4433static const EVP_CIPHER *
4434get_cipher_alg(cose_alg_t alg) {
4435 size_t idx;
4436
4437 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4438 if (ciphers[idx].alg == alg)
4439 return ciphers[idx].get_cipher();
4440 }
4441 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4442 return NULL;
4443}
4444
4445/*
4446 * The struct hmac_algs and the function get_hmac_alg() are used to
4447 * determine which hmac type to use for creating the required hmac
4448 * suite object.
4449 */
4450static struct hmac_algs {
4451 cose_hmac_alg_t hmac_alg;
4452 const EVP_MD *(*get_hmac)(void);
4453} hmacs[] = {
4454 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4455 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4456 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4457};
4458
4459static const EVP_MD *
4460get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4461 size_t idx;
4462
4463 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4464 if (hmacs[idx].hmac_alg == hmac_alg)
4465 return hmacs[idx].get_hmac();
4466 }
4467 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4468 return NULL;
4469}
4470
4471int
4473 return get_cipher_alg(alg) != NULL;
4474}
4475
4476int
4478 cose_hmac_alg_t hmac_alg;
4479
4480 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4481 return 0;
4482 return get_hmac_alg(hmac_alg) != NULL;
4483}
4484
4485#define C(Func) \
4486 if (1 != (Func)) { \
4487 goto error; \
4488 }
4489
4490int
4492 coap_bin_const_t *data,
4493 coap_bin_const_t *aad,
4494 uint8_t *result,
4495 size_t *max_result_len) {
4496 const EVP_CIPHER *cipher;
4497 const coap_crypto_aes_ccm_t *ccm;
4498 int tmp;
4499 int result_len = (int)(*max_result_len & INT_MAX);
4500 EVP_CIPHER_CTX *ctx;
4501
4502 if (data == NULL)
4503 return 0;
4504
4505 assert(params != NULL);
4506 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4507 return 0;
4508 }
4509
4510 /* TODO: set evp_md depending on params->alg */
4511 ccm = &params->params.aes;
4512
4513 ctx = EVP_CIPHER_CTX_new();
4514 if (!ctx)
4515 return 0;
4516
4517 /* EVP_CIPHER_CTX_init(ctx); */
4518 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4519 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4520 C(EVP_CIPHER_CTX_ctrl(ctx,
4521 EVP_CTRL_AEAD_SET_IVLEN,
4522 (int)(15 - ccm->l),
4523 NULL));
4524 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4525 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4526 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4527
4528 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4529 if (aad && aad->s && (aad->length > 0)) {
4530 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4531 }
4532 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4533 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4534 tmp = result_len;
4535 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4536 result_len += tmp;
4537
4538 /* retrieve the tag */
4539 C(EVP_CIPHER_CTX_ctrl(ctx,
4540 EVP_CTRL_CCM_GET_TAG,
4541 (int)ccm->tag_len,
4542 result + result_len));
4543
4544 *max_result_len = result_len + ccm->tag_len;
4545 EVP_CIPHER_CTX_free(ctx);
4546 return 1;
4547
4548error:
4549 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4550 return 0;
4551}
4552
4553int
4555 coap_bin_const_t *data,
4556 coap_bin_const_t *aad,
4557 uint8_t *result,
4558 size_t *max_result_len) {
4559 const EVP_CIPHER *cipher;
4560 const coap_crypto_aes_ccm_t *ccm;
4561 int tmp;
4562 int len;
4563 const uint8_t *tag;
4564 uint8_t *rwtag;
4565 EVP_CIPHER_CTX *ctx;
4566
4567 if (data == NULL)
4568 return 0;
4569
4570 assert(params != NULL);
4571 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4572 return 0;
4573 }
4574
4575 ccm = &params->params.aes;
4576
4577 if (data->length < ccm->tag_len) {
4578 return 0;
4579 } else {
4580 tag = data->s + data->length - ccm->tag_len;
4581 data->length -= ccm->tag_len;
4582 /* Kludge to stop compiler warning */
4583 memcpy(&rwtag, &tag, sizeof(rwtag));
4584 }
4585
4586 ctx = EVP_CIPHER_CTX_new();
4587 if (!ctx)
4588 return 0;
4589
4590 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4591 C(EVP_CIPHER_CTX_ctrl(ctx,
4592 EVP_CTRL_AEAD_SET_IVLEN,
4593 (int)(15 - ccm->l),
4594 NULL));
4595 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4596 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4597 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4598 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4599
4600 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4601 if (aad && aad->s && (aad->length > 0)) {
4602 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4603 }
4604 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4605 EVP_CIPHER_CTX_free(ctx);
4606 if (tmp <= 0) {
4607 *max_result_len = 0;
4608 return 0;
4609 }
4610 *max_result_len = len;
4611 return 1;
4612
4613error:
4614 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4615 return 0;
4616}
4617
4618int
4620 coap_bin_const_t *key,
4621 coap_bin_const_t *data,
4622 coap_bin_const_t **hmac) {
4623 unsigned int result_len;
4624 const EVP_MD *evp_md;
4625 coap_binary_t *dummy = NULL;
4626
4627 assert(key);
4628 assert(data);
4629 assert(hmac);
4630
4631 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4632 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4633 return 0;
4634 }
4635 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4636 if (dummy == NULL)
4637 return 0;
4638 result_len = (unsigned int)dummy->length;
4639 if (HMAC(evp_md,
4640 key->s,
4641 (int)key->length,
4642 data->s,
4643 (int)data->length,
4644 dummy->s,
4645 &result_len)) {
4646 dummy->length = result_len;
4647 *hmac = (coap_bin_const_t *)dummy;
4648 return 1;
4649 }
4650
4652 coap_crypto_output_errors("coap_crypto_hmac");
4653 return 0;
4654}
4655
4656#endif /* COAP_OSCORE_SUPPORT */
4657
4658#else /* ! COAP_WITH_LIBOPENSSL */
4659
4660#ifdef __clang__
4661/* Make compilers happy that do not like empty modules. As this function is
4662 * never used, we ignore -Wunused-function at the end of compiling this file
4663 */
4664#pragma GCC diagnostic ignored "-Wunused-function"
4665#endif
4666static inline void
4667dummy(void) {
4668}
4669
4670#endif /* ! COAP_WITH_LIBOPENSSL */
#define PRIdS
#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:5000
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:2934
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:321
@ COAP_PROTO_TLS
Definition coap_pdu.h:323
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