libcoap 4.3.5-develop-0a48cee
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 if (data != NULL)
601 free(data);
602 BIO_set_data(a, NULL);
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
3313 if (!context->dtls.ssl) {
3314 /* This is set up to handle new incoming sessions to a server */
3315 context->dtls.ssl = SSL_new(context->dtls.ctx);
3316 if (!context->dtls.ssl)
3317 return 0;
3318 bio = BIO_new(context->dtls.meth);
3319 if (!bio) {
3320 SSL_free(context->dtls.ssl);
3321 context->dtls.ssl = NULL;
3322 return 0;
3323 }
3324 SSL_set_bio(context->dtls.ssl, bio, bio);
3325 SSL_set_app_data(context->dtls.ssl, NULL);
3326 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3327 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3328 }
3329 context->psk_pki_enabled |= IS_PKI;
3330 if (setup_data->use_cid) {
3331 coap_log_warn("OpenSSL has no Connection-ID support\n");
3332 }
3333 return 1;
3334}
3335
3336int
3338 const char *ca_file,
3339 const char *ca_dir
3340 ) {
3341 coap_openssl_context_t *context =
3342 ((coap_openssl_context_t *)ctx->dtls_context);
3343 if (context->dtls.ctx) {
3344 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3345 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3346 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3347 return 0;
3348 }
3349 }
3350#if !COAP_DISABLE_TCP
3351 if (context->tls.ctx) {
3352 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3353 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3354 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3355 return 0;
3356 }
3357 }
3358#endif /* !COAP_DISABLE_TCP */
3359 return 1;
3360}
3361
3362int
3364#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3365 coap_openssl_context_t *context =
3366 ((coap_openssl_context_t *)ctx->dtls_context);
3367 if (context->dtls.ctx) {
3368 if (!SSL_CTX_set_default_verify_store(context->dtls.ctx)) {
3369 coap_log_warn("Unable to load trusted root CAs\n");
3370 return 0;
3371 }
3372 }
3373#if !COAP_DISABLE_TCP
3374 if (context->tls.ctx) {
3375 if (!SSL_CTX_set_default_verify_store(context->tls.ctx)) {
3376 coap_log_warn("Unable to load trusted root CAs\n");
3377 return 0;
3378 }
3379 }
3380#endif /* !COAP_DISABLE_TCP */
3381 return 1;
3382#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3383 (void)ctx;
3384 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3385 "not supported for OpenSSL < v3.0.0\n");
3386 return 0;
3387#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3388}
3389
3390int
3392 coap_openssl_context_t *context =
3393 ((coap_openssl_context_t *)ctx->dtls_context);
3394 return context->psk_pki_enabled ? 1 : 0;
3395}
3396
3397
3398void
3399coap_dtls_free_context(void *handle) {
3400 size_t i;
3401 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3402
3403 if (context->dtls.ssl)
3404 SSL_free(context->dtls.ssl);
3405 if (context->dtls.ctx)
3406 SSL_CTX_free(context->dtls.ctx);
3407 if (context->dtls.cookie_hmac)
3408 HMAC_CTX_free(context->dtls.cookie_hmac);
3409 if (context->dtls.meth)
3410 BIO_meth_free(context->dtls.meth);
3411 if (context->dtls.bio_addr)
3412 BIO_ADDR_free(context->dtls.bio_addr);
3413#if !COAP_DISABLE_TCP
3414 if (context->tls.ctx)
3415 SSL_CTX_free(context->tls.ctx);
3416 if (context->tls.meth)
3417 BIO_meth_free(context->tls.meth);
3418#endif /* !COAP_DISABLE_TCP */
3419 for (i = 0; i < context->sni_count; i++) {
3420 OPENSSL_free(context->sni_entry_list[i].sni);
3421#if OPENSSL_VERSION_NUMBER < 0x10101000L
3422 SSL_CTX_free(context->sni_entry_list[i].ctx);
3423#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3424 }
3425 if (context->sni_count)
3426 OPENSSL_free(context->sni_entry_list);
3427#if OPENSSL_VERSION_NUMBER < 0x10101000L
3428 for (i = 0; i < context->psk_sni_count; i++) {
3429 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3430 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3431 }
3432 if (context->psk_sni_count)
3433 OPENSSL_free(context->psk_sni_entry_list);
3434#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3435 coap_free_type(COAP_STRING, context);
3436}
3437
3438#if COAP_SERVER_SUPPORT
3439void *
3440coap_dtls_new_server_session(coap_session_t *session) {
3441 BIO *nbio = NULL;
3442 SSL *nssl = NULL, *ssl = NULL;
3443 coap_ssl_data *data;
3444 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3445 int r;
3446 const coap_bin_const_t *psk_hint;
3447 BIO *rbio;
3448
3449 nssl = SSL_new(dtls->ctx);
3450 if (!nssl)
3451 goto error;
3452 nbio = BIO_new(dtls->meth);
3453 if (!nbio)
3454 goto error;
3455 SSL_set_bio(nssl, nbio, nbio);
3456 SSL_set_app_data(nssl, NULL);
3457 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3458 SSL_set_mtu(nssl, (long)session->mtu);
3459 ssl = dtls->ssl;
3460 dtls->ssl = nssl;
3461 nssl = NULL;
3462 SSL_set_app_data(ssl, session);
3463
3464 rbio = SSL_get_rbio(ssl);
3465 data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3466 if (!data)
3467 goto error;
3468 data->session = session;
3469
3470 /* hint may get updated if/when handling SNI callback */
3471 psk_hint = coap_get_session_server_psk_hint(session);
3472 if (psk_hint != NULL && psk_hint->length) {
3473 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3474
3475 if (hint) {
3476 memcpy(hint, psk_hint->s, psk_hint->length);
3477 hint[psk_hint->length] = '\000';
3478 SSL_use_psk_identity_hint(ssl, hint);
3479 OPENSSL_free(hint);
3480 } else {
3481 coap_log_warn("hint malloc failure\n");
3482 }
3483 }
3484
3485 r = SSL_accept(ssl);
3486 if (r == -1) {
3487 int err = SSL_get_error(ssl, r);
3488 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3489 r = 0;
3490 }
3491
3492 if (r == 0) {
3493 SSL_free(ssl);
3494 return NULL;
3495 }
3496
3497 return ssl;
3498
3499error:
3500 if (nssl)
3501 SSL_free(nssl);
3502 return NULL;
3503}
3504#endif /* COAP_SERVER_SUPPORT */
3505
3506#if COAP_CLIENT_SUPPORT
3507static int
3508setup_client_ssl_session(coap_session_t *session, SSL *ssl
3509 ) {
3510 coap_openssl_context_t *context =
3511 ((coap_openssl_context_t *)session->context->dtls_context);
3512
3513 if (context->psk_pki_enabled & IS_PSK) {
3514 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3515
3516 /* Issue SNI if requested */
3517 if (setup_data->client_sni &&
3518 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3519 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3520 setup_data->client_sni);
3521 }
3522 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3523#if COAP_SERVER_SUPPORT
3524 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3525#endif /* COAP_SERVER_SUPPORT */
3526 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3527#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
3528 /*
3529 * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
3530 * Potentially opens up security vulnerabilities.
3531 * Default value is 1.
3532 */
3533 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
3534#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
3535 if (setup_data->validate_ih_call_back) {
3536 if (session->proto == COAP_PROTO_DTLS) {
3537 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3538 }
3539#if !COAP_DISABLE_TCP
3540 else {
3541 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3542 }
3543#endif /* !COAP_DISABLE_TCP */
3544 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3545 }
3546 }
3547 if ((context->psk_pki_enabled & IS_PKI) ||
3548 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3549 /*
3550 * If neither PSK or PKI have been set up, use PKI basics.
3551 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3552 */
3553 coap_dtls_pki_t *setup_data = &context->setup_data;
3554
3555 if (!(context->psk_pki_enabled & IS_PKI)) {
3556 /* PKI not defined - set up some defaults */
3557 setup_data->verify_peer_cert = 1;
3558 setup_data->check_common_ca = 0;
3559 setup_data->allow_self_signed = 1;
3560 setup_data->allow_expired_certs = 1;
3561 setup_data->cert_chain_validation = 1;
3562 setup_data->cert_chain_verify_depth = 2;
3563 setup_data->check_cert_revocation = 1;
3564 setup_data->allow_no_crl = 1;
3565 setup_data->allow_expired_crl = 1;
3566 setup_data->is_rpk_not_cert = 0;
3567 setup_data->use_cid = 0;
3568 }
3569 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3570 return 0;
3571 /* libcoap is managing (D)TLS connection based on setup_data options */
3572#if !COAP_DISABLE_TCP
3573 if (session->proto == COAP_PROTO_TLS)
3574 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3575#endif /* !COAP_DISABLE_TCP */
3576
3577 /* Issue SNI if requested */
3578 if (setup_data->client_sni &&
3579 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3580 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3581 setup_data->client_sni);
3582 }
3583 /* Certificate Revocation */
3584 if (setup_data->check_cert_revocation) {
3585 X509_VERIFY_PARAM *param;
3586
3587 param = X509_VERIFY_PARAM_new();
3588 if (param) {
3589 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3590 SSL_set1_param(ssl, param);
3591 X509_VERIFY_PARAM_free(param);
3592 }
3593 }
3594
3595 /* Verify Peer */
3596 if (setup_data->verify_peer_cert)
3597 SSL_set_verify(ssl,
3598 SSL_VERIFY_PEER |
3599 SSL_VERIFY_CLIENT_ONCE |
3600 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3601 tls_verify_call_back);
3602 else
3603 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3604
3605 /* Check CA Chain */
3606 if (setup_data->cert_chain_validation)
3607 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3608
3609 }
3610#if COAP_DTLS_RETRANSMIT_MS != 1000
3611#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3612 if (session->proto == COAP_PROTO_DTLS) {
3613 DTLS_set_timer_cb(ssl, timer_cb);
3614 }
3615#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3616#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3617 return 1;
3618}
3619
3620void *
3621coap_dtls_new_client_session(coap_session_t *session) {
3622 BIO *bio = NULL;
3623 SSL *ssl = NULL;
3624 coap_ssl_data *data;
3625 int r;
3626 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3627 coap_dtls_context_t *dtls = &context->dtls;
3628
3629 ssl = SSL_new(dtls->ctx);
3630 if (!ssl)
3631 goto error;
3632 bio = BIO_new(dtls->meth);
3633 if (!bio)
3634 goto error;
3635 data = (coap_ssl_data *)BIO_get_data(bio);
3636 if (!data)
3637 goto error;
3638 data->session = session;
3639 SSL_set_bio(ssl, bio, bio);
3640 SSL_set_app_data(ssl, session);
3641 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3642 SSL_set_mtu(ssl, (long)session->mtu);
3643
3644 if (!setup_client_ssl_session(session, ssl))
3645 goto error;
3646
3647 session->dtls_timeout_count = 0;
3648
3649 r = SSL_connect(ssl);
3650 if (r == -1) {
3651 int ret = SSL_get_error(ssl, r);
3652 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3653 r = 0;
3654 }
3655
3656 if (r == 0)
3657 goto error;
3658
3659 session->tls = ssl;
3660 return ssl;
3661
3662error:
3663 if (ssl)
3664 SSL_free(ssl);
3665 return NULL;
3666}
3667
3668void
3670 SSL *ssl = (SSL *)session->tls;
3671 if (ssl)
3672 SSL_set_mtu(ssl, (long)session->mtu);
3673}
3674#endif /* COAP_CLIENT_SUPPORT */
3675
3676void
3678 SSL *ssl = (SSL *)session->tls;
3679 if (ssl) {
3680 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3681 int r = SSL_shutdown(ssl);
3682 if (r == 0)
3683 SSL_shutdown(ssl);
3684 }
3685 SSL_free(ssl);
3686 session->tls = NULL;
3687 if (session->context)
3689 }
3690}
3691
3692ssize_t
3694 const uint8_t *data, size_t data_len) {
3695 int r;
3696 SSL *ssl = (SSL *)session->tls;
3697
3698 if (ssl == NULL) {
3700 return -1;
3701 }
3702
3703 session->dtls_event = -1;
3704 ERR_clear_error();
3705 r = SSL_write(ssl, data, (int)data_len);
3706
3707 if (r <= 0) {
3708 int err = SSL_get_error(ssl, r);
3709 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3710 r = 0;
3711 } else {
3712 if (err == SSL_ERROR_ZERO_RETURN)
3714 else if (err == SSL_ERROR_SSL) {
3715 unsigned long e = ERR_get_error();
3716
3717 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3718 coap_session_str(session),
3719 ERR_GET_REASON(e), ERR_reason_error_string(e));
3721 } else {
3722 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3723 coap_session_str(session), err);
3724 }
3725 r = -1;
3726 }
3727 }
3728
3729 if (session->dtls_event >= 0) {
3730 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3731 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3732 coap_handle_event_lkd(session->context, session->dtls_event, session);
3733 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3734 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3736 r = -1;
3737 }
3738 }
3739
3740 if (r > 0) {
3741 if (r == (ssize_t)data_len)
3742 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3743 coap_session_str(session), r);
3744 else
3745 coap_log_debug("* %s: dtls: sent %4d of %4" PRIdS " bytes\n",
3746 coap_session_str(session), r, data_len);
3747 }
3748 return r;
3749}
3750
3751int
3753 return 0;
3754}
3755
3757coap_dtls_get_context_timeout(void *dtls_context) {
3758 (void)dtls_context;
3759 return 0;
3760}
3761
3764 SSL *ssl = (SSL *)session->tls;
3765 coap_ssl_data *ssl_data;
3766 BIO *rbio;
3767
3768 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3769 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3770 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3771 return ssl_data ? ssl_data->timeout : 1000;
3772}
3773
3774/*
3775 * return 1 timed out
3776 * 0 still timing out
3777 */
3778int
3780 SSL *ssl = (SSL *)session->tls;
3781
3782 if (ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE) {
3783 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3784 (DTLSv1_handle_timeout(ssl) < 0)) {
3785 /* Too many retries */
3787 return 1;
3788 }
3789 return 0;
3790 }
3791 return 1;
3792}
3793
3794#if COAP_SERVER_SUPPORT
3795int
3796coap_dtls_hello(coap_session_t *session,
3797 const uint8_t *data, size_t data_len) {
3798 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3799 coap_ssl_data *ssl_data;
3800 int r;
3801 BIO *rbio;
3802
3803 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3804 rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) : NULL;
3805 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3806 assert(ssl_data != NULL);
3807 if (!ssl_data) {
3808 errno = ENOMEM;
3809 return -1;
3810 }
3811 if (ssl_data->pdu_len) {
3812 coap_log_err("** %s: Previous data not read %u bytes\n",
3813 coap_session_str(session), ssl_data->pdu_len);
3814 }
3815 ssl_data->session = session;
3816 ssl_data->pdu = data;
3817 ssl_data->pdu_len = (unsigned)data_len;
3818 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3819 if (r <= 0) {
3820 int err = SSL_get_error(dtls->ssl, r);
3821 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3822 /* Got a ClientHello, sent-out a VerifyRequest */
3823 r = 0;
3824 }
3825 } else {
3826 /* Got a valid answer to a VerifyRequest */
3827 r = 1;
3828 }
3829
3830 /*
3831 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3832 * only does a 'peek' read of the incoming data.
3833 *
3834 */
3835 return r;
3836}
3837#endif /* COAP_SERVER_SUPPORT */
3838
3839int
3840coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3841 coap_ssl_data *ssl_data;
3842 SSL *ssl = (SSL *)session->tls;
3843 int r;
3844 BIO *rbio;
3845#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3846 int retry = 0;
3847#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3848
3849 assert(ssl != NULL);
3850
3851 int in_init = SSL_in_init(ssl);
3852 uint8_t pdu[COAP_RXBUFFER_SIZE];
3853 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3854 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3855 if (!ssl_data) {
3856 errno = ENOTCONN;
3857 return -1;
3858 }
3859
3860 if (ssl_data->pdu_len) {
3861 coap_log_err("** %s: Previous data not read %u bytes\n",
3862 coap_session_str(session), ssl_data->pdu_len);
3863 }
3864 ssl_data->pdu = data;
3865 ssl_data->pdu_len = (unsigned)data_len;
3866
3867 session->dtls_event = -1;
3868#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3869retry:
3870#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3871 ERR_clear_error();
3872 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3873 if (r > 0) {
3874 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3875 coap_session_str(session), r);
3876 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3877 goto finished;
3878 } else {
3879 int err = SSL_get_error(ssl, r);
3880 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3881 if (in_init && SSL_is_init_finished(ssl)) {
3882 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3883 coap_session_str(session), SSL_get_cipher_name(ssl));
3885 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3886 }
3887 r = 0;
3888 } else {
3889 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3891 else if (err == SSL_ERROR_SSL) {
3892 unsigned long e = ERR_get_error();
3893
3894#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3895#include <openssl/proverr.h>
3896 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3897 /* Loading trust store - first access causes a directory read error */
3898 retry = 1;
3899 goto retry;
3900 }
3901#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3902 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3903 coap_session_str(session),
3904 ERR_GET_REASON(e), ERR_reason_error_string(e));
3906 } else {
3907 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3908 coap_session_str(session), err);
3909 }
3910 r = -1;
3911 }
3912 if (session->dtls_event >= 0) {
3913 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3914 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3915 coap_handle_event_lkd(session->context, session->dtls_event, session);
3916 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3917 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3919 ssl_data = NULL;
3920 r = -1;
3921 }
3922 }
3923 }
3924
3925finished:
3926 if (ssl_data && ssl_data->pdu_len) {
3927 /* pdu data is held on stack which will not stay there */
3928 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3929 ssl_data->pdu_len = 0;
3930 ssl_data->pdu = NULL;
3931 }
3932 return r;
3933}
3934
3935unsigned int
3937 unsigned int overhead = 37;
3938 const SSL_CIPHER *s_ciph = NULL;
3939 if (session->tls != NULL)
3940 s_ciph = SSL_get_current_cipher(session->tls);
3941 if (s_ciph) {
3942 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3943
3944 const EVP_CIPHER *e_ciph;
3945 const EVP_MD *e_md;
3946 char cipher[128];
3947
3948 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3949
3950 switch (EVP_CIPHER_mode(e_ciph)) {
3951 case EVP_CIPH_GCM_MODE:
3952 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3953 maclen = EVP_GCM_TLS_TAG_LEN;
3954 break;
3955
3956 case EVP_CIPH_CCM_MODE:
3957 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3958 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3959 if (strstr(cipher, "CCM8"))
3960 maclen = 8;
3961 else
3962 maclen = 16;
3963 break;
3964
3965 case EVP_CIPH_CBC_MODE:
3966 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3967 blocksize = EVP_CIPHER_block_size(e_ciph);
3968 ivlen = EVP_CIPHER_iv_length(e_ciph);
3969 pad = 1;
3970 maclen = EVP_MD_size(e_md);
3971 break;
3972
3973 case EVP_CIPH_STREAM_CIPHER:
3974 /* Seen with PSK-CHACHA20-POLY1305 */
3975 ivlen = 8;
3976 maclen = 8;
3977 break;
3978
3979 default:
3980 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3981 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3982 cipher);
3983 ivlen = 8;
3984 maclen = 16;
3985 break;
3986 }
3987 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3988 }
3989 return overhead;
3990}
3991
3992#if !COAP_DISABLE_TCP
3993#if COAP_CLIENT_SUPPORT
3994void *
3995coap_tls_new_client_session(coap_session_t *session) {
3996 BIO *bio = NULL;
3997 SSL *ssl = NULL;
3998 int r;
3999 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
4000 coap_tls_context_t *tls = &context->tls;
4001
4002 ssl = SSL_new(tls->ctx);
4003 if (!ssl)
4004 goto error;
4005 bio = BIO_new(tls->meth);
4006 if (!bio)
4007 goto error;
4008 BIO_set_data(bio, session);
4009 SSL_set_bio(ssl, bio, bio);
4010 SSL_set_app_data(ssl, session);
4011
4012 if (!setup_client_ssl_session(session, ssl))
4013 return 0;
4014
4015 r = SSL_connect(ssl);
4016 if (r == -1) {
4017 int ret = SSL_get_error(ssl, r);
4018 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
4019 r = 0;
4020 if (ret == SSL_ERROR_WANT_READ)
4021 session->sock.flags |= COAP_SOCKET_WANT_READ;
4022 if (ret == SSL_ERROR_WANT_WRITE) {
4023 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4024#ifdef COAP_EPOLL_SUPPORT
4025 coap_epoll_ctl_mod(&session->sock,
4026 EPOLLOUT |
4027 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4028 EPOLLIN : 0),
4029 __func__);
4030#endif /* COAP_EPOLL_SUPPORT */
4031 }
4032 }
4033
4034 if (r == 0)
4035 goto error;
4036
4037 session->tls = ssl;
4038 if (SSL_is_init_finished(ssl)) {
4040 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4041 }
4042
4043 return ssl;
4044
4045error:
4046 if (ssl)
4047 SSL_free(ssl);
4048 return NULL;
4049}
4050#endif /* COAP_CLIENT_SUPPORT */
4051
4052#if COAP_SERVER_SUPPORT
4053void *
4054coap_tls_new_server_session(coap_session_t *session) {
4055 BIO *bio = NULL;
4056 SSL *ssl = NULL;
4057 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
4058 int r;
4059 const coap_bin_const_t *psk_hint;
4060
4061 ssl = SSL_new(tls->ctx);
4062 if (!ssl)
4063 goto error;
4064 bio = BIO_new(tls->meth);
4065 if (!bio)
4066 goto error;
4067 BIO_set_data(bio, session);
4068 SSL_set_bio(ssl, bio, bio);
4069 SSL_set_app_data(ssl, session);
4070
4071 psk_hint = coap_get_session_server_psk_hint(session);
4072 if (psk_hint != NULL && psk_hint->length) {
4073 char *hint = OPENSSL_malloc(psk_hint->length + 1);
4074
4075 if (hint) {
4076 memcpy(hint, psk_hint->s, psk_hint->length);
4077 hint[psk_hint->length] = '\000';
4078 SSL_use_psk_identity_hint(ssl, hint);
4079 OPENSSL_free(hint);
4080 } else {
4081 coap_log_warn("hint malloc failure\n");
4082 }
4083 }
4084
4085 r = SSL_accept(ssl);
4086 if (r == -1) {
4087 int err = SSL_get_error(ssl, r);
4088 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4089 r = 0;
4090 if (err == SSL_ERROR_WANT_READ)
4091 session->sock.flags |= COAP_SOCKET_WANT_READ;
4092 if (err == SSL_ERROR_WANT_WRITE) {
4093 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4094#ifdef COAP_EPOLL_SUPPORT
4095 coap_epoll_ctl_mod(&session->sock,
4096 EPOLLOUT |
4097 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4098 EPOLLIN : 0),
4099 __func__);
4100#endif /* COAP_EPOLL_SUPPORT */
4101 }
4102 }
4103
4104 if (r == 0)
4105 goto error;
4106
4107 session->tls = ssl;
4108 if (SSL_is_init_finished(ssl)) {
4110 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4111 }
4112
4113#if COAP_DTLS_RETRANSMIT_MS != 1000
4114#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4115 if (session->proto == COAP_PROTO_DTLS) {
4116 DTLS_set_timer_cb(ssl, timer_cb);
4117 }
4118#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4119#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4120
4121 return ssl;
4122
4123error:
4124 if (ssl)
4125 SSL_free(ssl);
4126 return NULL;
4127}
4128#endif /* COAP_SERVER_SUPPORT */
4129
4130void
4132 SSL *ssl = (SSL *)session->tls;
4133 if (ssl) {
4134 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4135 int r = SSL_shutdown(ssl);
4136 if (r == 0)
4137 SSL_shutdown(ssl);
4138 }
4139 SSL_free(ssl);
4140 session->tls = NULL;
4141 if (session->context)
4143 }
4144}
4145
4146/*
4147 * strm
4148 * return +ve Number of bytes written.
4149 * -1 Error (error in errno).
4150 */
4151ssize_t
4152coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4153 SSL *ssl = (SSL *)session->tls;
4154 int r, in_init;
4155
4156 if (ssl == NULL)
4157 return -1;
4158
4159 in_init = !SSL_is_init_finished(ssl);
4160 session->dtls_event = -1;
4161 ERR_clear_error();
4162 r = SSL_write(ssl, data, (int)data_len);
4163
4164 if (r <= 0) {
4165 int err = SSL_get_error(ssl, r);
4166 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4167 if (in_init && SSL_is_init_finished(ssl)) {
4168 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4169 coap_session_str(session), SSL_get_cipher_name(ssl));
4171 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4172 }
4173 if (err == SSL_ERROR_WANT_READ)
4174 session->sock.flags |= COAP_SOCKET_WANT_READ;
4175 else if (err == SSL_ERROR_WANT_WRITE) {
4176 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4177#ifdef COAP_EPOLL_SUPPORT
4178 coap_epoll_ctl_mod(&session->sock,
4179 EPOLLOUT |
4180 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4181 EPOLLIN : 0),
4182 __func__);
4183#endif /* COAP_EPOLL_SUPPORT */
4184 }
4185 r = 0;
4186 } else {
4187 if (err == SSL_ERROR_ZERO_RETURN)
4189 else if (err == SSL_ERROR_SSL) {
4190 unsigned long e = ERR_get_error();
4191
4192 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4193 coap_session_str(session),
4194 ERR_GET_REASON(e), ERR_reason_error_string(e));
4196 } else {
4197 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4198 coap_session_str(session), err);
4199 }
4200 r = -1;
4201 }
4202 } else if (in_init && SSL_is_init_finished(ssl)) {
4203 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4204 coap_session_str(session), SSL_get_cipher_name(ssl));
4206 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4207 }
4208
4209 if (session->dtls_event >= 0) {
4210 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4211 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4212 coap_handle_event_lkd(session->context, session->dtls_event, session);
4213 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4214 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4216 r = -1;
4217 }
4218 }
4219
4220 if (r >= 0) {
4221 if (r == (ssize_t)data_len)
4222 coap_log_debug("* %s: tls: sent %4d bytes\n",
4223 coap_session_str(session), r);
4224 else
4225 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
4226 coap_session_str(session), r, data_len);
4227 }
4228 return r;
4229}
4230
4231/*
4232 * strm
4233 * return >=0 Number of bytes read.
4234 * -1 Error (error in errno).
4235 */
4236ssize_t
4237coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4238 SSL *ssl = (SSL *)session->tls;
4239 int r, in_init;
4240
4241 if (ssl == NULL) {
4242 errno = ENXIO;
4243 return -1;
4244 }
4245
4246 in_init = !SSL_is_init_finished(ssl);
4247 session->dtls_event = -1;
4248 ERR_clear_error();
4249 r = SSL_read(ssl, data, (int)data_len);
4250 if (r <= 0) {
4251 int err = SSL_get_error(ssl, r);
4252 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4253 if (in_init && SSL_is_init_finished(ssl)) {
4254 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4255 coap_session_str(session), SSL_get_cipher_name(ssl));
4257 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4258 }
4259 if (err == SSL_ERROR_WANT_READ)
4260 session->sock.flags |= COAP_SOCKET_WANT_READ;
4261 if (err == SSL_ERROR_WANT_WRITE) {
4262 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4263#ifdef COAP_EPOLL_SUPPORT
4264 coap_epoll_ctl_mod(&session->sock,
4265 EPOLLOUT |
4266 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4267 EPOLLIN : 0),
4268 __func__);
4269#endif /* COAP_EPOLL_SUPPORT */
4270 }
4271 r = 0;
4272 } else {
4273 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4275 else if (err == SSL_ERROR_SSL) {
4276 unsigned long e = ERR_get_error();
4277
4278 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4279 coap_session_str(session),
4280 ERR_GET_REASON(e), ERR_reason_error_string(e));
4282 } else {
4283 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4284 coap_session_str(session), err);
4285 }
4286 r = -1;
4287 }
4288 } else if (in_init && SSL_is_init_finished(ssl)) {
4289 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4290 coap_session_str(session), SSL_get_cipher_name(ssl));
4292 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4293 }
4294
4295 if (session->dtls_event >= 0) {
4296 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4297 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4298 coap_handle_event_lkd(session->context, session->dtls_event, session);
4299 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4300 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4302 r = -1;
4303 }
4304 }
4305
4306 if (r > 0) {
4307 coap_log_debug("* %s: tls: recv %4d bytes\n",
4308 coap_session_str(session), r);
4309 }
4310 return r;
4311}
4312#endif /* !COAP_DISABLE_TCP */
4313
4314#if COAP_SERVER_SUPPORT
4315coap_digest_ctx_t *
4316coap_digest_setup(void) {
4317 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4318
4319 if (digest_ctx) {
4320 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4321 }
4322 return digest_ctx;
4323}
4324
4325void
4326coap_digest_free(coap_digest_ctx_t *digest_ctx) {
4327 if (digest_ctx)
4328 EVP_MD_CTX_free(digest_ctx);
4329}
4330
4331int
4332coap_digest_update(coap_digest_ctx_t *digest_ctx,
4333 const uint8_t *data,
4334 size_t data_len) {
4335 return EVP_DigestUpdate(digest_ctx, data, data_len);
4336}
4337
4338int
4339coap_digest_final(coap_digest_ctx_t *digest_ctx,
4340 coap_digest_t *digest_buffer) {
4341 unsigned int size = sizeof(coap_digest_t);
4342 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4343
4344 coap_digest_free(digest_ctx);
4345 return ret;
4346}
4347#endif /* COAP_SERVER_SUPPORT */
4348
4349#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4350static void
4351coap_crypto_output_errors(const char *prefix) {
4352#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4353 (void)prefix;
4354#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4355 unsigned long e;
4356
4357 while ((e = ERR_get_error()))
4358 coap_log_warn("%s: %s%s\n",
4359 prefix,
4360 ERR_reason_error_string(e),
4361 ssl_function_definition(e));
4362#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4363}
4364#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4365
4366#if COAP_WS_SUPPORT
4367/*
4368 * The struct hash_algs and the function get_hash_alg() are used to
4369 * determine which hash type to use for creating the required hash object.
4370 */
4371static struct hash_algs {
4372 cose_alg_t alg;
4373 const EVP_MD *(*get_hash)(void);
4374 size_t length; /* in bytes */
4375} hashs[] = {
4376 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4377 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4378 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4379 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4380};
4381
4382static const EVP_MD *
4383get_hash_alg(cose_alg_t alg, size_t *length) {
4384 size_t idx;
4385
4386 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
4387 if (hashs[idx].alg == alg) {
4388 *length = hashs[idx].length;
4389 return hashs[idx].get_hash();
4390 }
4391 }
4392 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4393 return NULL;
4394}
4395
4396int
4398 const coap_bin_const_t *data,
4399 coap_bin_const_t **hash) {
4400 unsigned int length;
4401 const EVP_MD *evp_md;
4402 EVP_MD_CTX *evp_ctx = NULL;
4404 size_t hash_length;
4405
4406 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4407 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4408 return 0;
4409 }
4410 evp_ctx = EVP_MD_CTX_new();
4411 if (evp_ctx == NULL)
4412 goto error;
4413 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4414 goto error;
4415 ;
4416 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4417 goto error;
4418 ;
4419 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4420 if (dummy == NULL)
4421 goto error;
4422 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4423 goto error;
4424 dummy->length = length;
4425 if (hash_length < dummy->length)
4426 dummy->length = hash_length;
4427 *hash = (coap_bin_const_t *)(dummy);
4428 EVP_MD_CTX_free(evp_ctx);
4429 return 1;
4430
4431error:
4432 coap_crypto_output_errors("coap_crypto_hash");
4434 if (evp_ctx)
4435 EVP_MD_CTX_free(evp_ctx);
4436 return 0;
4437}
4438#endif /* COAP_WS_SUPPORT */
4439
4440#if COAP_OSCORE_SUPPORT
4441int
4443 return 1;
4444}
4445
4446#include <openssl/evp.h>
4447#include <openssl/hmac.h>
4448
4449/*
4450 * The struct cipher_algs and the function get_cipher_alg() are used to
4451 * determine which cipher type to use for creating the required cipher
4452 * suite object.
4453 */
4454static struct cipher_algs {
4455 cose_alg_t alg;
4456 const EVP_CIPHER *(*get_cipher)(void);
4457} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4458 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4459};
4460
4461static const EVP_CIPHER *
4462get_cipher_alg(cose_alg_t alg) {
4463 size_t idx;
4464
4465 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4466 if (ciphers[idx].alg == alg)
4467 return ciphers[idx].get_cipher();
4468 }
4469 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4470 return NULL;
4471}
4472
4473/*
4474 * The struct hmac_algs and the function get_hmac_alg() are used to
4475 * determine which hmac type to use for creating the required hmac
4476 * suite object.
4477 */
4478static struct hmac_algs {
4479 cose_hmac_alg_t hmac_alg;
4480 const EVP_MD *(*get_hmac)(void);
4481} hmacs[] = {
4482 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4483 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4484 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4485};
4486
4487static const EVP_MD *
4488get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4489 size_t idx;
4490
4491 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4492 if (hmacs[idx].hmac_alg == hmac_alg)
4493 return hmacs[idx].get_hmac();
4494 }
4495 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4496 return NULL;
4497}
4498
4499int
4501 return get_cipher_alg(alg) != NULL;
4502}
4503
4504int
4506 cose_hmac_alg_t hmac_alg;
4507
4508 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4509 return 0;
4510 return get_hmac_alg(hmac_alg) != NULL;
4511}
4512
4513#define C(Func) \
4514 if (1 != (Func)) { \
4515 goto error; \
4516 }
4517
4518int
4520 coap_bin_const_t *data,
4521 coap_bin_const_t *aad,
4522 uint8_t *result,
4523 size_t *max_result_len) {
4524 const EVP_CIPHER *cipher;
4525 const coap_crypto_aes_ccm_t *ccm;
4526 int tmp;
4527 int result_len = (int)(*max_result_len & INT_MAX);
4528 EVP_CIPHER_CTX *ctx;
4529
4530 if (data == NULL)
4531 return 0;
4532
4533 assert(params != NULL);
4534 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4535 return 0;
4536 }
4537
4538 /* TODO: set evp_md depending on params->alg */
4539 ccm = &params->params.aes;
4540
4541 ctx = EVP_CIPHER_CTX_new();
4542 if (!ctx)
4543 return 0;
4544
4545 /* EVP_CIPHER_CTX_init(ctx); */
4546 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4547 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4548 C(EVP_CIPHER_CTX_ctrl(ctx,
4549 EVP_CTRL_AEAD_SET_IVLEN,
4550 (int)(15 - ccm->l),
4551 NULL));
4552 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4553 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4554 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4555
4556 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4557 if (aad && aad->s && (aad->length > 0)) {
4558 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4559 }
4560 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4561 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4562 tmp = result_len;
4563 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4564 result_len += tmp;
4565
4566 /* retrieve the tag */
4567 C(EVP_CIPHER_CTX_ctrl(ctx,
4568 EVP_CTRL_CCM_GET_TAG,
4569 (int)ccm->tag_len,
4570 result + result_len));
4571
4572 *max_result_len = result_len + ccm->tag_len;
4573 EVP_CIPHER_CTX_free(ctx);
4574 return 1;
4575
4576error:
4577 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4578 return 0;
4579}
4580
4581int
4583 coap_bin_const_t *data,
4584 coap_bin_const_t *aad,
4585 uint8_t *result,
4586 size_t *max_result_len) {
4587 const EVP_CIPHER *cipher;
4588 const coap_crypto_aes_ccm_t *ccm;
4589 int tmp;
4590 int len;
4591 const uint8_t *tag;
4592 uint8_t *rwtag;
4593 EVP_CIPHER_CTX *ctx;
4594
4595 if (data == NULL)
4596 return 0;
4597
4598 assert(params != NULL);
4599 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4600 return 0;
4601 }
4602
4603 ccm = &params->params.aes;
4604
4605 if (data->length < ccm->tag_len) {
4606 return 0;
4607 } else {
4608 tag = data->s + data->length - ccm->tag_len;
4609 data->length -= ccm->tag_len;
4610 /* Kludge to stop compiler warning */
4611 memcpy(&rwtag, &tag, sizeof(rwtag));
4612 }
4613
4614 ctx = EVP_CIPHER_CTX_new();
4615 if (!ctx)
4616 return 0;
4617
4618 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4619 C(EVP_CIPHER_CTX_ctrl(ctx,
4620 EVP_CTRL_AEAD_SET_IVLEN,
4621 (int)(15 - ccm->l),
4622 NULL));
4623 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4624 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4625 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4626 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4627
4628 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4629 if (aad && aad->s && (aad->length > 0)) {
4630 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4631 }
4632 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4633 EVP_CIPHER_CTX_free(ctx);
4634 if (tmp <= 0) {
4635 *max_result_len = 0;
4636 return 0;
4637 }
4638 *max_result_len = len;
4639 return 1;
4640
4641error:
4642 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4643 return 0;
4644}
4645
4646int
4648 coap_bin_const_t *key,
4649 coap_bin_const_t *data,
4650 coap_bin_const_t **hmac) {
4651 unsigned int result_len;
4652 const EVP_MD *evp_md;
4654
4655 assert(key);
4656 assert(data);
4657 assert(hmac);
4658
4659 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4660 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4661 return 0;
4662 }
4663 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4664 if (dummy == NULL)
4665 return 0;
4666 result_len = (unsigned int)dummy->length;
4667 if (HMAC(evp_md,
4668 key->s,
4669 (int)key->length,
4670 data->s,
4671 (int)data->length,
4672 dummy->s,
4673 &result_len)) {
4674 dummy->length = result_len;
4675 *hmac = (coap_bin_const_t *)dummy;
4676 return 1;
4677 }
4678
4680 coap_crypto_output_errors("coap_crypto_hmac");
4681 return 0;
4682}
4683
4684#endif /* COAP_OSCORE_SUPPORT */
4685
4686#else /* ! COAP_WITH_LIBOPENSSL */
4687
4688#ifdef __clang__
4689/* Make compilers happy that do not like empty modules. As this function is
4690 * never used, we ignore -Wunused-function at the end of compiling this file
4691 */
4692#pragma GCC diagnostic ignored "-Wunused-function"
4693#endif
4694static inline void
4695dummy(void) {
4696}
4697
4698#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:5036
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:2947
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:319
@ COAP_PROTO_TLS
Definition coap_pdu.h:321
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_CSM
void coap_delete_str_const(coap_str_const_t *s)
Deletes the given const string and releases any memory allocated.
Definition coap_str.c:65
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:81
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:114
coap_str_const_t * coap_new_str_const(const uint8_t *data, size_t size)
Returns a new const string object with at least size+1 bytes storage allocated, and the provided data...
Definition coap_str.c:55
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
Definition coap_notls.c:86
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
#define COAP_UNUSED
Definition libcoap.h:74
CoAP binary data definition with const data.
Definition coap_str.h:65
size_t length
length of binary data
Definition coap_str.h:66
const uint8_t * s
read-only binary data
Definition coap_str.h:67
CoAP binary data definition.
Definition coap_str.h:57
The CoAP stack's global state is stored in a coap_context_t object.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith to use.
The structure that holds the Client PSK information.
Definition coap_dtls.h:383
coap_bin_const_t key
Definition coap_dtls.h:385
coap_bin_const_t identity
Definition coap_dtls.h:384
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:414
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
Definition coap_dtls.h:421
void * ih_call_back_arg
Passed in to the Identity Hint callback function.
Definition coap_dtls.h:438
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:441
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:437
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:419
The structure that holds the PKI key information.
Definition coap_dtls.h:283
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:290
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:284
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:316
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:330
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:355
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:327
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:337
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:329
coap_dtls_pki_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:362
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:328
coap_dtls_security_setup_t additional_tls_setup_call_back
Additional Security callback handler that is invoked when libcoap has done the standard,...
Definition coap_dtls.h:370
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:326
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:321
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:372
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:324
void * sni_call_back_arg
Passed in to the sni callback function.
Definition coap_dtls.h:363
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:354
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:331
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:334
uint8_t check_common_ca
1 if peer cert is to be signed by the same CA as the local cert
Definition coap_dtls.h:322
coap_dtls_key_t pki_key
PKI key definition.
Definition coap_dtls.h:377
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:454
coap_bin_const_t hint
Definition coap_dtls.h:455
coap_bin_const_t key
Definition coap_dtls.h:456
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:505
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:534
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:526
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:527
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:510
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:535
coap_dtls_spsk_info_t psk_info
Server PSK definition.
Definition coap_dtls.h:537
coap_layer_read_t l_read
coap_layer_write_t l_write
coap_layer_establish_t l_establish
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:265
coap_asn1_privatekey_type_t private_key_type
define: ASN1 Private Key Type (if needed)
Definition coap_dtls.h:273
const char * user_pin
define: User pin to access type PKCS11.
Definition coap_dtls.h:275
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:266
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:264
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:268
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:267
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:272
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:269
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:270
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:271
Abstraction of virtual session that can be attached to coap_context_t (client) or coap_endpoint_t (se...
unsigned int dtls_timeout_count
dtls setup retry counter
coap_bin_const_t * psk_key
If client, this field contains the current pre-shared key for server; When this field is NULL,...
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_proto_t proto
protocol used
coap_dtls_cpsk_t cpsk_setup_data
client provided PSK initial setup data
size_t mtu
path or CSM mtu (xmt)
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
uint16_t max_retransmit
maximum re-transmit count (default 4)
coap_context_t * context
session's context
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
CoAP string data definition with const data.
Definition coap_str.h:47
const uint8_t * s
read-only string data
Definition coap_str.h:49
size_t length
length of string
Definition coap_str.h:48
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:87
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:90
coap_tls_library_t type
Library type.
Definition coap_dtls.h:89
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:88
const char * s_byte
signed char ptr
Definition coap_str.h:84
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:85