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