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