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