libcoap 4.3.5-develop-60e9f08
Loading...
Searching...
No Matches
coap_openssl.c
Go to the documentation of this file.
1/*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018-2025 Jon Shallow <supjps-libcoap@jpshallow.com>
6 *
7 * SPDX-License-Identifier: BSD-2-Clause
8 *
9 * This file is part of the CoAP library libcoap. Please see README for terms
10 * of use.
11 */
12
19
20#ifdef 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_st {
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->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 ret = 1;
672 break;
673 case BIO_CTRL_DGRAM_SET_PEEK_MODE:
674 data->peekmode = (unsigned)num;
675 break;
676 case BIO_CTRL_DGRAM_CONNECT:
677 case BIO_C_SET_FD:
678 case BIO_C_GET_FD:
679 case BIO_CTRL_DGRAM_SET_DONT_FRAG:
680 case BIO_CTRL_DGRAM_GET_MTU:
681 case BIO_CTRL_DGRAM_SET_MTU:
682 case BIO_CTRL_DGRAM_QUERY_MTU:
683 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
684 ret = -1;
685 break;
686 case BIO_CTRL_DUP:
687 case BIO_CTRL_FLUSH:
688 case BIO_CTRL_DGRAM_MTU_DISCOVER:
689 case BIO_CTRL_DGRAM_SET_CONNECTED:
690 ret = 1;
691 break;
692 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
693 data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval *)ptr)->tv_sec * 1000000 + ((
694 struct timeval *)ptr)->tv_usec);
695 ret = 1;
696 break;
697 case BIO_CTRL_RESET:
698 case BIO_C_FILE_SEEK:
699 case BIO_C_FILE_TELL:
700 case BIO_CTRL_INFO:
701 case BIO_CTRL_PENDING:
702 case BIO_CTRL_WPENDING:
703 case BIO_CTRL_DGRAM_GET_PEER:
704 case BIO_CTRL_DGRAM_SET_PEER:
705 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
706 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
707 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
708 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
709 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
710 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
711 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
712 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
713 default:
714 ret = 0;
715 break;
716 }
717 return ret;
718}
719
720static int
721coap_dtls_generate_cookie(SSL *ssl,
722 unsigned char *cookie,
723 unsigned int *cookie_len) {
724 coap_dtls_context_t *dtls =
725 (coap_dtls_context_t *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
726 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
727 int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
728 r &= HMAC_Update(dtls->cookie_hmac,
729 (const uint8_t *)&data->session->addr_info.local.addr,
730 (size_t)data->session->addr_info.local.size);
731 r &= HMAC_Update(dtls->cookie_hmac,
732 (const uint8_t *)&data->session->addr_info.remote.addr,
733 (size_t)data->session->addr_info.remote.size);
734 r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
735 return r;
736}
737
738static int
739coap_dtls_verify_cookie(SSL *ssl,
740 const uint8_t *cookie,
741 unsigned int cookie_len) {
742 uint8_t hmac[32];
743 unsigned len = 32;
744 if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
745 cookie_len == len && memcmp(cookie, hmac, len) == 0)
746 return 1;
747 else
748 return 0;
749}
750
751#if COAP_CLIENT_SUPPORT
752static unsigned int
753coap_dtls_psk_client_callback(SSL *ssl,
754 const char *hint,
755 char *identity,
756 unsigned int max_identity_len,
757 unsigned char *psk,
758 unsigned int max_psk_len) {
759 coap_session_t *c_session;
760 coap_openssl_context_t *o_context;
761 coap_dtls_cpsk_t *setup_data;
762 coap_bin_const_t temp;
763 const coap_dtls_cpsk_info_t *cpsk_info;
764 const coap_bin_const_t *psk_key;
765 const coap_bin_const_t *psk_identity;
766
767 c_session = (coap_session_t *)SSL_get_app_data(ssl);
768 if (c_session == NULL)
769 return 0;
770 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
771 if (o_context == NULL)
772 return 0;
773 setup_data = &c_session->cpsk_setup_data;
774
775 temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
776 temp.length = strlen((const char *)temp.s);
777 coap_session_refresh_psk_hint(c_session, &temp);
778
779 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
780 (const char *)temp.s);
781
782 if (setup_data->validate_ih_call_back) {
783 coap_str_const_t lhint;
784
785 lhint.s = temp.s;
786 lhint.length = temp.length;
787 coap_lock_callback_ret(cpsk_info, c_session->context,
788 setup_data->validate_ih_call_back(&lhint,
789 c_session,
790 setup_data->ih_call_back_arg));
791
792 if (cpsk_info == NULL)
793 return 0;
794
795 coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
796 coap_session_refresh_psk_key(c_session, &cpsk_info->key);
797 psk_identity = &cpsk_info->identity;
798 psk_key = &cpsk_info->key;
799 } else {
800 psk_identity = coap_get_session_client_psk_identity(c_session);
801 psk_key = coap_get_session_client_psk_key(c_session);
802 }
803
804 if (psk_identity == NULL || psk_key == NULL) {
805 coap_log_warn("no PSK available\n");
806 return 0;
807 }
808
809 /* identity has to be NULL terminated */
810 if (!max_identity_len)
811 return 0;
812 max_identity_len--;
813 if (psk_identity->length > max_identity_len) {
814 coap_log_warn("psk_identity too large, truncated to %d bytes\n",
815 max_identity_len);
816 } else {
817 /* Reduce to match */
818 max_identity_len = (unsigned int)psk_identity->length;
819 }
820 memcpy(identity, psk_identity->s, max_identity_len);
821 identity[max_identity_len] = '\000';
822
823 if (psk_key->length > max_psk_len) {
824 coap_log_warn("psk_key too large, truncated to %d bytes\n",
825 max_psk_len);
826 } else {
827 /* Reduce to match */
828 max_psk_len = (unsigned int)psk_key->length;
829 }
830 memcpy(psk, psk_key->s, max_psk_len);
831 return max_psk_len;
832}
833#endif /* COAP_CLIENT_SUPPORT */
834
835#if COAP_SERVER_SUPPORT
836static unsigned int
837coap_dtls_psk_server_callback(
838 SSL *ssl,
839 const char *identity,
840 unsigned char *psk,
841 unsigned int max_psk_len
842) {
843 coap_session_t *c_session;
844 coap_dtls_spsk_t *setup_data;
845 coap_bin_const_t lidentity;
846 const coap_bin_const_t *psk_key;
847
848 c_session = (coap_session_t *)SSL_get_app_data(ssl);
849 if (c_session == NULL)
850 return 0;
851
852 setup_data = &c_session->context->spsk_setup_data;
853
854 /* Track the Identity being used */
855 lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
856 lidentity.length = strlen((const char *)lidentity.s);
857 coap_session_refresh_psk_identity(c_session, &lidentity);
858
859 coap_log_debug("got psk_identity: '%.*s'\n",
860 (int)lidentity.length, (const char *)lidentity.s);
861
862 if (setup_data->validate_id_call_back) {
863 psk_key = setup_data->validate_id_call_back(&lidentity,
864 c_session,
865 setup_data->id_call_back_arg);
866
867 coap_session_refresh_psk_key(c_session, psk_key);
868 } else {
869 psk_key = coap_get_session_server_psk_key(c_session);
870 }
871
872 if (psk_key == NULL)
873 return 0;
874
875 if (psk_key->length > max_psk_len) {
876 coap_log_warn("psk_key too large, truncated to %d bytes\n",
877 max_psk_len);
878 } else {
879 /* Reduce to match */
880 max_psk_len = (unsigned int)psk_key->length;
881 }
882 memcpy(psk, psk_key->s, max_psk_len);
883 return max_psk_len;
884}
885#endif /* COAP_SERVER_SUPPORT */
886
887static const char *
888ssl_function_definition(unsigned long e) {
889#if OPENSSL_VERSION_NUMBER >= 0x30000000L
890 (void)e;
891 return "";
892#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
893 static char buff[80];
894
895 snprintf(buff, sizeof(buff), " at %s:%s",
896 ERR_lib_error_string(e), ERR_func_error_string(e));
897 return buff;
898#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
899}
900
901static void
902coap_dtls_info_callback(const SSL *ssl, int where, int ret) {
903 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
904 const char *pstr;
905 int w = where &~SSL_ST_MASK;
906
907 if (w & SSL_ST_CONNECT)
908 pstr = "SSL_connect";
909 else if (w & SSL_ST_ACCEPT)
910 pstr = "SSL_accept";
911 else
912 pstr = "undefined";
913
914 if (where & SSL_CB_LOOP) {
915 coap_dtls_log(COAP_LOG_DEBUG, "* %s: %s:%s\n",
916 coap_session_str(session), pstr, SSL_state_string_long(ssl));
917 } else if (where & SSL_CB_ALERT) {
918 coap_log_t log_level = COAP_LOG_INFO;
919 pstr = (where & SSL_CB_READ) ? "read" : "write";
920 if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
922 if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
923 log_level = COAP_LOG_WARN;
924 }
925 /* Need to let CoAP logging know why this session is dying */
926 coap_log(log_level, "* %s: SSL3 alert %s:%s:%s\n",
927 coap_session_str(session),
928 pstr,
929 SSL_alert_type_string_long(ret),
930 SSL_alert_desc_string_long(ret));
931 } else if (where & SSL_CB_EXIT) {
932 if (ret == 0) {
934 unsigned long e;
935 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:failed in %s\n",
936 coap_session_str(session), pstr, SSL_state_string_long(ssl));
937 while ((e = ERR_get_error()))
938 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
939 coap_session_str(session), ERR_reason_error_string(e),
940 ssl_function_definition(e));
941 }
942 } else if (ret < 0) {
944 int err = SSL_get_error(ssl, ret);
945 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
946 err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
947 err != SSL_ERROR_WANT_X509_LOOKUP) {
948 long e;
949 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:error in %s\n",
950 coap_session_str(session), pstr, SSL_state_string_long(ssl));
951 while ((e = ERR_get_error()))
952 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
953 coap_session_str(session), ERR_reason_error_string(e),
954 ssl_function_definition(e));
955 }
956 }
957 }
958 }
959
960 if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
962}
963
964#if !COAP_DISABLE_TCP
965static int
966coap_sock_create(BIO *a) {
967 BIO_set_init(a, 1);
968 return 1;
969}
970
971static int
972coap_sock_destroy(BIO *a) {
973 (void)a;
974 return 1;
975}
976
977/*
978 * strm
979 * return +ve data amount
980 * 0 no more
981 * -1 error
982 */
983static int
984coap_sock_read(BIO *a, char *out, int outl) {
985 int ret = 0;
986 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
987
988 if (out != NULL) {
989 ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (uint8_t *)out,
990 outl);
991 /* Translate layer returns into what OpenSSL expects */
992 if (ret == 0) {
993 BIO_set_retry_read(a);
994 ret = -1;
995 } else {
996 BIO_clear_retry_flags(a);
997 }
998 }
999 return ret;
1000}
1001
1002/*
1003 * strm
1004 * return +ve data amount
1005 * 0 no more
1006 * -1 error (error in errno)
1007 */
1008static int
1009coap_sock_write(BIO *a, const char *in, int inl) {
1010 int ret = 0;
1011 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1012
1013 ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
1014 (const uint8_t *)in,
1015 inl);
1016 /* Translate layer what returns into what OpenSSL expects */
1017 BIO_clear_retry_flags(a);
1018 if (ret == 0) {
1019 BIO_set_retry_read(a);
1020 ret = -1;
1021 } else {
1022 BIO_clear_retry_flags(a);
1023 if (ret == -1) {
1024 if ((session->state == COAP_SESSION_STATE_CSM ||
1025 session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1026 (errno == EPIPE || errno == ECONNRESET)) {
1027 /*
1028 * Need to handle a TCP timing window where an agent continues with
1029 * the sending of the next handshake or a CSM.
1030 * However, the peer does not like a certificate and so sends a
1031 * fatal alert and closes the TCP session.
1032 * The sending of the next handshake or CSM may get terminated because
1033 * of the closed TCP session, but there is still an outstanding alert
1034 * to be read in and reported on.
1035 * In this case, pretend that sending the info was fine so that the
1036 * alert can be read (which effectively is what happens with DTLS).
1037 */
1038 ret = inl;
1039 }
1040 }
1041 }
1042 return ret;
1043}
1044
1045static int
1046coap_sock_puts(BIO *a, const char *pstr) {
1047 return coap_sock_write(a, pstr, (int)strlen(pstr));
1048}
1049
1050static long
1051coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
1052 int r = 1;
1053 (void)a;
1054 (void)ptr;
1055 (void)num;
1056
1057 switch (cmd) {
1058 case BIO_C_SET_FD:
1059 case BIO_C_GET_FD:
1060 r = -1;
1061 break;
1062 case BIO_CTRL_SET_CLOSE:
1063 case BIO_CTRL_DUP:
1064 case BIO_CTRL_FLUSH:
1065 r = 1;
1066 break;
1067 default:
1068 case BIO_CTRL_GET_CLOSE:
1069 r = 0;
1070 break;
1071 }
1072 return r;
1073}
1074#endif /* !COAP_DISABLE_TCP */
1075
1076static void
1077coap_set_user_prefs(SSL_CTX *ctx) {
1078 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
1079
1080#ifdef COAP_OPENSSL_SIGALGS
1081 SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1082 SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1083#endif
1084
1085#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1086 SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1087#endif
1088}
1089
1090#if COAP_DTLS_RETRANSMIT_MS != 1000
1091#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1092static unsigned int
1093timer_cb(SSL *s, unsigned int timer_us) {
1094 (void)s;
1095 if (timer_us == 0)
1096 return COAP_DTLS_RETRANSMIT_MS * 1000;
1097 else
1098 return 2 * timer_us;
1099}
1100#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1101#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
1102
1103void *
1105 coap_openssl_context_t *context;
1106 (void)coap_context;
1107
1108 context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
1109 if (context) {
1110 uint8_t cookie_secret[32];
1111
1112 memset(context, 0, sizeof(coap_openssl_context_t));
1113
1114 /* Set up DTLS context */
1115 context->dtls.ctx = SSL_CTX_new(DTLS_method());
1116 if (!context->dtls.ctx)
1117 goto error;
1118 SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1119 SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1120 SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1121 coap_set_user_prefs(context->dtls.ctx);
1122 memset(cookie_secret, 0, sizeof(cookie_secret));
1123 if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
1125 "Insufficient entropy for random cookie generation");
1126 coap_prng_lkd(cookie_secret, sizeof(cookie_secret));
1127 }
1128 context->dtls.cookie_hmac = HMAC_CTX_new();
1129 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1130 EVP_sha256(), NULL))
1131 goto error;
1132 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1133 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1134 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1135 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1136#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1137 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1138#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1139 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1140 if (!context->dtls.meth)
1141 goto error;
1142 context->dtls.bio_addr = BIO_ADDR_new();
1143 if (!context->dtls.bio_addr)
1144 goto error;
1145 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1146 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1147 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1148 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1149 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1150 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1151
1152#if !COAP_DISABLE_TCP
1153 /* Set up TLS context */
1154 context->tls.ctx = SSL_CTX_new(TLS_method());
1155 if (!context->tls.ctx)
1156 goto error;
1157 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1158 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1159 coap_set_user_prefs(context->tls.ctx);
1160 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1161 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1162 if (!context->tls.meth)
1163 goto error;
1164 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1165 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1166 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1167 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1168 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1169 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1170#endif /* !COAP_DISABLE_TCP */
1171 }
1172
1173 return context;
1174
1175error:
1176 coap_dtls_free_context(context);
1177 return NULL;
1178}
1179
1180#if COAP_SERVER_SUPPORT
1181int
1183 coap_dtls_spsk_t *setup_data
1184 ) {
1185 coap_openssl_context_t *o_context =
1186 ((coap_openssl_context_t *)c_context->dtls_context);
1187 BIO *bio;
1188
1189 if (!setup_data || !o_context)
1190 return 0;
1191
1192 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1193 coap_dtls_psk_server_callback);
1194#if !COAP_DISABLE_TCP
1195 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1196 coap_dtls_psk_server_callback);
1197#endif /* !COAP_DISABLE_TCP */
1198 if (setup_data->psk_info.hint.s) {
1199 char hint[COAP_DTLS_HINT_LENGTH];
1200 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1201 setup_data->psk_info.hint.s);
1202 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1203#if !COAP_DISABLE_TCP
1204 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1205#endif /* !COAP_DISABLE_TCP */
1206 }
1207 if (setup_data->validate_sni_call_back) {
1208#if OPENSSL_VERSION_NUMBER < 0x10101000L
1209 SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1210 &c_context->spsk_setup_data);
1211 SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1212 psk_tls_server_name_call_back);
1213#if !COAP_DISABLE_TCP
1214 SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1215 &c_context->spsk_setup_data);
1216 SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1217 psk_tls_server_name_call_back);
1218#endif /* !COAP_DISABLE_TCP */
1219#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1220 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1221 psk_tls_client_hello_call_back,
1222 NULL);
1223#if !COAP_DISABLE_TCP
1224 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1225 psk_tls_client_hello_call_back,
1226 NULL);
1227#endif /* !COAP_DISABLE_TCP */
1228#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1229 }
1230
1231 if (!o_context->dtls.ssl) {
1232 /* This is set up to handle new incoming sessions to a server */
1233 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1234 if (!o_context->dtls.ssl)
1235 return 0;
1236 bio = BIO_new(o_context->dtls.meth);
1237 if (!bio) {
1238 SSL_free(o_context->dtls.ssl);
1239 o_context->dtls.ssl = NULL;
1240 return 0;
1241 }
1242 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1243 SSL_set_app_data(o_context->dtls.ssl, NULL);
1244 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1245 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1246 }
1247 if (setup_data->ec_jpake) {
1248 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1249 }
1250 o_context->psk_pki_enabled |= IS_PSK;
1251 return 1;
1252}
1253#endif /* COAP_SERVER_SUPPORT */
1254
1255#if COAP_CLIENT_SUPPORT
1256int
1258 coap_dtls_cpsk_t *setup_data
1259 ) {
1260 coap_openssl_context_t *o_context =
1261 ((coap_openssl_context_t *)c_context->dtls_context);
1262 BIO *bio;
1263
1264 if (!setup_data || !o_context)
1265 return 0;
1266
1267 if (!o_context->dtls.ssl) {
1268 /* This is set up to handle new incoming sessions to a server */
1269 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1270 if (!o_context->dtls.ssl)
1271 return 0;
1272 bio = BIO_new(o_context->dtls.meth);
1273 if (!bio) {
1274 SSL_free(o_context->dtls.ssl);
1275 o_context->dtls.ssl = NULL;
1276 return 0;
1277 }
1278 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1279 SSL_set_app_data(o_context->dtls.ssl, NULL);
1280 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1281 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1282 }
1283 if (setup_data->ec_jpake) {
1284 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1285 }
1286 if (setup_data->use_cid) {
1287 coap_log_warn("OpenSSL has no Connection-ID support\n");
1288 }
1289 o_context->psk_pki_enabled |= IS_PSK;
1290 return 1;
1291}
1292#endif /* COAP_CLIENT_SUPPORT */
1293
1294static int
1295map_key_type(int asn1_private_key_type
1296 ) {
1297 switch (asn1_private_key_type) {
1299 return EVP_PKEY_NONE;
1300 case COAP_ASN1_PKEY_RSA:
1301 return EVP_PKEY_RSA;
1303 return EVP_PKEY_RSA2;
1304 case COAP_ASN1_PKEY_DSA:
1305 return EVP_PKEY_DSA;
1307 return EVP_PKEY_DSA1;
1309 return EVP_PKEY_DSA2;
1311 return EVP_PKEY_DSA3;
1313 return EVP_PKEY_DSA4;
1314 case COAP_ASN1_PKEY_DH:
1315 return EVP_PKEY_DH;
1316 case COAP_ASN1_PKEY_DHX:
1317 return EVP_PKEY_DHX;
1318 case COAP_ASN1_PKEY_EC:
1319 return EVP_PKEY_EC;
1321 return EVP_PKEY_HMAC;
1323 return EVP_PKEY_CMAC;
1325 return EVP_PKEY_TLS1_PRF;
1327 return EVP_PKEY_HKDF;
1328 default:
1329 coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1330 asn1_private_key_type);
1331 break;
1332 }
1333 return 0;
1334}
1335#if !COAP_DISABLE_TCP
1336static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1337
1338#if COAP_SERVER_SUPPORT
1339static int
1340server_alpn_callback(SSL *ssl COAP_UNUSED,
1341 const unsigned char **out,
1342 unsigned char *outlen,
1343 const unsigned char *in,
1344 unsigned int inlen,
1345 void *arg COAP_UNUSED
1346 ) {
1347 unsigned char *tout = NULL;
1348 int ret;
1349 if (inlen == 0)
1350 return SSL_TLSEXT_ERR_NOACK;
1351 ret = SSL_select_next_proto(&tout,
1352 outlen,
1353 coap_alpn,
1354 sizeof(coap_alpn),
1355 in,
1356 inlen);
1357 *out = tout;
1358 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1359}
1360#endif /* COAP_SERVER_SUPPORT */
1361#endif /* !COAP_DISABLE_TCP */
1362
1363static void
1364add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1365 long e;
1366
1367 /* Flush out existing errors */
1368 while (ERR_get_error() != 0) {
1369 }
1370
1371 if (!X509_STORE_add_cert(st, x509)) {
1372 while ((e = ERR_get_error()) != 0) {
1373 int r = ERR_GET_REASON(e);
1374 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1375 /* Not already added */
1376 coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1377 ERR_reason_error_string(e),
1378 ssl_function_definition(e));
1379 }
1380 }
1381 }
1382}
1383
1384static X509 *
1385missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1386 struct {
1387 const char *cert_id;
1388 X509 *cert;
1389 } params;
1390
1391 params.cert_id = cert_id;
1392 params.cert = NULL;
1393
1394 /* There is no ENGINE_load_cert() */
1395 if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1396 params.cert = NULL;
1397 }
1398 return params.cert;
1399}
1400
1401static int
1402check_pkcs11_engine(void) {
1403 static int already_tried = 0;
1404
1405 if (already_tried)
1406 return 0;
1407
1408 if (!pkcs11_engine) {
1409 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1410 if (!pkcs11_engine) {
1411 coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1412 COAP_OPENSSL_PKCS11_ENGINE_ID);
1413 already_tried = 1;
1414 return 0;
1415 }
1416 if (!ENGINE_init(pkcs11_engine)) {
1417 /* the engine couldn't initialise, release 'pkcs11_engine' */
1418 ENGINE_free(pkcs11_engine);
1419 pkcs11_engine = NULL;
1420 coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1421 already_tried = 1;
1422 return 0;
1423 }
1424 /*
1425 * ENGINE_init() returned a functional reference, so free the structural
1426 * reference from ENGINE_by_id().
1427 */
1428 ENGINE_free(pkcs11_engine);
1429 }
1430 return 1;
1431}
1432
1433#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1434
1435static int
1436install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1437 const char *public_cert) {
1438 X509 *x509;
1439
1440 x509 = missing_ENGINE_load_cert(engine, public_cert);
1441 if (!x509) {
1442 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1443 "%s Certificate\n",
1444 public_cert,
1445 "Server");
1446 return 0;
1447 }
1448 if (!SSL_CTX_use_certificate(ctx, x509)) {
1449 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1450 "%s Certificate\n",
1451 public_cert,
1452 "Server");
1453 X509_free(x509);
1454 return 0;
1455 }
1456 X509_free(x509);
1457 return 1;
1458}
1459
1460static int
1461install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1462 const char *private_key) {
1463 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1464 private_key,
1465 NULL, NULL);
1466
1467 if (!pkey) {
1468 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1469 "%s Private Key\n",
1470 private_key,
1471 "Server");
1472 return 0;
1473 }
1474 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1475 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1476 "%s Private Key\n",
1477 private_key,
1478 "Server");
1479 EVP_PKEY_free(pkey);
1480 return 0;
1481 }
1482 EVP_PKEY_free(pkey);
1483 return 1;
1484}
1485
1486static int
1487install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1488 X509 *x509;
1489 X509_STORE *st;
1490
1491 x509 = missing_ENGINE_load_cert(engine,
1492 ca);
1493 if (!x509) {
1494 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1495 "%s CA Certificate\n",
1496 ca,
1497 "Server");
1498 return 0;
1499 }
1500 if (!SSL_CTX_add_client_CA(ctx, x509)) {
1501 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1502 "%s CA Certificate\n",
1503 ca,
1504 "Server");
1505 X509_free(x509);
1506 return 0;
1507 }
1508 st = SSL_CTX_get_cert_store(ctx);
1509 add_ca_to_cert_store(st, x509);
1510 X509_free(x509);
1511 return 1;
1512}
1513
1514static int
1515load_in_cas_ctx(SSL_CTX *ctx,
1516 const char *ca_file) {
1517 STACK_OF(X509_NAME) *cert_names;
1518 X509_STORE *st;
1519 BIO *in;
1520 X509 *x = NULL;
1521 char *rw_var = NULL;
1522 cert_names = SSL_load_client_CA_file(ca_file);
1523 if (cert_names != NULL)
1524 SSL_CTX_set_client_CA_list(ctx, cert_names);
1525 else {
1526 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1527 "client CA File\n",
1528 ca_file);
1529 return 0;
1530 }
1531
1532 /* Add CA to the trusted root CA store */
1533 st = SSL_CTX_get_cert_store(ctx);
1534 in = BIO_new(BIO_s_file());
1535 /* Need to do this to not get a compiler warning about const parameters */
1536 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1537 if (!BIO_read_filename(in, rw_var)) {
1538 BIO_free(in);
1539 X509_free(x);
1540 return 0;
1541 }
1542
1543 for (;;) {
1544 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1545 break;
1546 add_ca_to_cert_store(st, x);
1547 X509_free(x);
1548 }
1549 BIO_free(in);
1550 return 1;
1551}
1552
1553static int
1554setup_pki_server(SSL_CTX *ctx,
1555 const coap_dtls_pki_t *setup_data) {
1556 coap_dtls_key_t key;
1557
1558 /* Map over to the new define format to save code duplication */
1559 coap_dtls_map_key_type_to_define(setup_data, &key);
1560
1561 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1562
1563 /*
1564 * Configure the Private Key
1565 */
1566 if (key.key.define.private_key.u_byte &&
1567 key.key.define.private_key.u_byte[0]) {
1568 switch (key.key.define.private_key_def) {
1569 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1570 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1572 SSL_FILETYPE_PEM))) {
1575 &key, COAP_DTLS_ROLE_SERVER, 0);
1576 }
1577 break;
1578 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1579 if (key.key.define.private_key_len) {
1580 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1581 (int)key.key.define.private_key_len);
1582 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1583
1584 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1585 if (bp)
1586 BIO_free(bp);
1587 if (pkey)
1588 EVP_PKEY_free(pkey);
1591 &key, COAP_DTLS_ROLE_SERVER, 0);
1592 }
1593 if (bp)
1594 BIO_free(bp);
1595 if (pkey)
1596 EVP_PKEY_free(pkey);
1597 } else {
1600 &key, COAP_DTLS_ROLE_SERVER, 0);
1601 }
1602 break;
1603 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1606 &key, COAP_DTLS_ROLE_SERVER, 0);
1607 case COAP_PKI_KEY_DEF_DER: /* define private key */
1608 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1610 SSL_FILETYPE_ASN1))) {
1613 &key, COAP_DTLS_ROLE_SERVER, 0);
1614 }
1615 break;
1616 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1617 if (key.key.define.private_key_len == 0 ||
1618 !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1619 ctx,
1621 (long)key.key.define.private_key_len))) {
1624 &key, COAP_DTLS_ROLE_SERVER, 0);
1625 }
1626 break;
1627 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1628 if (!check_pkcs11_engine()) {
1629 return 0;
1630 }
1631 if (key.key.define.user_pin) {
1632 /* If not set, pin-value may be held in pkcs11: URI */
1633 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1634 "PIN",
1635 key.key.define.user_pin, 0) == 0) {
1636 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1637 key.key.define.user_pin);
1638 return 0;
1639 }
1640 }
1641 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1645 &key, COAP_DTLS_ROLE_SERVER, 0);
1646 }
1647 break;
1648 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1649 if (!defined_engine ||
1650 !install_engine_private_key_ctx(defined_engine, ctx,
1654 &key, COAP_DTLS_ROLE_SERVER, 0);
1655 }
1656 break;
1657 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1658 default:
1661 &key, COAP_DTLS_ROLE_SERVER, 0);
1662 }
1663 } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1666 &key, COAP_DTLS_ROLE_SERVER, 0);
1667 }
1668
1669 /*
1670 * Configure the Public Certificate / Key
1671 * OpenSSL < 1.1.1 and Server
1672 */
1673 if (key.key.define.public_cert.u_byte &&
1674 key.key.define.public_cert.u_byte[0]) {
1675 switch (key.key.define.public_cert_def) {
1676 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1677 if (key.key.define.ca.u_byte &&
1678 key.key.define.ca.u_byte[0]) {
1679 if (!(SSL_CTX_use_certificate_file(ctx,
1681 SSL_FILETYPE_PEM))) {
1684 &key, COAP_DTLS_ROLE_SERVER, 0);
1685 }
1686 } else {
1687 if (!SSL_CTX_use_certificate_chain_file(ctx,
1691 &key, COAP_DTLS_ROLE_SERVER, 0);
1692 }
1693 }
1694 break;
1695 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1696 if (key.key.define.public_cert_len) {
1697 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1698 (int)key.key.define.public_cert_len);
1699 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1700
1701 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1702 if (bp)
1703 BIO_free(bp);
1704 if (cert)
1705 X509_free(cert);
1708 &key, COAP_DTLS_ROLE_SERVER, 0);
1709 }
1710 if (bp)
1711 BIO_free(bp);
1712 if (cert)
1713 X509_free(cert);
1714 } else {
1717 &key, COAP_DTLS_ROLE_SERVER, 0);
1718 }
1719 break;
1720 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1723 &key, COAP_DTLS_ROLE_SERVER, 0);
1724 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1725 if (!(SSL_CTX_use_certificate_file(ctx,
1727 SSL_FILETYPE_ASN1))) {
1730 &key, COAP_DTLS_ROLE_SERVER, 0);
1731 }
1732 break;
1733 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1734 if (key.key.define.public_cert_len == 0 ||
1735 !(SSL_CTX_use_certificate_ASN1(ctx,
1736 (int)key.key.define.public_cert_len,
1737 key.key.define.public_cert.u_byte))) {
1740 &key, COAP_DTLS_ROLE_SERVER, 0);
1741 }
1742 break;
1743 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1744 if (!check_pkcs11_engine()) {
1745 return 0;
1746 }
1747 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1751 &key, COAP_DTLS_ROLE_SERVER, 0);
1752 }
1753 break;
1754 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1755 if (!defined_engine ||
1756 !install_engine_public_cert_ctx(defined_engine, ctx,
1760 &key, COAP_DTLS_ROLE_SERVER, 0);
1761 }
1762 break;
1763 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1764 default:
1767 &key, COAP_DTLS_ROLE_SERVER, 0);
1768 }
1769 } else if (key.key.define.private_key.u_byte &&
1770 key.key.define.private_key.u_byte[0]) {
1773 &key, COAP_DTLS_ROLE_SERVER, 0);
1774 }
1775
1776 /*
1777 * Configure the CA
1778 */
1779 if (key.key.define.ca.u_byte &&
1780 key.key.define.ca.u_byte[0]) {
1781 switch (key.key.define.ca_def) {
1783 if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1786 &key, COAP_DTLS_ROLE_SERVER, 0);
1787 }
1788 break;
1789 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1790 if (key.key.define.ca_len) {
1791 BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1792 (int)key.key.define.ca_len);
1793 X509 *x;
1794 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1795
1796 if (bp) {
1797 for (;;) {
1798 if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1799 break;
1800 add_ca_to_cert_store(st, x);
1801 SSL_CTX_add_client_CA(ctx, x);
1802 X509_free(x);
1803 }
1804 BIO_free(bp);
1805 }
1806 } else {
1809 &key, COAP_DTLS_ROLE_SERVER, 0);
1810 }
1811 break;
1812 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1815 &key, COAP_DTLS_ROLE_SERVER, 0);
1816 case COAP_PKI_KEY_DEF_DER: /* define ca */
1817 if (!(SSL_CTX_use_certificate_file(ctx,
1818 key.key.define.ca.s_byte,
1819 SSL_FILETYPE_ASN1))) {
1822 &key, COAP_DTLS_ROLE_SERVER, 0);
1823 }
1824 break;
1825 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1826 if (key.key.define.ca_len > 0) {
1827 /* Need to use a temp variable as it gets incremented*/
1828 const uint8_t *p = key.key.define.ca.u_byte;
1829 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1830 X509_STORE *st;
1831
1832 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1833 X509_free(x509);
1836 &key, COAP_DTLS_ROLE_SERVER, 0);
1837 }
1838
1839 /* Add CA to the trusted root CA store */
1840 st = SSL_CTX_get_cert_store(ctx);
1841 add_ca_to_cert_store(st, x509);
1842 X509_free(x509);
1843 }
1844 break;
1845 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1846 if (!check_pkcs11_engine()) {
1847 return 0;
1848 }
1849 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1850 key.key.define.ca.s_byte)) {
1853 &key, COAP_DTLS_ROLE_SERVER, 0);
1854 }
1855 break;
1856 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1857 if (!defined_engine ||
1858 !install_engine_ca_ctx(defined_engine, ctx,
1859 key.key.define.ca.s_byte)) {
1862 &key, COAP_DTLS_ROLE_SERVER, 0);
1863 }
1864 break;
1865 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1866 default:
1869 &key, COAP_DTLS_ROLE_SERVER, 0);
1870 }
1871 }
1872
1873 return 1;
1874}
1875#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1876
1877#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1878
1879static int
1880install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1881 coap_dtls_role_t role) {
1882 X509 *x509;
1883
1884 x509 = missing_ENGINE_load_cert(engine, public_cert);
1885 if (!x509) {
1886 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1887 "%s Certificate\n",
1888 public_cert,
1889 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1890 return 0;
1891 }
1892 if (!SSL_use_certificate(ssl, x509)) {
1893 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1894 "%s Certificate\n",
1895 public_cert,
1896 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1897 X509_free(x509);
1898 return 0;
1899 }
1900 X509_free(x509);
1901 return 1;
1902}
1903
1904static int
1905install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1906 coap_dtls_role_t role) {
1907 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1908 private_key,
1909 NULL, NULL);
1910
1911 if (!pkey) {
1912 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1913 "%s Private Key\n",
1914 private_key,
1915 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1916 return 0;
1917 }
1918 if (!SSL_use_PrivateKey(ssl, pkey)) {
1919 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1920 "%s Private Key\n",
1921 private_key,
1922 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1923 EVP_PKEY_free(pkey);
1924 return 0;
1925 }
1926 EVP_PKEY_free(pkey);
1927 return 1;
1928}
1929
1930static int
1931install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1932 coap_dtls_role_t role) {
1933 X509 *x509;
1934 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1935 X509_STORE *st;
1936
1937 x509 = missing_ENGINE_load_cert(engine,
1938 ca);
1939 if (!x509) {
1940 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1941 "%s CA Certificate\n",
1942 ca,
1943 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1944 return 0;
1945 }
1946 if (!SSL_add_client_CA(ssl, x509)) {
1947 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1948 "%s CA Certificate\n",
1949 ca,
1950 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1951 X509_free(x509);
1952 return 0;
1953 }
1954 st = SSL_CTX_get_cert_store(ctx);
1955 add_ca_to_cert_store(st, x509);
1956 X509_free(x509);
1957 return 1;
1958}
1959
1960static int
1961load_in_cas(SSL *ssl,
1962 const char *ca_file, coap_dtls_role_t role) {
1963 X509_STORE *st;
1964 BIO *in;
1965 X509 *x = NULL;
1966 char *rw_var = NULL;
1967 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1968
1969 if (role == COAP_DTLS_ROLE_SERVER) {
1970 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
1971
1972 if (cert_names != NULL)
1973 SSL_set_client_CA_list(ssl, cert_names);
1974 else {
1975 return 0;
1976 }
1977 }
1978
1979 /* Add CA to the trusted root CA store */
1980 in = BIO_new(BIO_s_file());
1981 /* Need to do this to not get a compiler warning about const parameters */
1982 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1983 if (!BIO_read_filename(in, rw_var)) {
1984 BIO_free(in);
1985 return 0;
1986 }
1987 st = SSL_CTX_get_cert_store(ctx);
1988 for (;;) {
1989 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1990 break;
1991 add_ca_to_cert_store(st, x);
1992 X509_free(x);
1993 }
1994 BIO_free(in);
1995 return 1;
1996}
1997
1998static int
1999setup_pki_ssl(SSL *ssl,
2000 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
2001 coap_dtls_key_t key;
2002
2003 /* Map over to the new define format to save code duplication */
2004 coap_dtls_map_key_type_to_define(setup_data, &key);
2005
2006 assert(key.key_type == COAP_PKI_KEY_DEFINE);
2007
2008 /*
2009 * Configure the Private Key
2010 */
2011 if (key.key.define.private_key.u_byte &&
2012 key.key.define.private_key.u_byte[0]) {
2013 switch (key.key.define.private_key_def) {
2014 case COAP_PKI_KEY_DEF_PEM: /* define private key */
2015 if (!(SSL_use_PrivateKey_file(ssl,
2017 SSL_FILETYPE_PEM))) {
2020 &key, role, 0);
2021 }
2022 break;
2023 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2024 if (key.key.define.private_key_len) {
2025 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2026 (int)key.key.define.private_key_len);
2027 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2028
2029 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2030 if (bp)
2031 BIO_free(bp);
2032 if (pkey)
2033 EVP_PKEY_free(pkey);
2036 &key, role, 0);
2037 }
2038 if (bp)
2039 BIO_free(bp);
2040 if (pkey)
2041 EVP_PKEY_free(pkey);
2042 } else {
2045 &key, role, 0);
2046 }
2047 break;
2048 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2051 &key, role, 0);
2052 case COAP_PKI_KEY_DEF_DER: /* define private key */
2053 if (!(SSL_use_PrivateKey_file(ssl,
2055 SSL_FILETYPE_ASN1))) {
2058 &key, role, 0);
2059 }
2060 break;
2061 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2062 if (key.key.define.private_key_len == 0 ||
2063 !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2064 ssl,
2066 (long)key.key.define.private_key_len))) {
2069 &key, role, 0);
2070 }
2071 break;
2072 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2073 if (!check_pkcs11_engine()) {
2074 return 0;
2075 }
2076 if (key.key.define.user_pin) {
2077 /* If not set, pin-value may be held in pkcs11: URI */
2078 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2079 "PIN",
2080 key.key.define.user_pin, 0) == 0) {
2081 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2082 key.key.define.user_pin);
2083 return 0;
2084 }
2085 }
2086 if (!install_engine_private_key(pkcs11_engine, ssl,
2088 role)) {
2091 &key, role, 0);
2092 }
2093 break;
2094 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2095 if (!defined_engine ||
2096 !install_engine_private_key(defined_engine, ssl,
2098 role)) {
2101 &key, role, 0);
2102 }
2103 break;
2104 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2105 default:
2108 &key, role, 0);
2109 }
2110 } else if (role == COAP_DTLS_ROLE_SERVER ||
2112 key.key.define.public_cert.u_byte[0])) {
2115 &key, role, 0);
2116 }
2117
2118 /*
2119 * Configure the Public Certificate / Key
2120 */
2121 if (key.key.define.public_cert.u_byte &&
2122 key.key.define.public_cert.u_byte[0]) {
2123 switch (key.key.define.public_cert_def) {
2124 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2125 if (key.key.define.ca.u_byte &&
2126 key.key.define.ca.u_byte[0]) {
2127 /* If CA is separately defined */
2128 if (!(SSL_use_certificate_file(ssl,
2130 SSL_FILETYPE_PEM))) {
2133 &key, role, 0);
2134 }
2135 } else {
2136 if (!SSL_use_certificate_chain_file(ssl,
2140 &key, role, 0);
2141 }
2142 }
2143 break;
2144 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2145 if (key.key.define.public_cert_len) {
2146 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2147 (int)key.key.define.public_cert_len);
2148 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2149
2150 if (!cert || !SSL_use_certificate(ssl, cert)) {
2151 if (bp)
2152 BIO_free(bp);
2153 if (cert)
2154 X509_free(cert);
2157 &key, role, 0);
2158 }
2159 if (bp)
2160 BIO_free(bp);
2161 if (cert)
2162 X509_free(cert);
2163 } else {
2166 &key, role, 0);
2167 }
2168 break;
2169 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2172 &key, role, 0);
2173 case COAP_PKI_KEY_DEF_DER: /* define public cert */
2174 if (!(SSL_use_certificate_file(ssl,
2176 SSL_FILETYPE_ASN1))) {
2179 &key, role, 0);
2180 }
2181 break;
2182 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2183 if (key.key.define.public_cert_len == 0 ||
2184 !(SSL_use_certificate_ASN1(ssl,
2186 (int)key.key.define.public_cert_len))) {
2189 &key, role, 0);
2190 }
2191 break;
2192 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2193 if (!check_pkcs11_engine()) {
2194 return 0;
2195 }
2196 if (!install_engine_public_cert(pkcs11_engine, ssl,
2198 role)) {
2201 &key, role, 0);
2202 }
2203 break;
2204 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2205 if (!defined_engine ||
2206 !install_engine_public_cert(defined_engine, ssl,
2208 role)) {
2211 &key, role, 0);
2212 }
2213 break;
2214 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2215 default:
2218 &key, role, 0);
2219 }
2220 } else if (role == COAP_DTLS_ROLE_SERVER ||
2222 key.key.define.private_key.u_byte[0])) {
2225 &key, role, 0);
2226 }
2227
2228 /*
2229 * Configure the CA
2230 */
2231 if (key.key.define.ca.u_byte &&
2232 key.key.define.ca.u_byte[0]) {
2233 switch (key.key.define.ca_def) {
2235 if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2238 &key, role, 0);
2239 }
2240 break;
2241 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2242 if (key.key.define.ca_len) {
2243 BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2244 (int)key.key.define.ca_len);
2245 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2246 X509 *x;
2247 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
2248
2249 if (bp) {
2250 for (;;) {
2251 if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2252 break;
2253 add_ca_to_cert_store(st, x);
2254 SSL_add_client_CA(ssl, x);
2255 X509_free(x);
2256 }
2257 BIO_free(bp);
2258 }
2259 } else {
2262 &key, role, 0);
2263 }
2264 break;
2265 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2268 &key, role, 0);
2269 case COAP_PKI_KEY_DEF_DER: /* define ca */
2270 if (!(SSL_use_certificate_file(ssl,
2271 key.key.define.ca.s_byte,
2272 SSL_FILETYPE_ASN1))) {
2275 &key, role, 0);
2276 }
2277 break;
2278 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2279 if (key.key.define.ca_len > 0) {
2280 /* Need to use a temp variable as it gets incremented*/
2281 const uint8_t *p = key.key.define.ca.u_byte;
2282 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2283 X509_STORE *st;
2284 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2285
2286 if (role == COAP_DTLS_ROLE_SERVER) {
2287 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2288 X509_free(x509);
2291 &key, role, 0);
2292 }
2293 }
2294
2295 /* Add CA to the trusted root CA store */
2296 st = SSL_CTX_get_cert_store(ctx);
2297 add_ca_to_cert_store(st, x509);
2298 X509_free(x509);
2299 }
2300 break;
2301 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2302 if (!check_pkcs11_engine()) {
2303 return 0;
2304 }
2305 if (!install_engine_ca(pkcs11_engine, ssl,
2306 key.key.define.ca.s_byte,
2307 role)) {
2310 &key, role, 0);
2311 }
2312 break;
2313 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2314 if (!defined_engine ||
2315 !install_engine_ca(defined_engine, ssl,
2316 key.key.define.ca.s_byte,
2317 role)) {
2320 &key, role, 0);
2321 }
2322 break;
2323 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2324 default:
2327 &key, role, 0);
2328 }
2329 }
2330
2331 return 1;
2332}
2333#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2334
2335static char *
2336get_san_or_cn_from_cert(X509 *x509) {
2337 if (x509) {
2338 char *cn;
2339 int n;
2340 STACK_OF(GENERAL_NAME) *san_list;
2341 char buffer[256];
2342
2343 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2344 if (san_list) {
2345 int san_count = sk_GENERAL_NAME_num(san_list);
2346
2347 for (n = 0; n < san_count; n++) {
2348 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2349
2350 if (name->type == GEN_DNS) {
2351 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2352
2353 /* Make sure that there is not an embedded NUL in the dns_name */
2354 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2355 continue;
2356 cn = OPENSSL_strdup(dns_name);
2357 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2358 return cn;
2359 }
2360 }
2361 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2362 }
2363 /* Otherwise look for the CN= field */
2364 X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2365
2366 /* Need to emulate strcasestr() here. Looking for CN= */
2367 n = (int)strlen(buffer) - 3;
2368 cn = buffer;
2369 while (n > 0) {
2370 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2371 ((cn[1] == 'N') || (cn[1] == 'n')) &&
2372 (cn[2] == '=')) {
2373 cn += 3;
2374 break;
2375 }
2376 cn++;
2377 n--;
2378 }
2379 if (n > 0) {
2380 char *ecn = strchr(cn, '/');
2381 if (ecn) {
2382 return OPENSSL_strndup(cn, ecn-cn);
2383 } else {
2384 return OPENSSL_strdup(cn);
2385 }
2386 }
2387 }
2388 return NULL;
2389}
2390
2391static int
2392tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2393 SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
2394 SSL_get_ex_data_X509_STORE_CTX_idx());
2395 coap_session_t *session = SSL_get_app_data(ssl);
2396 coap_openssl_context_t *context =
2397 ((coap_openssl_context_t *)session->context->dtls_context);
2398 coap_dtls_pki_t *setup_data = &context->setup_data;
2399 int depth = X509_STORE_CTX_get_error_depth(ctx);
2400 int err = X509_STORE_CTX_get_error(ctx);
2401 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2402 char *cn = get_san_or_cn_from_cert(x509);
2403 int keep_preverify_ok = preverify_ok;
2404
2405 coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2406 depth, err, preverify_ok, cn);
2407 if (!preverify_ok) {
2408 switch (err) {
2409 case X509_V_ERR_CERT_NOT_YET_VALID:
2410 case X509_V_ERR_CERT_HAS_EXPIRED:
2411 if (setup_data->allow_expired_certs)
2412 preverify_ok = 1;
2413 break;
2414 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2415 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2416 preverify_ok = 1;
2417 break;
2418 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2419 if (!setup_data->verify_peer_cert)
2420 preverify_ok = 1;
2421 break;
2422 case X509_V_ERR_UNABLE_TO_GET_CRL:
2423 if (setup_data->allow_no_crl)
2424 preverify_ok = 1;
2425 break;
2426 case X509_V_ERR_CRL_NOT_YET_VALID:
2427 case X509_V_ERR_CRL_HAS_EXPIRED:
2428 if (setup_data->allow_expired_crl)
2429 preverify_ok = 1;
2430 break;
2431 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2432 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2433 case X509_V_ERR_AKID_SKID_MISMATCH:
2434 if (!setup_data->verify_peer_cert)
2435 preverify_ok = 1;
2436 break;
2437 default:
2438 break;
2439 }
2440 if (setup_data->cert_chain_validation &&
2441 depth > (setup_data->cert_chain_verify_depth + 1)) {
2442 preverify_ok = 0;
2443 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2444 X509_STORE_CTX_set_error(ctx, err);
2445 }
2446 if (!preverify_ok) {
2447 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2448 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2449 coap_session_str(session),
2450 "Unknown CA", cn ? cn : "?", depth);
2451 } else {
2452 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2453 coap_session_str(session),
2454 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2455 }
2456 } else {
2457 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
2458 coap_session_str(session),
2459 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2460 }
2461 }
2462 /* Certificate - depth == 0 is the Client Cert */
2463 if (setup_data->validate_cn_call_back && keep_preverify_ok) {
2464 int length = i2d_X509(x509, NULL);
2465 uint8_t *base_buf;
2466 uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
2467 int ret;
2468
2469 /* base_buf2 gets moved to the end */
2470 i2d_X509(x509, &base_buf2);
2471 coap_lock_callback_ret(ret, session->context,
2472 setup_data->validate_cn_call_back(cn, base_buf, length, session,
2473 depth, preverify_ok,
2474 setup_data->cn_call_back_arg));
2475 if (!ret) {
2476 if (depth == 0) {
2477 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2478 } else {
2479 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2480 }
2481 preverify_ok = 0;
2482 }
2483 OPENSSL_free(base_buf);
2484 }
2485 OPENSSL_free(cn);
2486 return preverify_ok;
2487}
2488
2489#if COAP_SERVER_SUPPORT
2490#if OPENSSL_VERSION_NUMBER < 0x10101000L
2491/* OpenSSL < 1.1.1 */
2492/*
2493 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2494 * it is possible to determine whether this is a PKI or PSK incoming
2495 * request and adjust the ciphers if necessary
2496 *
2497 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2498 */
2499static int
2500tls_secret_call_back(SSL *ssl,
2501 void *secret,
2502 int *secretlen,
2503 STACK_OF(SSL_CIPHER) *peer_ciphers,
2504 const SSL_CIPHER **cipher COAP_UNUSED,
2505 void *arg) {
2506 int ii;
2507 int psk_requested = 0;
2508 coap_session_t *session;
2509 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2510
2511 session = (coap_session_t *)SSL_get_app_data(ssl);
2512 assert(session != NULL);
2513 assert(session->context != NULL);
2514 if (session == NULL ||
2515 session->context == NULL)
2516 return 0;
2517
2518 if ((session->psk_key) ||
2519 (session->context->spsk_setup_data.psk_info.key.s &&
2521 /* Is PSK being requested - if so, we need to change algorithms */
2522 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2523 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2524
2525 coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2526 SSL_CIPHER_get_name(peer_cipher));
2527 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2528 psk_requested = 1;
2529 break;
2530 }
2531 }
2532 }
2533 if (!psk_requested) {
2534 coap_log_debug(" %s: Using PKI ciphers\n",
2535 coap_session_str(session));
2536
2537 if (setup_data->verify_peer_cert) {
2538 SSL_set_verify(ssl,
2539 SSL_VERIFY_PEER |
2540 SSL_VERIFY_CLIENT_ONCE |
2541 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2542 tls_verify_call_back);
2543 } else {
2544 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2545 }
2546
2547 /* Check CA Chain */
2548 if (setup_data->cert_chain_validation)
2549 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2550
2551 /* Certificate Revocation */
2552 if (setup_data->check_cert_revocation) {
2553 X509_VERIFY_PARAM *param;
2554
2555 param = X509_VERIFY_PARAM_new();
2556 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2557 SSL_set1_param(ssl, param);
2558 X509_VERIFY_PARAM_free(param);
2559 }
2560 if (setup_data->additional_tls_setup_call_back) {
2561 /* Additional application setup wanted */
2562 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2563 return 0;
2564 }
2565 } else {
2566 if (session->psk_key) {
2567 memcpy(secret, session->psk_key->s, session->psk_key->length);
2568 *secretlen = session->psk_key->length;
2569 } else if (session->context->spsk_setup_data.psk_info.key.s &&
2571 memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2573 *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2574 }
2575 coap_log_debug(" %s: Setting PSK ciphers\n",
2576 coap_session_str(session));
2577 /*
2578 * Force a PSK algorithm to be used, so we do PSK
2579 */
2580 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2581 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2582 }
2583 return 0;
2584}
2585
2586/* OpenSSL < 1.1.1 */
2587/*
2588 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2589 * called so it is possible to set up an extra callback to determine whether
2590 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2591 *
2592 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2593 * coap_dtls_context_set_pki()
2594 */
2595static int
2596tls_server_name_call_back(SSL *ssl,
2597 int *sd COAP_UNUSED,
2598 void *arg) {
2599 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2600
2601 if (!ssl) {
2602 return SSL_TLSEXT_ERR_NOACK;
2603 }
2604
2605 if (setup_data->validate_sni_call_back) {
2606 /* SNI checking requested */
2607 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2608 coap_openssl_context_t *context =
2609 ((coap_openssl_context_t *)session->context->dtls_context);
2610 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2611 size_t i;
2612
2613 if (!sni || !sni[0]) {
2614 sni = "";
2615 }
2616 for (i = 0; i < context->sni_count; i++) {
2617 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2618 break;
2619 }
2620 }
2621 if (i == context->sni_count) {
2622 SSL_CTX *ctx;
2623 coap_dtls_pki_t sni_setup_data;
2624 coap_dtls_key_t *new_entry;
2625
2626 coap_lock_callback_ret(new_entry, session->context,
2627 setup_data->validate_sni_call_back(sni,
2628 setup_data->sni_call_back_arg));
2629 if (!new_entry) {
2630 return SSL_TLSEXT_ERR_ALERT_FATAL;
2631 }
2632 /* Need to set up a new SSL_CTX to switch to */
2633 if (session->proto == COAP_PROTO_DTLS) {
2634 /* Set up DTLS context */
2635 ctx = SSL_CTX_new(DTLS_method());
2636 if (!ctx)
2637 goto error;
2638 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2639 SSL_CTX_set_app_data(ctx, &context->dtls);
2640 SSL_CTX_set_read_ahead(ctx, 1);
2641 coap_set_user_prefs(ctx);
2642 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2643 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2644 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2645 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2646 }
2647#if !COAP_DISABLE_TCP
2648 else {
2649 /* Set up TLS context */
2650 ctx = SSL_CTX_new(TLS_method());
2651 if (!ctx)
2652 goto error;
2653 SSL_CTX_set_app_data(ctx, &context->tls);
2654 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2655 coap_set_user_prefs(ctx);
2656 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2657 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2658 }
2659#endif /* !COAP_DISABLE_TCP */
2660 sni_setup_data = *setup_data;
2661 sni_setup_data.pki_key = *new_entry;
2662 setup_pki_server(ctx, &sni_setup_data);
2663
2664 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2665 (context->sni_count+1)*sizeof(sni_entry));
2666 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2667 context->sni_entry_list[context->sni_count].ctx = ctx;
2668 context->sni_count++;
2669 }
2670 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2671 SSL_clear_options(ssl, 0xFFFFFFFFL);
2672 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2673 }
2674
2675 /*
2676 * Have to do extra call back next to get client algorithms
2677 * SSL_get_client_ciphers() does not work this early on
2678 */
2679 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2680 return SSL_TLSEXT_ERR_OK;
2681
2682error:
2683 return SSL_TLSEXT_ERR_ALERT_WARNING;
2684}
2685
2686/* OpenSSL < 1.1.1 */
2687/*
2688 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2689 * called to see if SNI is being used.
2690 *
2691 * Set up by SSL_CTX_set_tlsext_servername_callback()
2692 * in coap_dtls_context_set_spsk()
2693 */
2694static int
2695psk_tls_server_name_call_back(SSL *ssl,
2696 int *sd COAP_UNUSED,
2697 void *arg
2698 ) {
2699 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2700
2701 if (!ssl) {
2702 return SSL_TLSEXT_ERR_NOACK;
2703 }
2704
2705 if (setup_data->validate_sni_call_back) {
2706 /* SNI checking requested */
2707 coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2708 coap_openssl_context_t *o_context =
2709 ((coap_openssl_context_t *)c_session->context->dtls_context);
2710 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2711 size_t i;
2712 char lhint[COAP_DTLS_HINT_LENGTH];
2713
2714 if (!sni || !sni[0]) {
2715 sni = "";
2716 }
2717 for (i = 0; i < o_context->psk_sni_count; i++) {
2718 if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2719 break;
2720 }
2721 }
2722 if (i == o_context->psk_sni_count) {
2723 SSL_CTX *ctx;
2724 const coap_dtls_spsk_info_t *new_entry;
2725
2726 coap_lock_callback_ret(new_entry, c_session->context,
2727 setup_data->validate_sni_call_back(sni,
2728 c_session,
2729 setup_data->sni_call_back_arg));
2730 if (!new_entry) {
2731 return SSL_TLSEXT_ERR_ALERT_FATAL;
2732 }
2733 /* Need to set up a new SSL_CTX to switch to */
2734 if (c_session->proto == COAP_PROTO_DTLS) {
2735 /* Set up DTLS context */
2736 ctx = SSL_CTX_new(DTLS_method());
2737 if (!ctx)
2738 goto error;
2739 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2740 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2741 SSL_CTX_set_read_ahead(ctx, 1);
2742 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2743 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2744 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2745 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2746 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2747 }
2748#if !COAP_DISABLE_TCP
2749 else {
2750 /* Set up TLS context */
2751 ctx = SSL_CTX_new(TLS_method());
2752 if (!ctx)
2753 goto error;
2754 SSL_CTX_set_app_data(ctx, &o_context->tls);
2755 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2756 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2757 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2758 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2759 }
2760#endif /* !COAP_DISABLE_TCP */
2761
2762 o_context->psk_sni_entry_list =
2763 OPENSSL_realloc(o_context->psk_sni_entry_list,
2764 (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2765 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2766 OPENSSL_strdup(sni);
2767 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2768 *new_entry;
2769 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2770 ctx;
2771 o_context->psk_sni_count++;
2772 }
2773 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2774 SSL_clear_options(ssl, 0xFFFFFFFFL);
2775 SSL_set_options(ssl,
2776 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2778 &o_context->psk_sni_entry_list[i].psk_info.key);
2779 snprintf(lhint, sizeof(lhint), "%.*s",
2780 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2781 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2782 SSL_use_psk_identity_hint(ssl, lhint);
2783 }
2784
2785 /*
2786 * Have to do extra call back next to get client algorithms
2787 * SSL_get_client_ciphers() does not work this early on
2788 */
2789 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2790 return SSL_TLSEXT_ERR_OK;
2791
2792error:
2793 return SSL_TLSEXT_ERR_ALERT_WARNING;
2794}
2795#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2796/* OpenSSL >= 1.1.1 */
2797/*
2798 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2799 * called early in the Client Hello processing so it is possible to determine
2800 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2801 * necessary.
2802 *
2803 * Set up by SSL_CTX_set_client_hello_cb().
2804 */
2805static int
2806tls_client_hello_call_back(SSL *ssl,
2807 int *al,
2808 void *arg COAP_UNUSED
2809 ) {
2810 coap_session_t *session;
2811 coap_openssl_context_t *dtls_context;
2812 coap_dtls_pki_t *setup_data;
2813 int psk_requested = 0;
2814 const unsigned char *out;
2815 size_t outlen;
2816
2817 if (!ssl) {
2818 *al = SSL_AD_INTERNAL_ERROR;
2819 return SSL_CLIENT_HELLO_ERROR;
2820 }
2821 session = (coap_session_t *)SSL_get_app_data(ssl);
2822 assert(session != NULL);
2823 assert(session->context != NULL);
2824 assert(session->context->dtls_context != NULL);
2825 if (session == NULL ||
2826 session->context == NULL ||
2827 session->context->dtls_context == NULL) {
2828 *al = SSL_AD_INTERNAL_ERROR;
2829 return SSL_CLIENT_HELLO_ERROR;
2830 }
2831 dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2832 setup_data = &dtls_context->setup_data;
2833
2834 /*
2835 * See if PSK being requested
2836 */
2837 if ((session->psk_key) ||
2838 (session->context->spsk_setup_data.psk_info.key.s &&
2840 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2841 STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2842 STACK_OF(SSL_CIPHER) *scsvc = NULL;
2843
2844 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2845 SSL_client_hello_isv2(ssl),
2846 &peer_ciphers, &scsvc)) {
2847 int ii;
2848 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2849 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2850
2852 "Client cipher: %s (%04x)\n",
2853 SSL_CIPHER_get_name(peer_cipher),
2854 SSL_CIPHER_get_protocol_id(peer_cipher));
2855 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2856 psk_requested = 1;
2857 break;
2858 }
2859 }
2860 }
2861 sk_SSL_CIPHER_free(peer_ciphers);
2862 sk_SSL_CIPHER_free(scsvc);
2863 }
2864
2865 if (psk_requested) {
2866 /*
2867 * Client has requested PSK and it is supported
2868 */
2869 coap_log_debug(" %s: PSK request\n",
2870 coap_session_str(session));
2871 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2872 if (setup_data->additional_tls_setup_call_back) {
2873 /* Additional application setup wanted */
2874 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2875 return 0;
2876 }
2877 return SSL_CLIENT_HELLO_SUCCESS;
2878 }
2879
2880 /*
2881 * Handle Certificate requests
2882 */
2883
2884 /*
2885 * Determine what type of certificate is being requested
2886 */
2887 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
2888 &out, &outlen)) {
2889 size_t ii;
2890 for (ii = 0; ii < outlen; ii++) {
2891 switch (out[ii]) {
2892 case 0:
2893 /* RFC6091 X.509 */
2894 if (outlen >= 2) {
2895 /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
2896 goto is_x509;
2897 }
2898 break;
2899 case 2:
2900 /* RFC7250 RPK - not yet supported */
2901 break;
2902 default:
2903 break;
2904 }
2905 }
2906 *al = SSL_AD_UNSUPPORTED_EXTENSION;
2907 return SSL_CLIENT_HELLO_ERROR;
2908 }
2909
2910is_x509:
2911 if (setup_data->validate_sni_call_back) {
2912 /*
2913 * SNI checking requested
2914 */
2915 coap_dtls_pki_t sni_setup_data;
2916 coap_openssl_context_t *context =
2917 ((coap_openssl_context_t *)session->context->dtls_context);
2918 const char *sni = "";
2919 char *sni_tmp = NULL;
2920 size_t i;
2921
2922 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2923 outlen > 5 &&
2924 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2925 out[2] == TLSEXT_NAMETYPE_host_name &&
2926 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2927 /* Skip over length, type and length */
2928 out += 5;
2929 outlen -= 5;
2930 sni_tmp = OPENSSL_malloc(outlen+1);
2931 sni_tmp[outlen] = '\000';
2932 memcpy(sni_tmp, out, outlen);
2933 sni = sni_tmp;
2934 }
2935 /* Is this a cached entry? */
2936 for (i = 0; i < context->sni_count; i++) {
2937 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2938 break;
2939 }
2940 }
2941 if (i == context->sni_count) {
2942 /*
2943 * New SNI request
2944 */
2945 coap_dtls_key_t *new_entry;
2946
2947 coap_lock_callback_ret(new_entry, session->context,
2948 setup_data->validate_sni_call_back(sni,
2949 setup_data->sni_call_back_arg));
2950 if (!new_entry) {
2951 *al = SSL_AD_UNRECOGNIZED_NAME;
2952 return SSL_CLIENT_HELLO_ERROR;
2953 }
2954
2955
2956 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2957 (context->sni_count+1)*sizeof(sni_entry));
2958 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2959 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
2960 context->sni_count++;
2961 }
2962 if (sni_tmp) {
2963 OPENSSL_free(sni_tmp);
2964 }
2965 sni_setup_data = *setup_data;
2966 sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
2967 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
2968 } else {
2969 setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
2970 }
2971
2972 coap_log_debug(" %s: Using PKI ciphers\n",
2973 coap_session_str(session));
2974
2975 if (setup_data->verify_peer_cert) {
2976 SSL_set_verify(ssl,
2977 SSL_VERIFY_PEER |
2978 SSL_VERIFY_CLIENT_ONCE |
2979 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2980 tls_verify_call_back);
2981 } else {
2982 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2983 }
2984
2985 /* Check CA Chain */
2986 if (setup_data->cert_chain_validation)
2987 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2988
2989 /* Certificate Revocation */
2990 if (setup_data->check_cert_revocation) {
2991 X509_VERIFY_PARAM *param;
2992
2993 param = X509_VERIFY_PARAM_new();
2994 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2995 SSL_set1_param(ssl, param);
2996 X509_VERIFY_PARAM_free(param);
2997 }
2998 if (setup_data->additional_tls_setup_call_back) {
2999 /* Additional application setup wanted */
3000 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3001 return 0;
3002 }
3003 return SSL_CLIENT_HELLO_SUCCESS;
3004}
3005
3006/* OpenSSL >= 1.1.1 */
3007/*
3008 * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is
3009 * called early in the Client Hello processing so it is possible to determine
3010 * whether SNI needs to be handled
3011 *
3012 * Set up by SSL_CTX_set_client_hello_cb().
3013 */
3014static int
3015psk_tls_client_hello_call_back(SSL *ssl,
3016 int *al,
3017 void *arg COAP_UNUSED
3018 ) {
3019 coap_session_t *c_session;
3020 coap_openssl_context_t *o_context;
3021 coap_dtls_spsk_t *setup_data;
3022 const unsigned char *out;
3023 size_t outlen;
3024
3025 if (!ssl)
3026 goto int_err;
3027 c_session = (coap_session_t *)SSL_get_app_data(ssl);
3028 if (!c_session || !c_session->context) {
3029 goto int_err;
3030 }
3031 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
3032 if (!o_context) {
3033 goto int_err;
3034 }
3035 setup_data = &c_session->context->spsk_setup_data;
3036
3037 if (setup_data->validate_sni_call_back) {
3038 /*
3039 * SNI checking requested
3040 */
3041 const char *sni = "";
3042 char *sni_tmp = NULL;
3043 char lhint[COAP_DTLS_HINT_LENGTH];
3044
3045 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3046 outlen > 5 &&
3047 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3048 out[2] == TLSEXT_NAMETYPE_host_name &&
3049 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3050 /* Skip over length, type and length */
3051 out += 5;
3052 outlen -= 5;
3053 sni_tmp = OPENSSL_malloc(outlen+1);
3054 if (sni_tmp) {
3055 sni_tmp[outlen] = '\000';
3056 memcpy(sni_tmp, out, outlen);
3057 sni = sni_tmp;
3058 }
3059 }
3060
3061#if OPENSSL_VERSION_NUMBER < 0x10101000L
3062 size_t i;
3063 /* Is this a cached entry? */
3064 for (i = 0; i < o_context->psk_sni_count; i++) {
3065 if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) {
3066 break;
3067 }
3068 }
3069 if (i == o_context->psk_sni_count) {
3070#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3071 /*
3072 * New SNI request
3073 */
3074 const coap_dtls_spsk_info_t *new_entry;
3075
3076 coap_lock_callback_ret(new_entry, c_session->context,
3077 setup_data->validate_sni_call_back(
3078 sni,
3079 c_session,
3080 setup_data->sni_call_back_arg));
3081 if (!new_entry) {
3082 *al = SSL_AD_UNRECOGNIZED_NAME;
3083 return SSL_CLIENT_HELLO_ERROR;
3084 }
3085
3086#if OPENSSL_VERSION_NUMBER < 0x10101000L
3087 psk_sni_entry *tmp_entry;
3088 tmp_entry =
3089 OPENSSL_realloc(o_context->psk_sni_entry_list,
3090 (o_context->psk_sni_count+1)*sizeof(sni_entry));
3091 if (tmp_entry) {
3092 o_context->psk_sni_entry_list = tmp_entry;
3093 o_context->psk_sni_entry_list[o_context->psk_sni_count]
3094 .sni =
3095 OPENSSL_strdup(sni);
3096 if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) {
3097 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
3098 *new_entry;
3099 o_context->psk_sni_count++;
3100 }
3101 }
3102 } else {
3103 new_entry = &o_context->psk_sni_entry_list[i].psk_info;
3104 }
3105#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3106
3107 if (sni_tmp) {
3108 OPENSSL_free(sni_tmp);
3109 }
3110 if (coap_session_refresh_psk_hint(c_session,
3111 &new_entry->hint)
3112 == 0) {
3113 goto int_err;
3114 }
3115 if (coap_session_refresh_psk_key(c_session,
3116 &new_entry->key)
3117 == 0) {
3118 goto int_err;
3119 }
3120 if (new_entry->hint.s) {
3121 snprintf(lhint, sizeof(lhint), "%.*s",
3122 (int)new_entry->hint.length,
3123 new_entry->hint.s);
3124 SSL_use_psk_identity_hint(ssl, lhint);
3125 }
3126 }
3127 return SSL_CLIENT_HELLO_SUCCESS;
3128
3129int_err:
3130 *al = SSL_AD_INTERNAL_ERROR;
3131 return SSL_CLIENT_HELLO_ERROR;
3132}
3133#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3134#endif /* COAP_SERVER_SUPPORT */
3135
3136int
3138 const coap_dtls_pki_t *setup_data,
3139 const coap_dtls_role_t role) {
3140 coap_openssl_context_t *context =
3141 ((coap_openssl_context_t *)ctx->dtls_context);
3142 BIO *bio;
3143 if (!setup_data)
3144 return 0;
3145 context->setup_data = *setup_data;
3146
3147 if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3148 if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3149 context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3150 context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3151 if (!defined_engine) {
3152 coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3153 return 0;
3154 }
3155 }
3156 }
3157
3158 if (!context->setup_data.verify_peer_cert) {
3159 /* Needs to be clear so that no CA DNs are transmitted */
3160 context->setup_data.check_common_ca = 0;
3161 /* Allow all of these but warn if issue */
3162 context->setup_data.allow_self_signed = 1;
3163 context->setup_data.allow_expired_certs = 1;
3164 context->setup_data.cert_chain_validation = 1;
3165 context->setup_data.cert_chain_verify_depth = 10;
3166 context->setup_data.check_cert_revocation = 1;
3167 context->setup_data.allow_no_crl = 1;
3168 context->setup_data.allow_expired_crl = 1;
3169 context->setup_data.allow_bad_md_hash = 1;
3170 context->setup_data.allow_short_rsa_length = 1;
3171 }
3172#if COAP_SERVER_SUPPORT
3173 if (role == COAP_DTLS_ROLE_SERVER) {
3174 if (context->dtls.ctx) {
3175 /* SERVER DTLS */
3176#if OPENSSL_VERSION_NUMBER < 0x10101000L
3177 if (!setup_pki_server(context->dtls.ctx, setup_data))
3178 return 0;
3179#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3180 /* libcoap is managing TLS connection based on setup_data options */
3181 /* Need to set up logic to differentiate between a PSK or PKI session */
3182 /*
3183 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3184 * which is not in 1.1.0
3185 */
3186#if OPENSSL_VERSION_NUMBER < 0x10101000L
3187 if (SSLeay() >= 0x10101000L) {
3188 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3189 "no certificate checking\n",
3190 OPENSSL_VERSION_NUMBER, SSLeay());
3191 }
3192 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3193 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3194 tls_server_name_call_back);
3195#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3196 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3197 tls_client_hello_call_back,
3198 NULL);
3199#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3200 }
3201#if !COAP_DISABLE_TCP
3202 if (context->tls.ctx) {
3203 /* SERVER TLS */
3204#if OPENSSL_VERSION_NUMBER < 0x10101000L
3205 if (!setup_pki_server(context->tls.ctx, setup_data))
3206 return 0;
3207#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3208 /* libcoap is managing TLS connection based on setup_data options */
3209 /* Need to set up logic to differentiate between a PSK or PKI session */
3210 /*
3211 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3212 * which is not in 1.1.0
3213 */
3214#if OPENSSL_VERSION_NUMBER < 0x10101000L
3215 if (SSLeay() >= 0x10101000L) {
3216 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3217 "no certificate checking\n",
3218 OPENSSL_VERSION_NUMBER, SSLeay());
3219 }
3220 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3221 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3222 tls_server_name_call_back);
3223#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3224 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3225 tls_client_hello_call_back,
3226 NULL);
3227#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3228 /* TLS Only */
3229 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3230 }
3231#endif /* !COAP_DISABLE_TCP */
3232 }
3233#else /* ! COAP_SERVER_SUPPORT */
3234 (void)role;
3235#endif /* ! COAP_SERVER_SUPPORT */
3236
3237 if (!context->dtls.ssl) {
3238 /* This is set up to handle new incoming sessions to a server */
3239 context->dtls.ssl = SSL_new(context->dtls.ctx);
3240 if (!context->dtls.ssl)
3241 return 0;
3242 bio = BIO_new(context->dtls.meth);
3243 if (!bio) {
3244 SSL_free(context->dtls.ssl);
3245 context->dtls.ssl = NULL;
3246 return 0;
3247 }
3248 SSL_set_bio(context->dtls.ssl, bio, bio);
3249 SSL_set_app_data(context->dtls.ssl, NULL);
3250 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3251 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3252 }
3253 context->psk_pki_enabled |= IS_PKI;
3254 if (setup_data->use_cid) {
3255 coap_log_warn("OpenSSL has no Connection-ID support\n");
3256 }
3257 return 1;
3258}
3259
3260int
3262 const char *ca_file,
3263 const char *ca_dir
3264 ) {
3265 coap_openssl_context_t *context =
3266 ((coap_openssl_context_t *)ctx->dtls_context);
3267 if (context->dtls.ctx) {
3268 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3269 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3270 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3271 return 0;
3272 }
3273 }
3274#if !COAP_DISABLE_TCP
3275 if (context->tls.ctx) {
3276 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3277 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3278 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3279 return 0;
3280 }
3281 }
3282#endif /* !COAP_DISABLE_TCP */
3283 return 1;
3284}
3285
3286int
3288#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3289 coap_openssl_context_t *context =
3290 ((coap_openssl_context_t *)ctx->dtls_context);
3291 if (context->dtls.ctx) {
3292 if (!SSL_CTX_set_default_verify_store(context->dtls.ctx)) {
3293 coap_log_warn("Unable to load trusted root CAs\n");
3294 return 0;
3295 }
3296 }
3297#if !COAP_DISABLE_TCP
3298 if (context->tls.ctx) {
3299 if (!SSL_CTX_set_default_verify_store(context->tls.ctx)) {
3300 coap_log_warn("Unable to load trusted root CAs\n");
3301 return 0;
3302 }
3303 }
3304#endif /* !COAP_DISABLE_TCP */
3305 return 1;
3306#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3307 (void)ctx;
3308 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3309 "not supported for OpenSSL < v3.0.0\n");
3310 return 0;
3311#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3312}
3313
3314int
3316 coap_openssl_context_t *context =
3317 ((coap_openssl_context_t *)ctx->dtls_context);
3318 return context->psk_pki_enabled ? 1 : 0;
3319}
3320
3321
3322void
3323coap_dtls_free_context(void *handle) {
3324 size_t i;
3325 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3326
3327 if (context->dtls.ssl)
3328 SSL_free(context->dtls.ssl);
3329 if (context->dtls.ctx)
3330 SSL_CTX_free(context->dtls.ctx);
3331 if (context->dtls.cookie_hmac)
3332 HMAC_CTX_free(context->dtls.cookie_hmac);
3333 if (context->dtls.meth)
3334 BIO_meth_free(context->dtls.meth);
3335 if (context->dtls.bio_addr)
3336 BIO_ADDR_free(context->dtls.bio_addr);
3337#if !COAP_DISABLE_TCP
3338 if (context->tls.ctx)
3339 SSL_CTX_free(context->tls.ctx);
3340 if (context->tls.meth)
3341 BIO_meth_free(context->tls.meth);
3342#endif /* !COAP_DISABLE_TCP */
3343 for (i = 0; i < context->sni_count; i++) {
3344 OPENSSL_free(context->sni_entry_list[i].sni);
3345#if OPENSSL_VERSION_NUMBER < 0x10101000L
3346 SSL_CTX_free(context->sni_entry_list[i].ctx);
3347#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3348 }
3349 if (context->sni_count)
3350 OPENSSL_free(context->sni_entry_list);
3351#if OPENSSL_VERSION_NUMBER < 0x10101000L
3352 for (i = 0; i < context->psk_sni_count; i++) {
3353 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3354 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3355 }
3356 if (context->psk_sni_count)
3357 OPENSSL_free(context->psk_sni_entry_list);
3358#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3359 coap_free_type(COAP_STRING, context);
3360}
3361
3362#if COAP_SERVER_SUPPORT
3363void *
3365 BIO *nbio = NULL;
3366 SSL *nssl = NULL, *ssl = NULL;
3367 coap_ssl_data *data;
3368 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3369 int r;
3370 const coap_bin_const_t *psk_hint;
3371
3372 nssl = SSL_new(dtls->ctx);
3373 if (!nssl)
3374 goto error;
3375 nbio = BIO_new(dtls->meth);
3376 if (!nbio)
3377 goto error;
3378 SSL_set_bio(nssl, nbio, nbio);
3379 SSL_set_app_data(nssl, NULL);
3380 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3381 SSL_set_mtu(nssl, (long)session->mtu);
3382 ssl = dtls->ssl;
3383 dtls->ssl = nssl;
3384 nssl = NULL;
3385 SSL_set_app_data(ssl, session);
3386
3387 data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3388 data->session = session;
3389
3390 /* hint may get updated if/when handling SNI callback */
3391 psk_hint = coap_get_session_server_psk_hint(session);
3392 if (psk_hint != NULL && psk_hint->length) {
3393 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3394
3395 if (hint) {
3396 memcpy(hint, psk_hint->s, psk_hint->length);
3397 hint[psk_hint->length] = '\000';
3398 SSL_use_psk_identity_hint(ssl, hint);
3399 OPENSSL_free(hint);
3400 } else {
3401 coap_log_warn("hint malloc failure\n");
3402 }
3403 }
3404
3405 r = SSL_accept(ssl);
3406 if (r == -1) {
3407 int err = SSL_get_error(ssl, r);
3408 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3409 r = 0;
3410 }
3411
3412 if (r == 0) {
3413 SSL_free(ssl);
3414 return NULL;
3415 }
3416
3417 return ssl;
3418
3419error:
3420 if (nssl)
3421 SSL_free(nssl);
3422 return NULL;
3423}
3424#endif /* COAP_SERVER_SUPPORT */
3425
3426#if COAP_CLIENT_SUPPORT
3427static int
3428setup_client_ssl_session(coap_session_t *session, SSL *ssl
3429 ) {
3430 coap_openssl_context_t *context =
3431 ((coap_openssl_context_t *)session->context->dtls_context);
3432
3433 if (context->psk_pki_enabled & IS_PSK) {
3434 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3435
3436 /* Issue SNI if requested */
3437 if (setup_data->client_sni &&
3438 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3439 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3440 setup_data->client_sni);
3441 }
3442 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3443#if COAP_SERVER_SUPPORT
3444 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3445#endif /* COAP_SERVER_SUPPORT */
3446 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3447 if (setup_data->validate_ih_call_back) {
3448 if (session->proto == COAP_PROTO_DTLS) {
3449 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3450 }
3451#if !COAP_DISABLE_TCP
3452 else {
3453 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3454 }
3455#endif /* !COAP_DISABLE_TCP */
3456 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3457 }
3458 }
3459 if ((context->psk_pki_enabled & IS_PKI) ||
3460 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3461 /*
3462 * If neither PSK or PKI have been set up, use PKI basics.
3463 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3464 */
3465 coap_dtls_pki_t *setup_data = &context->setup_data;
3466
3467 if (!(context->psk_pki_enabled & IS_PKI)) {
3468 /* PKI not defined - set up some defaults */
3469 setup_data->verify_peer_cert = 1;
3470 setup_data->check_common_ca = 0;
3471 setup_data->allow_self_signed = 1;
3472 setup_data->allow_expired_certs = 1;
3473 setup_data->cert_chain_validation = 1;
3474 setup_data->cert_chain_verify_depth = 2;
3475 setup_data->check_cert_revocation = 1;
3476 setup_data->allow_no_crl = 1;
3477 setup_data->allow_expired_crl = 1;
3478 setup_data->is_rpk_not_cert = 0;
3479 setup_data->use_cid = 0;
3480 }
3481 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3482 return 0;
3483 /* libcoap is managing (D)TLS connection based on setup_data options */
3484#if !COAP_DISABLE_TCP
3485 if (session->proto == COAP_PROTO_TLS)
3486 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3487#endif /* !COAP_DISABLE_TCP */
3488
3489 /* Issue SNI if requested */
3490 if (setup_data->client_sni &&
3491 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3492 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3493 setup_data->client_sni);
3494 }
3495 /* Certificate Revocation */
3496 if (setup_data->check_cert_revocation) {
3497 X509_VERIFY_PARAM *param;
3498
3499 param = X509_VERIFY_PARAM_new();
3500 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3501 SSL_set1_param(ssl, param);
3502 X509_VERIFY_PARAM_free(param);
3503 }
3504
3505 /* Verify Peer */
3506 if (setup_data->verify_peer_cert)
3507 SSL_set_verify(ssl,
3508 SSL_VERIFY_PEER |
3509 SSL_VERIFY_CLIENT_ONCE |
3510 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3511 tls_verify_call_back);
3512 else
3513 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3514
3515 /* Check CA Chain */
3516 if (setup_data->cert_chain_validation)
3517 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3518
3519 }
3520#if COAP_DTLS_RETRANSMIT_MS != 1000
3521#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3522 if (session->proto == COAP_PROTO_DTLS) {
3523 DTLS_set_timer_cb(ssl, timer_cb);
3524 }
3525#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3526#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3527 return 1;
3528}
3529
3530void *
3532 BIO *bio = NULL;
3533 SSL *ssl = NULL;
3534 coap_ssl_data *data;
3535 int r;
3536 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3537 coap_dtls_context_t *dtls = &context->dtls;
3538
3539 ssl = SSL_new(dtls->ctx);
3540 if (!ssl)
3541 goto error;
3542 bio = BIO_new(dtls->meth);
3543 if (!bio)
3544 goto error;
3545 data = (coap_ssl_data *)BIO_get_data(bio);
3546 data->session = session;
3547 SSL_set_bio(ssl, bio, bio);
3548 SSL_set_app_data(ssl, session);
3549 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3550 SSL_set_mtu(ssl, (long)session->mtu);
3551
3552 if (!setup_client_ssl_session(session, ssl))
3553 goto error;
3554
3555 session->dtls_timeout_count = 0;
3556
3557 r = SSL_connect(ssl);
3558 if (r == -1) {
3559 int ret = SSL_get_error(ssl, r);
3560 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3561 r = 0;
3562 }
3563
3564 if (r == 0)
3565 goto error;
3566
3567 session->tls = ssl;
3568 return ssl;
3569
3570error:
3571 if (ssl)
3572 SSL_free(ssl);
3573 return NULL;
3574}
3575
3576void
3578 SSL *ssl = (SSL *)session->tls;
3579 if (ssl)
3580 SSL_set_mtu(ssl, (long)session->mtu);
3581}
3582#endif /* COAP_CLIENT_SUPPORT */
3583
3584void
3586 SSL *ssl = (SSL *)session->tls;
3587 if (ssl) {
3588 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3589 int r = SSL_shutdown(ssl);
3590 if (r == 0)
3591 SSL_shutdown(ssl);
3592 }
3593 SSL_free(ssl);
3594 session->tls = NULL;
3595 if (session->context)
3597 }
3598}
3599
3600ssize_t
3602 const uint8_t *data, size_t data_len) {
3603 int r;
3604 SSL *ssl = (SSL *)session->tls;
3605
3606 if (ssl == NULL) {
3608 return -1;
3609 }
3610
3611 session->dtls_event = -1;
3612 ERR_clear_error();
3613 r = SSL_write(ssl, data, (int)data_len);
3614
3615 if (r <= 0) {
3616 int err = SSL_get_error(ssl, r);
3617 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3618 r = 0;
3619 } else {
3620 if (err == SSL_ERROR_ZERO_RETURN)
3622 else if (err == SSL_ERROR_SSL) {
3623 unsigned long e = ERR_get_error();
3624
3625 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3626 coap_session_str(session),
3627 ERR_GET_REASON(e), ERR_reason_error_string(e));
3629 } else {
3630 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3631 coap_session_str(session), err);
3632 }
3633 r = -1;
3634 }
3635 }
3636
3637 if (session->dtls_event >= 0) {
3638 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3639 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3640 coap_handle_event_lkd(session->context, session->dtls_event, session);
3641 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3642 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3644 r = -1;
3645 }
3646 }
3647
3648 if (r > 0) {
3649 if (r == (ssize_t)data_len)
3650 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3651 coap_session_str(session), r);
3652 else
3653 coap_log_debug("* %s: dtls: sent %4d of %4zd bytes\n",
3654 coap_session_str(session), r, data_len);
3655 }
3656 return r;
3657}
3658
3659int
3661 return 0;
3662}
3663
3665coap_dtls_get_context_timeout(void *dtls_context) {
3666 (void)dtls_context;
3667 return 0;
3668}
3669
3672 SSL *ssl = (SSL *)session->tls;
3673 coap_ssl_data *ssl_data;
3674
3675 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3676 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3677 return ssl_data->timeout;
3678}
3679
3680/*
3681 * return 1 timed out
3682 * 0 still timing out
3683 */
3684int
3686 SSL *ssl = (SSL *)session->tls;
3687
3688 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3689 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3690 (DTLSv1_handle_timeout(ssl) < 0)) {
3691 /* Too many retries */
3693 return 1;
3694 }
3695 return 0;
3696}
3697
3698#if COAP_SERVER_SUPPORT
3699int
3701 const uint8_t *data, size_t data_len) {
3702 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3703 coap_ssl_data *ssl_data;
3704 int r;
3705
3706 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3707 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(dtls->ssl));
3708 assert(ssl_data != NULL);
3709 if (ssl_data->pdu_len) {
3710 coap_log_err("** %s: Previous data not read %u bytes\n",
3711 coap_session_str(session), ssl_data->pdu_len);
3712 }
3713 ssl_data->session = session;
3714 ssl_data->pdu = data;
3715 ssl_data->pdu_len = (unsigned)data_len;
3716 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3717 if (r <= 0) {
3718 int err = SSL_get_error(dtls->ssl, r);
3719 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3720 /* Got a ClientHello, sent-out a VerifyRequest */
3721 r = 0;
3722 }
3723 } else {
3724 /* Got a valid answer to a VerifyRequest */
3725 r = 1;
3726 }
3727
3728 /*
3729 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3730 * only does a 'peek' read of the incoming data.
3731 *
3732 */
3733 return r;
3734}
3735#endif /* COAP_SERVER_SUPPORT */
3736
3737int
3738coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3739 coap_ssl_data *ssl_data;
3740 SSL *ssl = (SSL *)session->tls;
3741 int r;
3742#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3743 int retry = 0;
3744#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3745
3746 assert(ssl != NULL);
3747
3748 int in_init = SSL_in_init(ssl);
3749 uint8_t pdu[COAP_RXBUFFER_SIZE];
3750 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3751 assert(ssl_data != NULL);
3752
3753 if (ssl_data->pdu_len) {
3754 coap_log_err("** %s: Previous data not read %u bytes\n",
3755 coap_session_str(session), ssl_data->pdu_len);
3756 }
3757 ssl_data->pdu = data;
3758 ssl_data->pdu_len = (unsigned)data_len;
3759
3760 session->dtls_event = -1;
3761#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3762retry:
3763#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3764 ERR_clear_error();
3765 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3766 if (r > 0) {
3767 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3768 coap_session_str(session), r);
3769 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3770 goto finished;
3771 } else {
3772 int err = SSL_get_error(ssl, r);
3773 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3774 if (in_init && SSL_is_init_finished(ssl)) {
3775 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3776 coap_session_str(session), SSL_get_cipher_name(ssl));
3778 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3779 }
3780 r = 0;
3781 } else {
3782 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3784 else if (err == SSL_ERROR_SSL) {
3785 unsigned long e = ERR_get_error();
3786
3787#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3788#include <openssl/proverr.h>
3789 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3790 /* Loading trust store - first access causes a directory read error */
3791 retry = 1;
3792 goto retry;
3793 }
3794#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3795 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3796 coap_session_str(session),
3797 ERR_GET_REASON(e), ERR_reason_error_string(e));
3799 } else {
3800 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3801 coap_session_str(session), err);
3802 }
3803 r = -1;
3804 }
3805 if (session->dtls_event >= 0) {
3806 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3807 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3808 coap_handle_event_lkd(session->context, session->dtls_event, session);
3809 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3810 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3812 ssl_data = NULL;
3813 r = -1;
3814 }
3815 }
3816 }
3817
3818finished:
3819 if (ssl_data && ssl_data->pdu_len) {
3820 /* pdu data is held on stack which will not stay there */
3821 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3822 ssl_data->pdu_len = 0;
3823 ssl_data->pdu = NULL;
3824 }
3825 return r;
3826}
3827
3828unsigned int
3830 unsigned int overhead = 37;
3831 const SSL_CIPHER *s_ciph = NULL;
3832 if (session->tls != NULL)
3833 s_ciph = SSL_get_current_cipher(session->tls);
3834 if (s_ciph) {
3835 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3836
3837 const EVP_CIPHER *e_ciph;
3838 const EVP_MD *e_md;
3839 char cipher[128];
3840
3841 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3842
3843 switch (EVP_CIPHER_mode(e_ciph)) {
3844 case EVP_CIPH_GCM_MODE:
3845 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3846 maclen = EVP_GCM_TLS_TAG_LEN;
3847 break;
3848
3849 case EVP_CIPH_CCM_MODE:
3850 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3851 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3852 if (strstr(cipher, "CCM8"))
3853 maclen = 8;
3854 else
3855 maclen = 16;
3856 break;
3857
3858 case EVP_CIPH_CBC_MODE:
3859 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3860 blocksize = EVP_CIPHER_block_size(e_ciph);
3861 ivlen = EVP_CIPHER_iv_length(e_ciph);
3862 pad = 1;
3863 maclen = EVP_MD_size(e_md);
3864 break;
3865
3866 case EVP_CIPH_STREAM_CIPHER:
3867 /* Seen with PSK-CHACHA20-POLY1305 */
3868 ivlen = 8;
3869 maclen = 8;
3870 break;
3871
3872 default:
3873 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3874 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3875 cipher);
3876 ivlen = 8;
3877 maclen = 16;
3878 break;
3879 }
3880 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3881 }
3882 return overhead;
3883}
3884
3885#if !COAP_DISABLE_TCP
3886#if COAP_CLIENT_SUPPORT
3887void *
3889 BIO *bio = NULL;
3890 SSL *ssl = NULL;
3891 int r;
3892 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3893 coap_tls_context_t *tls = &context->tls;
3894
3895 ssl = SSL_new(tls->ctx);
3896 if (!ssl)
3897 goto error;
3898 bio = BIO_new(tls->meth);
3899 if (!bio)
3900 goto error;
3901 BIO_set_data(bio, session);
3902 SSL_set_bio(ssl, bio, bio);
3903 SSL_set_app_data(ssl, session);
3904
3905 if (!setup_client_ssl_session(session, ssl))
3906 return 0;
3907
3908 r = SSL_connect(ssl);
3909 if (r == -1) {
3910 int ret = SSL_get_error(ssl, r);
3911 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3912 r = 0;
3913 if (ret == SSL_ERROR_WANT_READ)
3914 session->sock.flags |= COAP_SOCKET_WANT_READ;
3915 if (ret == SSL_ERROR_WANT_WRITE) {
3916 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3917#ifdef COAP_EPOLL_SUPPORT
3918 coap_epoll_ctl_mod(&session->sock,
3919 EPOLLOUT |
3920 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3921 EPOLLIN : 0),
3922 __func__);
3923#endif /* COAP_EPOLL_SUPPORT */
3924 }
3925 }
3926
3927 if (r == 0)
3928 goto error;
3929
3930 session->tls = ssl;
3931 if (SSL_is_init_finished(ssl)) {
3933 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3934 }
3935
3936 return ssl;
3937
3938error:
3939 if (ssl)
3940 SSL_free(ssl);
3941 return NULL;
3942}
3943#endif /* COAP_CLIENT_SUPPORT */
3944
3945#if COAP_SERVER_SUPPORT
3946void *
3948 BIO *bio = NULL;
3949 SSL *ssl = NULL;
3950 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
3951 int r;
3952 const coap_bin_const_t *psk_hint;
3953
3954 ssl = SSL_new(tls->ctx);
3955 if (!ssl)
3956 goto error;
3957 bio = BIO_new(tls->meth);
3958 if (!bio)
3959 goto error;
3960 BIO_set_data(bio, session);
3961 SSL_set_bio(ssl, bio, bio);
3962 SSL_set_app_data(ssl, session);
3963
3964 psk_hint = coap_get_session_server_psk_hint(session);
3965 if (psk_hint != NULL && psk_hint->length) {
3966 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3967
3968 if (hint) {
3969 memcpy(hint, psk_hint->s, psk_hint->length);
3970 hint[psk_hint->length] = '\000';
3971 SSL_use_psk_identity_hint(ssl, hint);
3972 OPENSSL_free(hint);
3973 } else {
3974 coap_log_warn("hint malloc failure\n");
3975 }
3976 }
3977
3978 r = SSL_accept(ssl);
3979 if (r == -1) {
3980 int err = SSL_get_error(ssl, r);
3981 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3982 r = 0;
3983 if (err == SSL_ERROR_WANT_READ)
3984 session->sock.flags |= COAP_SOCKET_WANT_READ;
3985 if (err == SSL_ERROR_WANT_WRITE) {
3986 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3987#ifdef COAP_EPOLL_SUPPORT
3988 coap_epoll_ctl_mod(&session->sock,
3989 EPOLLOUT |
3990 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3991 EPOLLIN : 0),
3992 __func__);
3993#endif /* COAP_EPOLL_SUPPORT */
3994 }
3995 }
3996
3997 if (r == 0)
3998 goto error;
3999
4000 session->tls = ssl;
4001 if (SSL_is_init_finished(ssl)) {
4003 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4004 }
4005
4006#if COAP_DTLS_RETRANSMIT_MS != 1000
4007#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4008 if (session->proto == COAP_PROTO_DTLS) {
4009 DTLS_set_timer_cb(ssl, timer_cb);
4010 }
4011#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4012#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4013
4014 return ssl;
4015
4016error:
4017 if (ssl)
4018 SSL_free(ssl);
4019 return NULL;
4020}
4021#endif /* COAP_SERVER_SUPPORT */
4022
4023void
4025 SSL *ssl = (SSL *)session->tls;
4026 if (ssl) {
4027 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4028 int r = SSL_shutdown(ssl);
4029 if (r == 0)
4030 SSL_shutdown(ssl);
4031 }
4032 SSL_free(ssl);
4033 session->tls = NULL;
4034 if (session->context)
4036 }
4037}
4038
4039/*
4040 * strm
4041 * return +ve Number of bytes written.
4042 * -1 Error (error in errno).
4043 */
4044ssize_t
4045coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4046 SSL *ssl = (SSL *)session->tls;
4047 int r, in_init;
4048
4049 if (ssl == NULL)
4050 return -1;
4051
4052 in_init = !SSL_is_init_finished(ssl);
4053 session->dtls_event = -1;
4054 ERR_clear_error();
4055 r = SSL_write(ssl, data, (int)data_len);
4056
4057 if (r <= 0) {
4058 int err = SSL_get_error(ssl, r);
4059 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4060 if (in_init && SSL_is_init_finished(ssl)) {
4061 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4062 coap_session_str(session), SSL_get_cipher_name(ssl));
4064 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4065 }
4066 if (err == SSL_ERROR_WANT_READ)
4067 session->sock.flags |= COAP_SOCKET_WANT_READ;
4068 else if (err == SSL_ERROR_WANT_WRITE) {
4069 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4070#ifdef COAP_EPOLL_SUPPORT
4071 coap_epoll_ctl_mod(&session->sock,
4072 EPOLLOUT |
4073 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4074 EPOLLIN : 0),
4075 __func__);
4076#endif /* COAP_EPOLL_SUPPORT */
4077 }
4078 r = 0;
4079 } else {
4080 if (err == SSL_ERROR_ZERO_RETURN)
4082 else if (err == SSL_ERROR_SSL) {
4083 unsigned long e = ERR_get_error();
4084
4085 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4086 coap_session_str(session),
4087 ERR_GET_REASON(e), ERR_reason_error_string(e));
4089 } else {
4090 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4091 coap_session_str(session), err);
4092 }
4093 r = -1;
4094 }
4095 } else if (in_init && SSL_is_init_finished(ssl)) {
4096 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4097 coap_session_str(session), SSL_get_cipher_name(ssl));
4099 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4100 }
4101
4102 if (session->dtls_event >= 0) {
4103 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4104 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4105 coap_handle_event_lkd(session->context, session->dtls_event, session);
4106 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4107 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4109 r = -1;
4110 }
4111 }
4112
4113 if (r >= 0) {
4114 if (r == (ssize_t)data_len)
4115 coap_log_debug("* %s: tls: sent %4d bytes\n",
4116 coap_session_str(session), r);
4117 else
4118 coap_log_debug("* %s: tls: sent %4d of %4zd bytes\n",
4119 coap_session_str(session), r, data_len);
4120 }
4121 return r;
4122}
4123
4124/*
4125 * strm
4126 * return >=0 Number of bytes read.
4127 * -1 Error (error in errno).
4128 */
4129ssize_t
4130coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4131 SSL *ssl = (SSL *)session->tls;
4132 int r, in_init;
4133
4134 if (ssl == NULL) {
4135 errno = ENXIO;
4136 return -1;
4137 }
4138
4139 in_init = !SSL_is_init_finished(ssl);
4140 session->dtls_event = -1;
4141 ERR_clear_error();
4142 r = SSL_read(ssl, data, (int)data_len);
4143 if (r <= 0) {
4144 int err = SSL_get_error(ssl, r);
4145 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4146 if (in_init && SSL_is_init_finished(ssl)) {
4147 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4148 coap_session_str(session), SSL_get_cipher_name(ssl));
4150 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4151 }
4152 if (err == SSL_ERROR_WANT_READ)
4153 session->sock.flags |= COAP_SOCKET_WANT_READ;
4154 if (err == SSL_ERROR_WANT_WRITE) {
4155 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4156#ifdef COAP_EPOLL_SUPPORT
4157 coap_epoll_ctl_mod(&session->sock,
4158 EPOLLOUT |
4159 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4160 EPOLLIN : 0),
4161 __func__);
4162#endif /* COAP_EPOLL_SUPPORT */
4163 }
4164 r = 0;
4165 } else {
4166 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4168 else if (err == SSL_ERROR_SSL) {
4169 unsigned long e = ERR_get_error();
4170
4171 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4172 coap_session_str(session),
4173 ERR_GET_REASON(e), ERR_reason_error_string(e));
4175 } else {
4176 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4177 coap_session_str(session), err);
4178 }
4179 r = -1;
4180 }
4181 } else if (in_init && SSL_is_init_finished(ssl)) {
4182 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4183 coap_session_str(session), SSL_get_cipher_name(ssl));
4185 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4186 }
4187
4188 if (session->dtls_event >= 0) {
4189 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4190 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4191 coap_handle_event_lkd(session->context, session->dtls_event, session);
4192 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4193 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4195 r = -1;
4196 }
4197 }
4198
4199 if (r > 0) {
4200 coap_log_debug("* %s: tls: recv %4d bytes\n",
4201 coap_session_str(session), r);
4202 }
4203 return r;
4204}
4205#endif /* !COAP_DISABLE_TCP */
4206
4207#if COAP_SERVER_SUPPORT
4209coap_digest_setup(void) {
4210 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4211
4212 if (digest_ctx) {
4213 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4214 }
4215 return digest_ctx;
4216}
4217
4218void
4220 if (digest_ctx)
4221 EVP_MD_CTX_free(digest_ctx);
4222}
4223
4224int
4226 const uint8_t *data,
4227 size_t data_len) {
4228 return EVP_DigestUpdate(digest_ctx, data, data_len);
4229}
4230
4231int
4233 coap_digest_t *digest_buffer) {
4234 unsigned int size = sizeof(coap_digest_t);
4235 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4236
4237 coap_digest_free(digest_ctx);
4238 return ret;
4239}
4240#endif /* COAP_SERVER_SUPPORT */
4241
4242#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4243static void
4244coap_crypto_output_errors(const char *prefix) {
4245#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4246 (void)prefix;
4247#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4248 unsigned long e;
4249
4250 while ((e = ERR_get_error()))
4251 coap_log_warn("%s: %s%s\n",
4252 prefix,
4253 ERR_reason_error_string(e),
4254 ssl_function_definition(e));
4255#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4256}
4257#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4258
4259#if COAP_WS_SUPPORT
4260/*
4261 * The struct hash_algs and the function get_hash_alg() are used to
4262 * determine which hash type to use for creating the required hash object.
4263 */
4264static struct hash_algs {
4265 cose_alg_t alg;
4266 const EVP_MD *(*get_hash)(void);
4267 size_t length; /* in bytes */
4268} hashs[] = {
4269 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4270 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4271 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4272 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4273};
4274
4275static const EVP_MD *
4276get_hash_alg(cose_alg_t alg, size_t *length) {
4277 size_t idx;
4278
4279 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
4280 if (hashs[idx].alg == alg) {
4281 *length = hashs[idx].length;
4282 return hashs[idx].get_hash();
4283 }
4284 }
4285 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4286 return NULL;
4287}
4288
4289int
4291 const coap_bin_const_t *data,
4292 coap_bin_const_t **hash) {
4293 unsigned int length;
4294 const EVP_MD *evp_md;
4295 EVP_MD_CTX *evp_ctx = NULL;
4296 coap_binary_t *dummy = NULL;
4297 size_t hash_length;
4298
4299 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4300 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4301 return 0;
4302 }
4303 evp_ctx = EVP_MD_CTX_new();
4304 if (evp_ctx == NULL)
4305 goto error;
4306 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4307 goto error;
4308 ;
4309 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4310 goto error;
4311 ;
4312 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4313 if (dummy == NULL)
4314 goto error;
4315 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4316 goto error;
4317 dummy->length = length;
4318 if (hash_length < dummy->length)
4319 dummy->length = hash_length;
4320 *hash = (coap_bin_const_t *)(dummy);
4321 EVP_MD_CTX_free(evp_ctx);
4322 return 1;
4323
4324error:
4325 coap_crypto_output_errors("coap_crypto_hash");
4327 if (evp_ctx)
4328 EVP_MD_CTX_free(evp_ctx);
4329 return 0;
4330}
4331#endif /* COAP_WS_SUPPORT */
4332
4333#if COAP_OSCORE_SUPPORT
4334int
4336 return 1;
4337}
4338
4339#include <openssl/evp.h>
4340#include <openssl/hmac.h>
4341
4342/*
4343 * The struct cipher_algs and the function get_cipher_alg() are used to
4344 * determine which cipher type to use for creating the required cipher
4345 * suite object.
4346 */
4347static struct cipher_algs {
4348 cose_alg_t alg;
4349 const EVP_CIPHER *(*get_cipher)(void);
4350} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4351 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4352};
4353
4354static const EVP_CIPHER *
4355get_cipher_alg(cose_alg_t alg) {
4356 size_t idx;
4357
4358 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4359 if (ciphers[idx].alg == alg)
4360 return ciphers[idx].get_cipher();
4361 }
4362 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4363 return NULL;
4364}
4365
4366/*
4367 * The struct hmac_algs and the function get_hmac_alg() are used to
4368 * determine which hmac type to use for creating the required hmac
4369 * suite object.
4370 */
4371static struct hmac_algs {
4372 cose_hmac_alg_t hmac_alg;
4373 const EVP_MD *(*get_hmac)(void);
4374} hmacs[] = {
4375 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4376 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4377 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4378};
4379
4380static const EVP_MD *
4381get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4382 size_t idx;
4383
4384 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4385 if (hmacs[idx].hmac_alg == hmac_alg)
4386 return hmacs[idx].get_hmac();
4387 }
4388 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4389 return NULL;
4390}
4391
4392int
4394 return get_cipher_alg(alg) != NULL;
4395}
4396
4397int
4399 cose_hmac_alg_t hmac_alg;
4400
4401 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4402 return 0;
4403 return get_hmac_alg(hmac_alg) != NULL;
4404}
4405
4406#define C(Func) \
4407 if (1 != (Func)) { \
4408 goto error; \
4409 }
4410
4411int
4413 coap_bin_const_t *data,
4414 coap_bin_const_t *aad,
4415 uint8_t *result,
4416 size_t *max_result_len) {
4417 const EVP_CIPHER *cipher;
4418 const coap_crypto_aes_ccm_t *ccm;
4419 int tmp;
4420 int result_len = (int)(*max_result_len & INT_MAX);
4421
4422 if (data == NULL)
4423 return 0;
4424
4425 assert(params != NULL);
4426 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4427 return 0;
4428 }
4429
4430 /* TODO: set evp_md depending on params->alg */
4431 ccm = &params->params.aes;
4432
4433 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
4434
4435 /* EVP_CIPHER_CTX_init(ctx); */
4436 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4437 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4438 C(EVP_CIPHER_CTX_ctrl(ctx,
4439 EVP_CTRL_AEAD_SET_IVLEN,
4440 (int)(15 - ccm->l),
4441 NULL));
4442 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4443 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4444 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4445
4446 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4447 if (aad && aad->s && (aad->length > 0)) {
4448 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4449 }
4450 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4451 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4452 tmp = result_len;
4453 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4454 result_len += tmp;
4455
4456 /* retrieve the tag */
4457 C(EVP_CIPHER_CTX_ctrl(ctx,
4458 EVP_CTRL_CCM_GET_TAG,
4459 (int)ccm->tag_len,
4460 result + result_len));
4461
4462 *max_result_len = result_len + ccm->tag_len;
4463 EVP_CIPHER_CTX_free(ctx);
4464 return 1;
4465
4466error:
4467 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4468 return 0;
4469}
4470
4471int
4473 coap_bin_const_t *data,
4474 coap_bin_const_t *aad,
4475 uint8_t *result,
4476 size_t *max_result_len) {
4477 const EVP_CIPHER *cipher;
4478 const coap_crypto_aes_ccm_t *ccm;
4479 int tmp;
4480 int len;
4481 const uint8_t *tag;
4482 uint8_t *rwtag;
4483
4484 if (data == NULL)
4485 return 0;
4486
4487 assert(params != NULL);
4488 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4489 return 0;
4490 }
4491
4492 ccm = &params->params.aes;
4493
4494 if (data->length < ccm->tag_len) {
4495 return 0;
4496 } else {
4497 tag = data->s + data->length - ccm->tag_len;
4498 data->length -= ccm->tag_len;
4499 /* Kludge to stop compiler warning */
4500 memcpy(&rwtag, &tag, sizeof(rwtag));
4501 }
4502
4503 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
4504
4505 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4506 C(EVP_CIPHER_CTX_ctrl(ctx,
4507 EVP_CTRL_AEAD_SET_IVLEN,
4508 (int)(15 - ccm->l),
4509 NULL));
4510 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4511 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4512 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4513 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4514
4515 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4516 if (aad && aad->s && (aad->length > 0)) {
4517 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4518 }
4519 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4520 EVP_CIPHER_CTX_free(ctx);
4521 if (tmp <= 0) {
4522 *max_result_len = 0;
4523 return 0;
4524 }
4525 *max_result_len = len;
4526 return 1;
4527
4528error:
4529 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4530 return 0;
4531}
4532
4533int
4535 coap_bin_const_t *key,
4536 coap_bin_const_t *data,
4537 coap_bin_const_t **hmac) {
4538 unsigned int result_len;
4539 const EVP_MD *evp_md;
4540 coap_binary_t *dummy = NULL;
4541
4542 assert(key);
4543 assert(data);
4544 assert(hmac);
4545
4546 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4547 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4548 return 0;
4549 }
4550 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4551 if (dummy == NULL)
4552 return 0;
4553 result_len = (unsigned int)dummy->length;
4554 if (HMAC(evp_md,
4555 key->s,
4556 (int)key->length,
4557 data->s,
4558 (int)data->length,
4559 dummy->s,
4560 &result_len)) {
4561 dummy->length = result_len;
4562 *hmac = (coap_bin_const_t *)dummy;
4563 return 1;
4564 }
4565
4566 coap_crypto_output_errors("coap_crypto_hmac");
4567 return 0;
4568}
4569
4570#endif /* COAP_OSCORE_SUPPORT */
4571
4572#else /* !COAP_WITH_LIBOPENSSL */
4573
4574#ifdef __clang__
4575/* Make compilers happy that do not like empty modules. As this function is
4576 * never used, we ignore -Wunused-function at the end of compiling this file
4577 */
4578#pragma GCC diagnostic ignored "-Wunused-function"
4579#endif
4580static inline void
4581dummy(void) {
4582}
4583
4584#endif /* COAP_WITH_LIBOPENSSL */
#define COAP_RXBUFFER_SIZE
Definition coap_io.h:29
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:66
#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:39
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.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
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:178
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:4809
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:2836
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:35
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:44
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:70
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:245
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:242
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:236
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:234
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:251
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:238
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:240
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:248
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition coap_dtls.h:46
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition coap_dtls.h:45
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:172
@ COAP_ASN1_PKEY_DH
DH type.
Definition coap_dtls.h:155
@ COAP_ASN1_PKEY_NONE
NONE.
Definition coap_dtls.h:147
@ COAP_ASN1_PKEY_TLS1_PRF
TLS1_PRF type.
Definition coap_dtls.h:160
@ COAP_ASN1_PKEY_RSA2
RSA2 type.
Definition coap_dtls.h:149
@ COAP_ASN1_PKEY_DSA
DSA type.
Definition coap_dtls.h:150
@ COAP_ASN1_PKEY_DHX
DHX type.
Definition coap_dtls.h:156
@ COAP_ASN1_PKEY_DSA4
DSA4 type.
Definition coap_dtls.h:154
@ COAP_ASN1_PKEY_DSA2
DSA2 type.
Definition coap_dtls.h:152
@ COAP_ASN1_PKEY_RSA
RSA type.
Definition coap_dtls.h:148
@ COAP_ASN1_PKEY_DSA1
DSA1 type.
Definition coap_dtls.h:151
@ COAP_ASN1_PKEY_HKDF
HKDF type.
Definition coap_dtls.h:161
@ COAP_ASN1_PKEY_EC
EC type.
Definition coap_dtls.h:157
@ COAP_ASN1_PKEY_DSA3
DSA3 type.
Definition coap_dtls.h:153
@ COAP_ASN1_PKEY_HMAC
HMAC type.
Definition coap_dtls.h:158
@ COAP_ASN1_PKEY_CMAC
CMAC type.
Definition coap_dtls.h:159
@ COAP_TLS_LIBRARY_OPENSSL
Using OpenSSL library.
Definition coap_dtls.h:73
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:39
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_RENEGOTIATE
Triggered when (D)TLS session renegotiated.
Definition coap_event.h:43
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:45
#define coap_lock_callback_ret(r, c, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:120
coap_log_t
Logging type.
Definition coap_debug.h:50
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:300
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:108
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log_err(...)
Definition coap_debug.h:96
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:284
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_WARN
Definition coap_debug.h:55
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:41
@ COAP_PROTO_DTLS
Definition coap_pdu.h:316
@ COAP_PROTO_TLS
Definition coap_pdu.h:318
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:70
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
CoAP binary data definition.
Definition coap_str.h:56
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:379
coap_bin_const_t key
Definition coap_dtls.h:381
coap_bin_const_t identity
Definition coap_dtls.h:380
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:410
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
Definition coap_dtls.h:417
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:434
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:437
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:433
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:415
The structure that holds the PKI key information.
Definition coap_dtls.h:279
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:286
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:280
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:312
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:326
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:351
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:323
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:333
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:325
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:358
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:324
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:366
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:322
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:317
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:368
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:320
void * sni_call_back_arg
Passed in to the sni callback function.
Definition coap_dtls.h:359
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:350
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:327
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:330
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:318
coap_dtls_key_t pki_key
PKI key definition.
Definition coap_dtls.h:373
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:450
coap_bin_const_t hint
Definition coap_dtls.h:451
coap_bin_const_t key
Definition coap_dtls.h:452
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:501
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:530
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:522
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:523
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:506
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:531
coap_dtls_spsk_info_t psk_info
Server PSK definition.
Definition coap_dtls.h:533
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:261
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
Definition coap_dtls.h:269
const char * user_pin
define: User pin to access type PKCS11.
Definition coap_dtls.h:271
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:262
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:260
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:264
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:263
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:268
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:265
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:266
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:267
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:46
const uint8_t * s
read-only string data
Definition coap_str.h:48
size_t length
length of string
Definition coap_str.h:47
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:83
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:86
coap_tls_library_t type
Library type.
Definition coap_dtls.h:85
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:84
const char * s_byte
signed char ptr
Definition coap_str.h:73
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:74