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