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