libcoap 4.3.5-develop-892aa20
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 parameter #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 * Formatting 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 while (ERR_get_error()) {
1008 }
1009 }
1010 }
1011 }
1012
1013 if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
1015}
1016
1017#if !COAP_DISABLE_TCP
1018static int
1019coap_sock_create(BIO *a) {
1020 BIO_set_init(a, 1);
1021 return 1;
1022}
1023
1024static int
1025coap_sock_destroy(BIO *a) {
1026 (void)a;
1027 return 1;
1028}
1029
1030/*
1031 * strm
1032 * return +ve data amount
1033 * 0 no more
1034 * -1 error
1035 */
1036static int
1037coap_sock_read(BIO *a, char *out, int outl) {
1038 int ret = 0;
1039 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1040
1041 if (session && out != NULL) {
1042 ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (uint8_t *)out,
1043 outl);
1044 /* Translate layer returns into what OpenSSL expects */
1045 if (ret == 0) {
1046 BIO_set_retry_read(a);
1047 ret = -1;
1048 errno = EAGAIN;
1049 } else {
1050 BIO_clear_retry_flags(a);
1051 }
1052 }
1053 return ret;
1054}
1055
1056/*
1057 * strm
1058 * return +ve data amount
1059 * 0 no more
1060 * -1 error (error in errno)
1061 */
1062static int
1063coap_sock_write(BIO *a, const char *in, int inl) {
1064 int ret = 0;
1065 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1066
1067 if (!session) {
1068 errno = ENOMEM;
1069 return -1;
1070 } else {
1071 ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
1072 (const uint8_t *)in,
1073 inl);
1074 }
1075 /* Translate layer what returns into what OpenSSL expects */
1076 BIO_clear_retry_flags(a);
1077 if (ret == 0) {
1078 BIO_set_retry_read(a);
1079 ret = -1;
1080 errno = EAGAIN;
1081 } else {
1082 BIO_clear_retry_flags(a);
1083 if (ret == -1) {
1084 if ((session->state == COAP_SESSION_STATE_CSM ||
1085 session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1086 (errno == EPIPE || errno == ECONNRESET)) {
1087 /*
1088 * Need to handle a TCP timing window where an agent continues with
1089 * the sending of the next handshake or a CSM.
1090 * However, the peer does not like a certificate and so sends a
1091 * fatal alert and closes the TCP session.
1092 * The sending of the next handshake or CSM may get terminated because
1093 * of the closed TCP session, but there is still an outstanding alert
1094 * to be read in and reported on.
1095 * In this case, pretend that sending the info was fine so that the
1096 * alert can be read (which effectively is what happens with DTLS).
1097 */
1098 ret = inl;
1099 }
1100 }
1101 }
1102 return ret;
1103}
1104
1105static int
1106coap_sock_puts(BIO *a, const char *pstr) {
1107 return coap_sock_write(a, pstr, (int)strlen(pstr));
1108}
1109
1110static long
1111coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
1112 int r = 1;
1113 (void)a;
1114 (void)ptr;
1115 (void)num;
1116
1117 switch (cmd) {
1118 case BIO_C_SET_FD:
1119 case BIO_C_GET_FD:
1120 r = -1;
1121 break;
1122 case BIO_CTRL_SET_CLOSE:
1123 case BIO_CTRL_DUP:
1124 case BIO_CTRL_FLUSH:
1125 r = 1;
1126 break;
1127 default:
1128 case BIO_CTRL_GET_CLOSE:
1129 r = 0;
1130 break;
1131 }
1132 return r;
1133}
1134#endif /* !COAP_DISABLE_TCP */
1135
1136static void
1137coap_set_user_prefs(SSL_CTX *ctx) {
1138 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
1139
1140#ifdef COAP_OPENSSL_SIGALGS
1141 SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1142 SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1143#endif
1144
1145#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1146 SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1147#endif
1148}
1149
1150#if COAP_DTLS_RETRANSMIT_MS != 1000
1151#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1152static unsigned int
1153timer_cb(SSL *s, unsigned int timer_us) {
1154 (void)s;
1155 if (timer_us == 0)
1156 return COAP_DTLS_RETRANSMIT_MS * 1000;
1157 else
1158 return 2 * timer_us;
1159}
1160#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1161#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
1162
1163void *
1165 coap_openssl_context_t *context;
1166 (void)coap_context;
1167
1168 context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
1169 if (context) {
1170 uint8_t cookie_secret[32];
1171
1172 memset(context, 0, sizeof(coap_openssl_context_t));
1173
1174 /* Set up DTLS context */
1175 context->dtls.ctx = SSL_CTX_new(DTLS_method());
1176 if (!context->dtls.ctx)
1177 goto error;
1178 SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1179 SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1180 SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1181 coap_set_user_prefs(context->dtls.ctx);
1182 memset(cookie_secret, 0, sizeof(cookie_secret));
1183 if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
1185 "Insufficient entropy for random cookie generation");
1186 coap_prng_lkd(cookie_secret, sizeof(cookie_secret));
1187 }
1188 context->dtls.cookie_hmac = HMAC_CTX_new();
1189 if (!context->dtls.cookie_hmac)
1190 goto error;
1191 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1192 EVP_sha256(), NULL))
1193 goto error;
1194 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1195 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1196 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1197 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1198#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1199 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1200#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1201 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1202 if (!context->dtls.meth)
1203 goto error;
1204 context->dtls.bio_addr = BIO_ADDR_new();
1205 if (!context->dtls.bio_addr)
1206 goto error;
1207 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1208 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1209 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1210 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1211 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1212 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1213
1214#if !COAP_DISABLE_TCP
1215 /* Set up TLS context */
1216 context->tls.ctx = SSL_CTX_new(TLS_method());
1217 if (!context->tls.ctx)
1218 goto error;
1219 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1220 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1221 coap_set_user_prefs(context->tls.ctx);
1222 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1223 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1224 if (!context->tls.meth)
1225 goto error;
1226 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1227 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1228 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1229 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1230 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1231 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1232#endif /* !COAP_DISABLE_TCP */
1233 }
1234
1235 return context;
1236
1237error:
1238 coap_dtls_free_context(context);
1239 return NULL;
1240}
1241
1242#if COAP_SERVER_SUPPORT
1243int
1244coap_dtls_context_set_spsk(coap_context_t *c_context,
1245 coap_dtls_spsk_t *setup_data
1246 ) {
1247 coap_openssl_context_t *o_context =
1248 ((coap_openssl_context_t *)c_context->dtls_context);
1249 BIO *bio;
1250
1251 if (!setup_data || !o_context)
1252 return 0;
1253
1254 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1255 coap_dtls_psk_server_callback);
1256#if !COAP_DISABLE_TCP
1257 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1258 coap_dtls_psk_server_callback);
1259#endif /* !COAP_DISABLE_TCP */
1260 if (setup_data->psk_info.hint.s) {
1261 char hint[COAP_DTLS_HINT_LENGTH];
1262 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1263 setup_data->psk_info.hint.s);
1264 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1265#if !COAP_DISABLE_TCP
1266 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1267#endif /* !COAP_DISABLE_TCP */
1268 }
1269 if (setup_data->validate_sni_call_back) {
1270#if OPENSSL_VERSION_NUMBER < 0x10101000L
1271 SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1272 &c_context->spsk_setup_data);
1273 SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1274 psk_tls_server_name_call_back);
1275#if !COAP_DISABLE_TCP
1276 SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1277 &c_context->spsk_setup_data);
1278 SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1279 psk_tls_server_name_call_back);
1280#endif /* !COAP_DISABLE_TCP */
1281#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1282 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1283 tls_client_hello_call_back,
1284 NULL);
1285#if !COAP_DISABLE_TCP
1286 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1287 tls_client_hello_call_back,
1288 NULL);
1289#endif /* !COAP_DISABLE_TCP */
1290#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1291 }
1292
1293 if (!o_context->dtls.ssl) {
1294 /* This is set up to handle new incoming sessions to a server */
1295 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1296 if (!o_context->dtls.ssl)
1297 return 0;
1298 bio = BIO_new(o_context->dtls.meth);
1299 if (!bio) {
1300 SSL_free(o_context->dtls.ssl);
1301 o_context->dtls.ssl = NULL;
1302 return 0;
1303 }
1304 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1305 SSL_set_app_data(o_context->dtls.ssl, NULL);
1306 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1307 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1308 }
1309 if (setup_data->ec_jpake) {
1310 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1311 }
1312 o_context->psk_pki_enabled |= IS_PSK;
1313 return 1;
1314}
1315#endif /* COAP_SERVER_SUPPORT */
1316
1317#if COAP_CLIENT_SUPPORT
1318int
1319coap_dtls_context_set_cpsk(coap_context_t *c_context,
1320 coap_dtls_cpsk_t *setup_data
1321 ) {
1322 coap_openssl_context_t *o_context =
1323 ((coap_openssl_context_t *)c_context->dtls_context);
1324 BIO *bio;
1325
1326 if (!setup_data || !o_context)
1327 return 0;
1328
1329 if (!o_context->dtls.ssl) {
1330 /* This is set up to handle new incoming sessions to a server */
1331 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1332 if (!o_context->dtls.ssl)
1333 return 0;
1334 bio = BIO_new(o_context->dtls.meth);
1335 if (!bio) {
1336 SSL_free(o_context->dtls.ssl);
1337 o_context->dtls.ssl = NULL;
1338 return 0;
1339 }
1340 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1341 SSL_set_app_data(o_context->dtls.ssl, NULL);
1342 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1343 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1344 }
1345 if (setup_data->ec_jpake) {
1346 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1347 }
1348 if (setup_data->use_cid) {
1349 coap_log_warn("OpenSSL has no Connection-ID support\n");
1350 }
1351 o_context->psk_pki_enabled |= IS_PSK;
1352 return 1;
1353}
1354#endif /* COAP_CLIENT_SUPPORT */
1355
1356static int
1357map_key_type(int asn1_private_key_type
1358 ) {
1359 switch (asn1_private_key_type) {
1361 return EVP_PKEY_NONE;
1362 case COAP_ASN1_PKEY_RSA:
1363 return EVP_PKEY_RSA;
1365 return EVP_PKEY_RSA2;
1366 case COAP_ASN1_PKEY_DSA:
1367 return EVP_PKEY_DSA;
1369 return EVP_PKEY_DSA1;
1371 return EVP_PKEY_DSA2;
1373 return EVP_PKEY_DSA3;
1375 return EVP_PKEY_DSA4;
1376 case COAP_ASN1_PKEY_DH:
1377 return EVP_PKEY_DH;
1378 case COAP_ASN1_PKEY_DHX:
1379 return EVP_PKEY_DHX;
1380 case COAP_ASN1_PKEY_EC:
1381 return EVP_PKEY_EC;
1383 return EVP_PKEY_HMAC;
1385 return EVP_PKEY_CMAC;
1387 return EVP_PKEY_TLS1_PRF;
1389 return EVP_PKEY_HKDF;
1390 default:
1391 coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1392 asn1_private_key_type);
1393 break;
1394 }
1395 return 0;
1396}
1397#if !COAP_DISABLE_TCP
1398static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1399
1400#if COAP_SERVER_SUPPORT
1401static int
1402server_alpn_callback(SSL *ssl COAP_UNUSED,
1403 const unsigned char **out,
1404 unsigned char *outlen,
1405 const unsigned char *in,
1406 unsigned int inlen,
1407 void *arg COAP_UNUSED
1408 ) {
1409 unsigned char *tout = NULL;
1410 int ret;
1411 if (inlen == 0)
1412 return SSL_TLSEXT_ERR_NOACK;
1413 ret = SSL_select_next_proto(&tout,
1414 outlen,
1415 coap_alpn,
1416 sizeof(coap_alpn),
1417 in,
1418 inlen);
1419 *out = tout;
1420 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1421}
1422#endif /* COAP_SERVER_SUPPORT */
1423#endif /* !COAP_DISABLE_TCP */
1424
1425static void
1426add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1427 long e;
1428
1429 /* Flush out existing errors */
1430 while (ERR_get_error() != 0) {
1431 }
1432
1433 if (!X509_STORE_add_cert(st, x509)) {
1434 while ((e = ERR_get_error()) != 0) {
1435 int r = ERR_GET_REASON(e);
1436 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1437 /* Not already added */
1438 coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1439 ERR_reason_error_string(e),
1440 ssl_function_definition(e));
1441 }
1442 }
1443 }
1444}
1445
1446#if OPENSSL_VERSION_NUMBER < 0x40000000L
1447static X509 *
1448missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1449 struct {
1450 const char *cert_id;
1451 X509 *cert;
1452 } params;
1453
1454 params.cert_id = cert_id;
1455 params.cert = NULL;
1456
1457 /* There is no ENGINE_load_cert() */
1458 if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1459 params.cert = NULL;
1460 }
1461 return params.cert;
1462}
1463
1464static int
1465check_pkcs11_engine(void) {
1466 static int already_tried = 0;
1467
1468 if (already_tried)
1469 return 0;
1470
1471 if (!pkcs11_engine) {
1472 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1473 if (!pkcs11_engine) {
1474 coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1475 COAP_OPENSSL_PKCS11_ENGINE_ID);
1476 already_tried = 1;
1477 return 0;
1478 }
1479 if (!ENGINE_init(pkcs11_engine)) {
1480 /* the engine couldn't initialise, release 'pkcs11_engine' */
1481 ENGINE_free(pkcs11_engine);
1482 pkcs11_engine = NULL;
1483 coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1484 already_tried = 1;
1485 return 0;
1486 }
1487 /*
1488 * ENGINE_init() returned a functional reference, so free the structural
1489 * reference from ENGINE_by_id().
1490 */
1491 ENGINE_free(pkcs11_engine);
1492 }
1493 return 1;
1494}
1495#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
1496
1497#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1498
1499static int
1500install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1501 const char *public_cert) {
1502 X509 *x509;
1503
1504 x509 = missing_ENGINE_load_cert(engine, public_cert);
1505 if (!x509) {
1506 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1507 "%s Certificate\n",
1508 public_cert,
1509 "Server");
1510 return 0;
1511 }
1512 if (!SSL_CTX_use_certificate(ctx, x509)) {
1513 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1514 "%s Certificate\n",
1515 public_cert,
1516 "Server");
1517 X509_free(x509);
1518 return 0;
1519 }
1520 X509_free(x509);
1521 return 1;
1522}
1523
1524static int
1525install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1526 const char *private_key) {
1527 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1528 private_key,
1529 NULL, NULL);
1530
1531 if (!pkey) {
1532 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1533 "%s Private Key\n",
1534 private_key,
1535 "Server");
1536 return 0;
1537 }
1538 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1539 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1540 "%s Private Key\n",
1541 private_key,
1542 "Server");
1543 EVP_PKEY_free(pkey);
1544 return 0;
1545 }
1546 EVP_PKEY_free(pkey);
1547 return 1;
1548}
1549
1550static int
1551install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1552 X509 *x509;
1553 X509_STORE *st;
1554
1555 x509 = missing_ENGINE_load_cert(engine,
1556 ca);
1557 if (!x509) {
1558 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1559 "%s CA Certificate\n",
1560 ca,
1561 "Server");
1562 return 0;
1563 }
1564 if (!SSL_CTX_add_client_CA(ctx, x509)) {
1565 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1566 "%s CA Certificate\n",
1567 ca,
1568 "Server");
1569 X509_free(x509);
1570 return 0;
1571 }
1572 st = SSL_CTX_get_cert_store(ctx);
1573 add_ca_to_cert_store(st, x509);
1574 X509_free(x509);
1575 return 1;
1576}
1577
1578static int
1579load_in_cas_ctx(SSL_CTX *ctx,
1580 const char *ca_file) {
1581 STACK_OF(X509_NAME) *cert_names;
1582 X509_STORE *st;
1583 BIO *in;
1584 X509 *x = NULL;
1585 char *rw_var = NULL;
1586 cert_names = SSL_load_client_CA_file(ca_file);
1587 if (cert_names != NULL)
1588 SSL_CTX_set_client_CA_list(ctx, cert_names);
1589 else {
1590 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1591 "client CA File\n",
1592 ca_file);
1593 return 0;
1594 }
1595
1596 /* Add CA to the trusted root CA store */
1597 st = SSL_CTX_get_cert_store(ctx);
1598 in = BIO_new(BIO_s_file());
1599 if (!in)
1600 return 0;
1601 /* Need to do this to not get a compiler warning about const parameters */
1602 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1603 if (!BIO_read_filename(in, rw_var)) {
1604 BIO_free(in);
1605 return 0;
1606 }
1607
1608 for (;;) {
1609 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1610 break;
1611 add_ca_to_cert_store(st, x);
1612 X509_free(x);
1613 }
1614 BIO_free(in);
1615 return 1;
1616}
1617
1618static int
1619setup_pki_server(SSL_CTX *ctx,
1620 const coap_dtls_pki_t *setup_data) {
1621 coap_dtls_key_t key;
1622
1623 /* Map over to the new define format to save code duplication */
1624 coap_dtls_map_key_type_to_define(setup_data, &key);
1625
1626 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1627
1628 /*
1629 * Configure the Private Key
1630 */
1631 if (key.key.define.private_key.u_byte &&
1632 key.key.define.private_key.u_byte[0]) {
1633 switch (key.key.define.private_key_def) {
1634 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1635 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1637 SSL_FILETYPE_PEM))) {
1640 &key, COAP_DTLS_ROLE_SERVER, 0);
1641 }
1642 break;
1643 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1644 if (key.key.define.private_key_len) {
1645 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1646 (int)key.key.define.private_key_len);
1647 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1648
1649 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1650 if (bp)
1651 BIO_free(bp);
1652 if (pkey)
1653 EVP_PKEY_free(pkey);
1656 &key, COAP_DTLS_ROLE_SERVER, 0);
1657 }
1658 if (bp)
1659 BIO_free(bp);
1660 if (pkey)
1661 EVP_PKEY_free(pkey);
1662 } else {
1665 &key, COAP_DTLS_ROLE_SERVER, 0);
1666 }
1667 break;
1668 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1671 &key, COAP_DTLS_ROLE_SERVER, 0);
1672 case COAP_PKI_KEY_DEF_DER: /* define private key */
1673 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1675 SSL_FILETYPE_ASN1))) {
1678 &key, COAP_DTLS_ROLE_SERVER, 0);
1679 }
1680 break;
1681 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1682 if (key.key.define.private_key_len == 0 ||
1683 !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1684 ctx,
1686 (long)key.key.define.private_key_len))) {
1689 &key, COAP_DTLS_ROLE_SERVER, 0);
1690 }
1691 break;
1692 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1693 if (!check_pkcs11_engine()) {
1694 return 0;
1695 }
1696 if (key.key.define.user_pin) {
1697 /* If not set, pin-value may be held in pkcs11: URI */
1698 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1699 "PIN",
1700 key.key.define.user_pin, 0) == 0) {
1701 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1702 key.key.define.user_pin);
1703 return 0;
1704 }
1705 }
1706 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1710 &key, COAP_DTLS_ROLE_SERVER, 0);
1711 }
1712 break;
1713 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1714 if (!defined_engine ||
1715 !install_engine_private_key_ctx(defined_engine, ctx,
1719 &key, COAP_DTLS_ROLE_SERVER, 0);
1720 }
1721 break;
1722 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1723 default:
1726 &key, COAP_DTLS_ROLE_SERVER, 0);
1727 }
1728 } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1731 &key, COAP_DTLS_ROLE_SERVER, 0);
1732 }
1733
1734 /*
1735 * Configure the Public Certificate / Key
1736 * OpenSSL < 1.1.1 and Server
1737 */
1738 if (key.key.define.public_cert.u_byte &&
1739 key.key.define.public_cert.u_byte[0]) {
1740 switch (key.key.define.public_cert_def) {
1741 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1742 if (key.key.define.ca.u_byte &&
1743 key.key.define.ca.u_byte[0]) {
1744 if (!(SSL_CTX_use_certificate_file(ctx,
1746 SSL_FILETYPE_PEM))) {
1749 &key, COAP_DTLS_ROLE_SERVER, 0);
1750 }
1751 } else {
1752 if (!SSL_CTX_use_certificate_chain_file(ctx,
1756 &key, COAP_DTLS_ROLE_SERVER, 0);
1757 }
1758 }
1759 break;
1760 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1761 if (key.key.define.public_cert_len) {
1762 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1763 (int)key.key.define.public_cert_len);
1764 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1765
1766 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1767 if (bp)
1768 BIO_free(bp);
1769 if (cert)
1770 X509_free(cert);
1773 &key, COAP_DTLS_ROLE_SERVER, 0);
1774 }
1775 if (bp)
1776 BIO_free(bp);
1777 if (cert)
1778 X509_free(cert);
1779 } else {
1782 &key, COAP_DTLS_ROLE_SERVER, 0);
1783 }
1784 break;
1785 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1788 &key, COAP_DTLS_ROLE_SERVER, 0);
1789 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1790 if (!(SSL_CTX_use_certificate_file(ctx,
1792 SSL_FILETYPE_ASN1))) {
1795 &key, COAP_DTLS_ROLE_SERVER, 0);
1796 }
1797 break;
1798 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1799 if (key.key.define.public_cert_len == 0 ||
1800 !(SSL_CTX_use_certificate_ASN1(ctx,
1801 (int)key.key.define.public_cert_len,
1802 key.key.define.public_cert.u_byte))) {
1805 &key, COAP_DTLS_ROLE_SERVER, 0);
1806 }
1807 break;
1808 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1809 if (!check_pkcs11_engine()) {
1810 return 0;
1811 }
1812 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1816 &key, COAP_DTLS_ROLE_SERVER, 0);
1817 }
1818 break;
1819 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1820 if (!defined_engine ||
1821 !install_engine_public_cert_ctx(defined_engine, ctx,
1825 &key, COAP_DTLS_ROLE_SERVER, 0);
1826 }
1827 break;
1828 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1829 default:
1832 &key, COAP_DTLS_ROLE_SERVER, 0);
1833 }
1834 } else if (key.key.define.private_key.u_byte &&
1835 key.key.define.private_key.u_byte[0]) {
1838 &key, COAP_DTLS_ROLE_SERVER, 0);
1839 }
1840
1841 /*
1842 * Configure the CA
1843 */
1844 if (key.key.define.ca.u_byte &&
1845 key.key.define.ca.u_byte[0]) {
1846 switch (key.key.define.ca_def) {
1848 if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1851 &key, COAP_DTLS_ROLE_SERVER, 0);
1852 }
1853 break;
1854 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1855 if (key.key.define.ca_len) {
1856 BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1857 (int)key.key.define.ca_len);
1858 X509 *x;
1859 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1860
1861 if (bp) {
1862 for (;;) {
1863 if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1864 break;
1865 add_ca_to_cert_store(st, x);
1866 SSL_CTX_add_client_CA(ctx, x);
1867 X509_free(x);
1868 }
1869 BIO_free(bp);
1870 }
1871 } else {
1874 &key, COAP_DTLS_ROLE_SERVER, 0);
1875 }
1876 break;
1877 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1880 &key, COAP_DTLS_ROLE_SERVER, 0);
1881 case COAP_PKI_KEY_DEF_DER: /* define ca */
1882 if (!(SSL_CTX_use_certificate_file(ctx,
1883 key.key.define.ca.s_byte,
1884 SSL_FILETYPE_ASN1))) {
1887 &key, COAP_DTLS_ROLE_SERVER, 0);
1888 }
1889 break;
1890 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1891 if (key.key.define.ca_len > 0) {
1892 /* Need to use a temp variable as it gets incremented*/
1893 const uint8_t *p = key.key.define.ca.u_byte;
1894 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1895 X509_STORE *st;
1896
1897 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1898 X509_free(x509);
1901 &key, COAP_DTLS_ROLE_SERVER, 0);
1902 }
1903
1904 /* Add CA to the trusted root CA store */
1905 st = SSL_CTX_get_cert_store(ctx);
1906 add_ca_to_cert_store(st, x509);
1907 X509_free(x509);
1908 }
1909 break;
1910 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1911 if (!check_pkcs11_engine()) {
1912 return 0;
1913 }
1914 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1915 key.key.define.ca.s_byte)) {
1918 &key, COAP_DTLS_ROLE_SERVER, 0);
1919 }
1920 break;
1921 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1922 if (!defined_engine ||
1923 !install_engine_ca_ctx(defined_engine, ctx,
1924 key.key.define.ca.s_byte)) {
1927 &key, COAP_DTLS_ROLE_SERVER, 0);
1928 }
1929 break;
1930 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1931 default:
1934 &key, COAP_DTLS_ROLE_SERVER, 0);
1935 }
1936 }
1937
1938 return 1;
1939}
1940#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT */
1941
1942#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1943
1944#if OPENSSL_VERSION_NUMBER < 0x40000000L
1945static int
1946install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1947 coap_dtls_role_t role) {
1948 X509 *x509;
1949
1950 x509 = missing_ENGINE_load_cert(engine, public_cert);
1951 if (!x509) {
1952 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1953 "%s Certificate\n",
1954 public_cert,
1955 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1956 return 0;
1957 }
1958 if (!SSL_use_certificate(ssl, x509)) {
1959 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1960 "%s Certificate\n",
1961 public_cert,
1962 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1963 X509_free(x509);
1964 return 0;
1965 }
1966 X509_free(x509);
1967 return 1;
1968}
1969
1970static int
1971install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1972 coap_dtls_role_t role) {
1973 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1974 private_key,
1975 NULL, NULL);
1976
1977 if (!pkey) {
1978 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1979 "%s Private Key\n",
1980 private_key,
1981 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1982 return 0;
1983 }
1984 if (!SSL_use_PrivateKey(ssl, pkey)) {
1985 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1986 "%s Private Key\n",
1987 private_key,
1988 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1989 EVP_PKEY_free(pkey);
1990 return 0;
1991 }
1992 EVP_PKEY_free(pkey);
1993 return 1;
1994}
1995
1996static int
1997install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1998 coap_dtls_role_t role) {
1999 X509 *x509;
2000 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2001 X509_STORE *st;
2002
2003 if (!ctx) {
2004 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
2005 "%s CA Certificate (no ctx)\n",
2006 ca,
2007 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2008 return 0;
2009 }
2010 x509 = missing_ENGINE_load_cert(engine,
2011 ca);
2012 if (!x509) {
2013 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
2014 "%s CA Certificate\n",
2015 ca,
2016 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2017 return 0;
2018 }
2019 if (!SSL_add_client_CA(ssl, x509)) {
2020 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
2021 "%s CA Certificate\n",
2022 ca,
2023 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
2024 X509_free(x509);
2025 return 0;
2026 }
2027 st = SSL_CTX_get_cert_store(ctx);
2028 add_ca_to_cert_store(st, x509);
2029 X509_free(x509);
2030 return 1;
2031}
2032#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2033
2034static int
2035load_in_cas(SSL *ssl,
2036 const char *ca_file, coap_dtls_role_t role) {
2037 X509_STORE *st;
2038 BIO *in;
2039 X509 *x = NULL;
2040 char *rw_var = NULL;
2041 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2042
2043 if (role == COAP_DTLS_ROLE_SERVER) {
2044 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
2045
2046 if (cert_names != NULL)
2047 SSL_set_client_CA_list(ssl, cert_names);
2048 else {
2049 return 0;
2050 }
2051 }
2052
2053 if (!ctx)
2054 return 0;
2055
2056 /* Add CA to the trusted root CA store */
2057 in = BIO_new(BIO_s_file());
2058 if (!in)
2059 return 0;
2060 /* Need to do this to not get a compiler warning about const parameters */
2061 memcpy(&rw_var, &ca_file, sizeof(rw_var));
2062 if (!BIO_read_filename(in, rw_var)) {
2063 BIO_free(in);
2064 return 0;
2065 }
2066 st = SSL_CTX_get_cert_store(ctx);
2067 for (;;) {
2068 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
2069 break;
2070 add_ca_to_cert_store(st, x);
2071 X509_free(x);
2072 }
2073 BIO_free(in);
2074 return 1;
2075}
2076
2077static int
2078setup_pki_ssl(SSL *ssl,
2079 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
2080 coap_dtls_key_t key;
2081
2082 /* Map over to the new define format to save code duplication */
2083 coap_dtls_map_key_type_to_define(setup_data, &key);
2084
2085 assert(key.key_type == COAP_PKI_KEY_DEFINE);
2086
2087 /*
2088 * Configure the Private Key
2089 */
2090 if (key.key.define.private_key.u_byte &&
2091 key.key.define.private_key.u_byte[0]) {
2092 switch (key.key.define.private_key_def) {
2093 case COAP_PKI_KEY_DEF_PEM: /* define private key */
2094 if (!(SSL_use_PrivateKey_file(ssl,
2096 SSL_FILETYPE_PEM))) {
2097 goto fail_bad_private;
2098 }
2099 break;
2100 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2101 if (key.key.define.private_key_len) {
2102 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2103 (int)key.key.define.private_key_len);
2104 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2105
2106 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2107 if (bp)
2108 BIO_free(bp);
2109 if (pkey)
2110 EVP_PKEY_free(pkey);
2111 goto fail_bad_private;
2112 }
2113 if (bp)
2114 BIO_free(bp);
2115 if (pkey)
2116 EVP_PKEY_free(pkey);
2117 } else {
2118 goto fail_none_private;
2119 }
2120 break;
2121 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2122 goto fail_ns_private;
2123 case COAP_PKI_KEY_DEF_DER: /* define private key */
2124 if (!(SSL_use_PrivateKey_file(ssl,
2126 SSL_FILETYPE_ASN1))) {
2127 goto fail_bad_private;
2128 }
2129 break;
2130 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2131 if (key.key.define.private_key_len == 0 ||
2132 !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2133 ssl,
2135 (long)key.key.define.private_key_len))) {
2136 goto fail_bad_private;
2137 }
2138 break;
2139 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2140#if OPENSSL_VERSION_NUMBER < 0x40000000L
2141 if (!check_pkcs11_engine()) {
2142 goto fail_bad_private;
2143 }
2144 if (key.key.define.user_pin) {
2145 /* If not set, pin-value may be held in pkcs11: URI */
2146 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2147 "PIN",
2148 key.key.define.user_pin, 0) == 0) {
2149 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2150 key.key.define.user_pin);
2151 goto fail_bad_private;
2152 }
2153 }
2154 if (!install_engine_private_key(pkcs11_engine, ssl,
2156 role)) {
2157 goto fail_bad_private;
2158 }
2159#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2160 goto fail_bad_private;
2161#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2162 break;
2163 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2164#if OPENSSL_VERSION_NUMBER < 0x40000000L
2165 if (!defined_engine ||
2166 !install_engine_private_key(defined_engine, ssl,
2168 role)) {
2169 goto fail_bad_private;
2170 }
2171 break;
2172#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2173 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2174 default:
2175 goto fail_ns_private;
2176 }
2177 } else if (role == COAP_DTLS_ROLE_SERVER ||
2179 key.key.define.public_cert.u_byte[0])) {
2180 goto fail_none_private;
2181 }
2182
2183 /*
2184 * Configure the Public Certificate / Key
2185 */
2186 if (key.key.define.public_cert.u_byte &&
2187 key.key.define.public_cert.u_byte[0]) {
2188 switch (key.key.define.public_cert_def) {
2189 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2190 if (key.key.define.ca.u_byte &&
2191 key.key.define.ca.u_byte[0]) {
2192 /* If CA is separately defined */
2193 if (!(SSL_use_certificate_file(ssl,
2195 SSL_FILETYPE_PEM))) {
2196 goto fail_bad_public;
2197 }
2198 } else {
2199 if (!SSL_use_certificate_chain_file(ssl,
2201 goto fail_bad_public;
2202 }
2203 }
2204 break;
2205 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2206 if (key.key.define.public_cert_len) {
2207 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2208 (int)key.key.define.public_cert_len);
2209 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2210
2211 if (!cert || !SSL_use_certificate(ssl, cert)) {
2212 if (bp)
2213 BIO_free(bp);
2214 if (cert)
2215 X509_free(cert);
2216 goto fail_bad_public;
2217 }
2218 if (bp)
2219 BIO_free(bp);
2220 if (cert)
2221 X509_free(cert);
2222 } else {
2223 goto fail_bad_public;
2224 }
2225 break;
2226 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2227 goto fail_ns_public;
2228 case COAP_PKI_KEY_DEF_DER: /* define public cert */
2229 if (!(SSL_use_certificate_file(ssl,
2231 SSL_FILETYPE_ASN1))) {
2232 goto fail_bad_public;
2233 }
2234 break;
2235 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2236 if (key.key.define.public_cert_len == 0 ||
2237 !(SSL_use_certificate_ASN1(ssl,
2239 (int)key.key.define.public_cert_len))) {
2240 goto fail_bad_public;
2241 }
2242 break;
2243 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2244#if OPENSSL_VERSION_NUMBER < 0x40000000L
2245 if (!check_pkcs11_engine()) {
2246 goto fail_bad_public;
2247 }
2248 if (!install_engine_public_cert(pkcs11_engine, ssl,
2250 role)) {
2251 goto fail_bad_public;
2252 }
2253#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2254 goto fail_bad_public;
2255#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2256 break;
2257 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2258#if OPENSSL_VERSION_NUMBER < 0x40000000L
2259 if (!defined_engine ||
2260 !install_engine_public_cert(defined_engine, ssl,
2262 role)) {
2263 goto fail_bad_public;
2264 }
2265 break;
2266#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2267 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2268 default:
2269 goto fail_ns_public;
2270 }
2271 } else if (role == COAP_DTLS_ROLE_SERVER ||
2273 key.key.define.private_key.u_byte[0])) {
2274
2277 &key, role, 0);
2278 }
2279
2280 /*
2281 * Configure the CA
2282 */
2283 if (key.key.define.ca.u_byte &&
2284 key.key.define.ca.u_byte[0]) {
2285 switch (key.key.define.ca_def) {
2287 if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2288 goto fail_bad_ca;
2289 }
2290 break;
2291 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2292 if (key.key.define.ca_len) {
2293 BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2294 (int)key.key.define.ca_len);
2295 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2296 X509 *x;
2297 X509_STORE *st = ctx? SSL_CTX_get_cert_store(ctx) : NULL;
2298
2299 if (bp) {
2300 for (;;) {
2301 if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2302 break;
2303 if (st)
2304 add_ca_to_cert_store(st, x);
2305 SSL_add_client_CA(ssl, x);
2306 X509_free(x);
2307 }
2308 BIO_free(bp);
2309 }
2310 } else {
2311 goto fail_bad_ca;
2312 }
2313 break;
2314 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2315 goto fail_ns_ca;
2316 case COAP_PKI_KEY_DEF_DER: /* define ca */
2317 if (!(SSL_use_certificate_file(ssl,
2318 key.key.define.ca.s_byte,
2319 SSL_FILETYPE_ASN1))) {
2320 goto fail_bad_ca;
2321 }
2322 break;
2323 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2324 if (key.key.define.ca_len > 0) {
2325 /* Need to use a temp variable as it gets incremented*/
2326 const uint8_t *p = key.key.define.ca.u_byte;
2327 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2328 X509_STORE *st;
2329 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2330
2331 if (role == COAP_DTLS_ROLE_SERVER) {
2332 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2333 X509_free(x509);
2334 goto fail_bad_ca;
2335 }
2336 }
2337
2338 /* Add CA to the trusted root CA store */
2339 st = ctx ? SSL_CTX_get_cert_store(ctx) : NULL;
2340 if (st)
2341 add_ca_to_cert_store(st, x509);
2342 X509_free(x509);
2343 }
2344 break;
2345 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2346#if OPENSSL_VERSION_NUMBER < 0x40000000L
2347 if (!check_pkcs11_engine()) {
2348 goto fail_bad_ca;
2349 }
2350 if (!install_engine_ca(pkcs11_engine, ssl,
2351 key.key.define.ca.s_byte,
2352 role)) {
2353 goto fail_bad_ca;
2354 }
2355#else /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2356 goto fail_bad_ca;
2357#endif /* OPENSSL_VERSION_NUMBER >= 0x40000000L */
2358 break;
2359 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2360#if OPENSSL_VERSION_NUMBER < 0x40000000L
2361 if (!defined_engine ||
2362 !install_engine_ca(defined_engine, ssl,
2363 key.key.define.ca.s_byte,
2364 role)) {
2365 goto fail_bad_ca;
2366 }
2367 break;
2368#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
2369 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2370 default:
2371 goto fail_ns_ca;
2372 }
2373 }
2374
2375 return 1;
2376
2377fail_bad_private:
2380 &key, role, 0);
2381fail_ns_private:
2384 &key, role, 0);
2385fail_none_private:
2388 &key, role, 0);
2389fail_bad_public:
2392 &key, role, 0);
2393fail_ns_public:
2396 &key, role, 0);
2397fail_bad_ca:
2400 &key, role, 0);
2401fail_ns_ca:
2404 &key, role, 0);
2405
2406}
2407#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2408
2409static char *
2410get_san_or_cn_from_cert(coap_session_t *session, X509 *x509, const char *sni_match) {
2411 if (x509) {
2412 char *cn;
2413 int n;
2414 STACK_OF(GENERAL_NAME) *san_list;
2415 char buffer[256];
2416
2417 (void)session;
2418 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2419 if (san_list) {
2420 int san_count = sk_GENERAL_NAME_num(san_list);
2421
2422 for (n = 0; n < san_count; n++) {
2423 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2424
2425 if (name && name->type == GEN_DNS) {
2426 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2427
2428 /* Make sure that there is not an embedded NUL in the dns_name */
2429 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2430 continue;
2431 if (sni_match) {
2432 if (strcmp(dns_name, sni_match)) {
2433 continue;
2434 }
2435 }
2436 cn = OPENSSL_strdup(dns_name);
2437 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2438 return cn;
2439 }
2440 }
2441 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2442 }
2443 /* Otherwise look for the CN= field */
2444 X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2445
2446 /* Need to emulate strcasestr() here. Looking for CN= */
2447 n = (int)strlen(buffer) - 3;
2448 cn = buffer;
2449 while (n > 0) {
2450 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2451 ((cn[1] == 'N') || (cn[1] == 'n')) &&
2452 (cn[2] == '=')) {
2453 cn += 3;
2454 break;
2455 }
2456 cn++;
2457 n--;
2458 }
2459 if (n > 0) {
2460 char *ecn = strchr(cn, '/');
2461 if (ecn) {
2462 cn[ecn-cn] = '\000';
2463 }
2464 if (sni_match) {
2465 if (!coap_pki_name_match_sni(cn, strlen(cn), sni_match)) {
2466 coap_log_debug(" %s: got CN '%s'\n",
2467 coap_session_str(session), cn);
2468 goto no_match;
2469 }
2470 }
2471 return OPENSSL_strdup(cn);
2472 }
2473no_match:
2474 if (!sni_match) {
2475 return NULL;
2476 }
2477 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2478 if (san_list) {
2479 int san_count = sk_GENERAL_NAME_num(san_list);
2480
2481 for (n = 0; n < san_count; n++) {
2482 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2483
2484 if (name && name->type == GEN_DNS) {
2485 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2486
2487 /* Make sure that there is not an embedded NUL in the dns_name */
2488 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2489 continue;
2490 coap_log_debug(" %s: got DNS.%d '%s'\n",
2491 coap_session_str(session), n + 1, dns_name);
2492 }
2493 }
2494 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2495 }
2496 }
2497 return NULL;
2498}
2499
2500static int
2501tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2502 int index = SSL_get_ex_data_X509_STORE_CTX_idx();
2503 SSL *ssl = index >= 0 ? X509_STORE_CTX_get_ex_data(ctx, index) : NULL;
2504 coap_session_t *session = ssl ? SSL_get_app_data(ssl) : NULL;
2505 coap_openssl_context_t *context = (session && session->context) ?
2506 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2507 coap_dtls_pki_t *setup_data = context ? &context->setup_data : NULL;
2508 int depth = X509_STORE_CTX_get_error_depth(ctx);
2509 int err = X509_STORE_CTX_get_error(ctx);
2510 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2511 char *cn = NULL;
2512
2513 if (!setup_data || !x509) {
2514 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2515 return 0;
2516 }
2517 if (depth == 0 && session->type == COAP_SESSION_TYPE_CLIENT && setup_data->client_sni &&
2518 !setup_data->allow_sni_cn_mismatch) {
2519 cn = get_san_or_cn_from_cert(session, x509, setup_data->client_sni);
2520 if (!cn) {
2521 coap_log_info(" %s: SNI '%s' not returned in certificate\n",
2522 coap_session_str(session), setup_data->client_sni);
2523 preverify_ok = 0;
2524 X509_STORE_CTX_set_error(ctx, X509_V_ERR_SUBJECT_ISSUER_MISMATCH);
2525 err = X509_V_ERR_SUBJECT_ISSUER_MISMATCH;
2526 }
2527 }
2528 if (!cn)
2529 cn = get_san_or_cn_from_cert(session, x509, NULL);
2530
2531 coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2532 depth, err, preverify_ok, cn);
2533
2534 /* Certificate - depth == 0 is the Client Cert */
2535 if (setup_data->validate_cn_call_back) {
2536 int length = i2d_X509(x509, NULL);
2537 uint8_t *base_buf;
2538 uint8_t *base_buf2 = base_buf = length > 0 ? OPENSSL_malloc(length) : NULL;
2539 int ret;
2540
2541 if (base_buf) {
2542 /* base_buf2 gets moved to the end */
2543 assert(i2d_X509(x509, &base_buf2) > 0);
2544 (void)base_buf2;
2546 setup_data->validate_cn_call_back(cn, base_buf, length, session,
2547 depth, preverify_ok,
2548 setup_data->cn_call_back_arg));
2549 if (!ret) {
2550 if (depth == 0) {
2551 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2552 } else {
2553 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2554 }
2555 preverify_ok = 0;
2556 }
2557 OPENSSL_free(base_buf);
2558 } else {
2559 X509_STORE_CTX_set_error(ctx, X509_V_ERR_UNSPECIFIED);
2560 preverify_ok = 0;
2561 }
2562 }
2563 if (!preverify_ok) {
2564 switch (err) {
2565 case X509_V_ERR_CERT_NOT_YET_VALID:
2566 case X509_V_ERR_CERT_HAS_EXPIRED:
2567 if (setup_data->allow_expired_certs)
2568 preverify_ok = 1;
2569 break;
2570 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2571 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2572 preverify_ok = 1;
2573 break;
2574 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2575 if (!setup_data->verify_peer_cert)
2576 preverify_ok = 1;
2577 break;
2578 case X509_V_ERR_UNABLE_TO_GET_CRL:
2579 if (setup_data->allow_no_crl)
2580 preverify_ok = 1;
2581 break;
2582 case X509_V_ERR_CRL_NOT_YET_VALID:
2583 case X509_V_ERR_CRL_HAS_EXPIRED:
2584 if (setup_data->allow_expired_crl)
2585 preverify_ok = 1;
2586 break;
2587 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2588 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2589 case X509_V_ERR_AKID_SKID_MISMATCH:
2590 if (!setup_data->verify_peer_cert)
2591 preverify_ok = 1;
2592 break;
2593 case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
2594 if (setup_data->allow_sni_cn_mismatch)
2595 preverify_ok = 1;
2596 break;
2597 default:
2598 break;
2599 }
2600 if (setup_data->cert_chain_validation &&
2601 depth > (setup_data->cert_chain_verify_depth + 1)) {
2602 preverify_ok = 0;
2603 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2604 X509_STORE_CTX_set_error(ctx, err);
2605 }
2606 if (!preverify_ok) {
2607 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2608 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2609 coap_session_str(session),
2610 "Unknown CA", cn ? cn : "?", depth);
2611 } else {
2612 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2613 coap_session_str(session),
2614 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2615 }
2616 } else {
2617 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
2618 coap_session_str(session),
2619 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2620 }
2621 }
2622 OPENSSL_free(cn);
2623 return preverify_ok;
2624}
2625
2626#if COAP_SERVER_SUPPORT
2627#if OPENSSL_VERSION_NUMBER < 0x10101000L
2628/* OpenSSL < 1.1.1 */
2629/*
2630 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2631 * it is possible to determine whether this is a PKI or PSK incoming
2632 * request and adjust the ciphers if necessary
2633 *
2634 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2635 */
2636static int
2637tls_secret_call_back(SSL *ssl,
2638 void *secret,
2639 int *secretlen,
2640 STACK_OF(SSL_CIPHER) *peer_ciphers,
2641 const SSL_CIPHER **cipher COAP_UNUSED,
2642 void *arg) {
2643 int ii;
2644 int psk_requested = 0;
2645 coap_session_t *session;
2646 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2647
2648 session = (coap_session_t *)SSL_get_app_data(ssl);
2649 assert(session != NULL);
2650 assert(session->context != NULL);
2651 if (session == NULL ||
2652 session->context == NULL)
2653 return 0;
2654
2655 if ((session->psk_key) ||
2656 (session->context->spsk_setup_data.psk_info.key.s &&
2657 session->context->spsk_setup_data.psk_info.key.length)) {
2658 /* Is PSK being requested - if so, we need to change algorithms */
2659 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2660 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2661
2662 coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2663 SSL_CIPHER_get_name(peer_cipher));
2664 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2665 psk_requested = 1;
2666 break;
2667 }
2668 }
2669 }
2670 if (!psk_requested) {
2671 coap_log_debug(" %s: Using PKI ciphers\n",
2672 coap_session_str(session));
2673
2674 if (setup_data->verify_peer_cert) {
2675 SSL_set_verify(ssl,
2676 SSL_VERIFY_PEER |
2677 SSL_VERIFY_CLIENT_ONCE |
2678 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2679 tls_verify_call_back);
2680 } else {
2681 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2682 }
2683
2684 /* Check CA Chain */
2685 if (setup_data->cert_chain_validation)
2686 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2687
2688 /* Certificate Revocation */
2689 if (setup_data->check_cert_revocation) {
2690 X509_VERIFY_PARAM *param;
2691
2692 param = X509_VERIFY_PARAM_new();
2693 if (param) {
2694 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2695 SSL_set1_param(ssl, param);
2696 X509_VERIFY_PARAM_free(param);
2697 }
2698 }
2699 if (setup_data->additional_tls_setup_call_back) {
2700 /* Additional application setup wanted */
2701 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2702 return 0;
2703 }
2704 } else {
2705 if (session->psk_key) {
2706 memcpy(secret, session->psk_key->s, session->psk_key->length);
2707 *secretlen = session->psk_key->length;
2708 } else if (session->context->spsk_setup_data.psk_info.key.s &&
2709 session->context->spsk_setup_data.psk_info.key.length) {
2710 memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2711 session->context->spsk_setup_data.psk_info.key.length);
2712 *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2713 }
2714 coap_log_debug(" %s: Setting PSK ciphers\n",
2715 coap_session_str(session));
2716 /*
2717 * Force a PSK algorithm to be used, so we do PSK
2718 */
2719 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2720#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
2721 /*
2722 * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
2723 * Potentially opens up security vulnerabilities.
2724 * Default value is 1.
2725 */
2726 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
2727#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
2728 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2729 }
2730 return 0;
2731}
2732
2733/* OpenSSL < 1.1.1 */
2734/*
2735 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2736 * called so it is possible to set up an extra callback to determine whether
2737 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2738 *
2739 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2740 * coap_dtls_context_set_pki()
2741 */
2742static int
2743tls_server_name_call_back(SSL *ssl,
2744 int *sd COAP_UNUSED,
2745 void *arg) {
2746 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2747
2748 if (!ssl) {
2749 return SSL_TLSEXT_ERR_NOACK;
2750 }
2751
2752 if (setup_data->validate_sni_call_back) {
2753 /* SNI checking requested */
2754 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2755 coap_openssl_context_t *context = (session && session->context) ?
2756 ((coap_openssl_context_t *)session->context->dtls_context) : NULL;
2757 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2758 size_t i;
2759
2760 if (!context)
2761 return SSL_TLSEXT_ERR_NOACK;
2762
2763 if (!sni || !sni[0]) {
2764 sni = "";
2765 }
2766 for (i = 0; i < context->sni_count; i++) {
2767 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2768 break;
2769 }
2770 }
2771 if (i == context->sni_count) {
2772 SSL_CTX *ctx;
2773 coap_dtls_pki_t sni_setup_data;
2774 coap_dtls_key_t *new_entry;
2775
2776 coap_lock_callback_ret(new_entry,
2777 setup_data->validate_sni_call_back(sni,
2778 setup_data->sni_call_back_arg));
2779 if (!new_entry) {
2780 return SSL_TLSEXT_ERR_ALERT_FATAL;
2781 }
2782 /* Need to set up a new SSL_CTX to switch to */
2783 if (session->proto == COAP_PROTO_DTLS) {
2784 /* Set up DTLS context */
2785 ctx = SSL_CTX_new(DTLS_method());
2786 if (!ctx)
2787 goto error;
2788 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2789 SSL_CTX_set_app_data(ctx, &context->dtls);
2790 SSL_CTX_set_read_ahead(ctx, 1);
2791 coap_set_user_prefs(ctx);
2792 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2793 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2794 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2795 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2796 }
2797#if !COAP_DISABLE_TCP
2798 else {
2799 /* Set up TLS context */
2800 ctx = SSL_CTX_new(TLS_method());
2801 if (!ctx)
2802 goto error;
2803 SSL_CTX_set_app_data(ctx, &context->tls);
2804 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2805 coap_set_user_prefs(ctx);
2806 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2807 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2808 }
2809#endif /* !COAP_DISABLE_TCP */
2810 sni_setup_data = *setup_data;
2811 sni_setup_data.pki_key = *new_entry;
2812 setup_pki_server(ctx, &sni_setup_data);
2813
2814 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2815 (context->sni_count+1)*sizeof(sni_entry));
2816 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2817 context->sni_entry_list[context->sni_count].ctx = ctx;
2818 context->sni_count++;
2819 }
2820 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2821 SSL_clear_options(ssl, 0xFFFFFFFFL);
2822 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2823 }
2824
2825 /*
2826 * Have to do extra call back next to get client algorithms
2827 * SSL_get_client_ciphers() does not work this early on
2828 */
2829 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2830 return SSL_TLSEXT_ERR_OK;
2831
2832error:
2833 return SSL_TLSEXT_ERR_ALERT_WARNING;
2834}
2835
2836/* OpenSSL < 1.1.1 */
2837/*
2838 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2839 * called to see if SNI is being used.
2840 *
2841 * Set up by SSL_CTX_set_tlsext_servername_callback()
2842 * in coap_dtls_context_set_spsk()
2843 */
2844static int
2845psk_tls_server_name_call_back(SSL *ssl,
2846 int *sd COAP_UNUSED,
2847 void *arg
2848 ) {
2849 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2850
2851 if (!ssl) {
2852 return SSL_TLSEXT_ERR_NOACK;
2853 }
2854
2855 if (setup_data->validate_sni_call_back) {
2856 /* SNI checking requested */
2857 coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2858 coap_openssl_context_t *o_context = (c_session && c_session->context) ?
2859 ((coap_openssl_context_t *)c_session->context->dtls_context) : NULL;
2860 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2861 size_t i;
2862 char lhint[COAP_DTLS_HINT_LENGTH];
2863
2864 if (!o_context)
2865 return SSL_TLSEXT_ERR_ALERT_FATAL;
2866
2867 if (!sni || !sni[0]) {
2868 sni = "";
2869 }
2870 for (i = 0; i < o_context->psk_sni_count; i++) {
2871 if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2872 break;
2873 }
2874 }
2875 if (i == o_context->psk_sni_count) {
2876 SSL_CTX *ctx;
2877 const coap_dtls_spsk_info_t *new_entry;
2878
2879 coap_lock_callback_ret(new_entry,
2880 setup_data->validate_sni_call_back(sni,
2881 c_session,
2882 setup_data->sni_call_back_arg));
2883 if (!new_entry) {
2884 return SSL_TLSEXT_ERR_ALERT_FATAL;
2885 }
2886 /* Need to set up a new SSL_CTX to switch to */
2887 if (c_session->proto == COAP_PROTO_DTLS) {
2888 /* Set up DTLS context */
2889 ctx = SSL_CTX_new(DTLS_method());
2890 if (!ctx)
2891 goto error;
2892 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2893 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2894 SSL_CTX_set_read_ahead(ctx, 1);
2895 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2896 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2897 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2898 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2899 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2900 }
2901#if !COAP_DISABLE_TCP
2902 else {
2903 /* Set up TLS context */
2904 ctx = SSL_CTX_new(TLS_method());
2905 if (!ctx)
2906 goto error;
2907 SSL_CTX_set_app_data(ctx, &o_context->tls);
2908 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2909 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2910 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2911 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2912 }
2913#endif /* !COAP_DISABLE_TCP */
2914
2915 o_context->psk_sni_entry_list =
2916 OPENSSL_realloc(o_context->psk_sni_entry_list,
2917 (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2918 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2919 OPENSSL_strdup(sni);
2920 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2921 *new_entry;
2922 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2923 ctx;
2924 o_context->psk_sni_count++;
2925 }
2926 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2927 SSL_clear_options(ssl, 0xFFFFFFFFL);
2928 SSL_set_options(ssl,
2929 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2931 &o_context->psk_sni_entry_list[i].psk_info.key);
2932 snprintf(lhint, sizeof(lhint), "%.*s",
2933 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2934 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2935 SSL_use_psk_identity_hint(ssl, lhint);
2936 }
2937
2938 /*
2939 * Have to do extra call back next to get client algorithms
2940 * SSL_get_client_ciphers() does not work this early on
2941 */
2942 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2943 return SSL_TLSEXT_ERR_OK;
2944
2945error:
2946 return SSL_TLSEXT_ERR_ALERT_WARNING;
2947}
2948#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2949/* OpenSSL >= 1.1.1 */
2950/*
2951 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2952 * called early in the Client Hello processing so it is possible to determine
2953 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2954 * necessary.
2955 *
2956 * Set up by SSL_CTX_set_client_hello_cb().
2957 */
2958static int
2959tls_client_hello_call_back(SSL *ssl,
2960 int *al,
2961 void *arg COAP_UNUSED
2962 ) {
2963 coap_session_t *session;
2964 coap_openssl_context_t *dtls_context;
2965 coap_dtls_pki_t *setup_data;
2966 int psk_requested = 0;
2967 const unsigned char *out;
2968 size_t outlen;
2969
2970 if (!ssl) {
2971 *al = SSL_AD_INTERNAL_ERROR;
2972 return SSL_CLIENT_HELLO_ERROR;
2973 }
2974 session = (coap_session_t *)SSL_get_app_data(ssl);
2975 assert(session != NULL);
2976 assert(session->context != NULL);
2977 assert(session->context->dtls_context != NULL);
2978 if (session == NULL ||
2979 session->context == NULL ||
2980 session->context->dtls_context == NULL) {
2981 *al = SSL_AD_INTERNAL_ERROR;
2982 return SSL_CLIENT_HELLO_ERROR;
2983 }
2984 dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2985 setup_data = &dtls_context->setup_data;
2986
2987 /*
2988 * See if PSK being requested
2989 */
2990 if ((session->psk_key) ||
2991 (session->context->spsk_setup_data.psk_info.key.s &&
2992 session->context->spsk_setup_data.psk_info.key.length)) {
2993 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2994 STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2995 STACK_OF(SSL_CIPHER) *scsvc = NULL;
2996
2997 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2998 SSL_client_hello_isv2(ssl),
2999 &peer_ciphers, &scsvc)) {
3000 int ii;
3001 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
3002 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
3003
3005 "Client cipher: %s (%04x)\n",
3006 SSL_CIPHER_get_name(peer_cipher),
3007 SSL_CIPHER_get_protocol_id(peer_cipher));
3008 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
3009 psk_requested = 1;
3010 break;
3011 }
3012 }
3013 }
3014 sk_SSL_CIPHER_free(peer_ciphers);
3015 sk_SSL_CIPHER_free(scsvc);
3016 }
3017
3018 if (psk_requested) {
3019 /*
3020 * Client has requested PSK and it is supported
3021 */
3022 coap_dtls_spsk_t *psk_setup_data = &session->context->spsk_setup_data;
3023
3024 if (psk_setup_data->validate_sni_call_back) {
3025 const char *sni = "";
3026 char *sni_tmp = NULL;
3027 char lhint[COAP_DTLS_HINT_LENGTH];
3028 const coap_dtls_spsk_info_t *new_entry;
3029
3030 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name,
3031 &out, &outlen) &&
3032 outlen > 5 &&
3033 (((out[0] << 8) + out[1] + 2) == (int)outlen) &&
3034 out[2] == TLSEXT_NAMETYPE_host_name &&
3035 (((out[3] << 8) + out[4] + 2 + 3) == (int)outlen)) {
3036 /* Skip over length, type and length */
3037 out += 5;
3038 outlen -= 5;
3039 sni_tmp = OPENSSL_malloc(outlen + 1);
3040 if (sni_tmp) {
3041 sni_tmp[outlen] = '\000';
3042 memcpy(sni_tmp, out, outlen);
3043 sni = sni_tmp;
3044 }
3045 }
3046
3047 coap_lock_callback_ret(new_entry,
3048 psk_setup_data->validate_sni_call_back(
3049 sni,
3050 session,
3051 psk_setup_data->sni_call_back_arg));
3052 if (!new_entry) {
3053 if (sni_tmp) {
3054 OPENSSL_free(sni_tmp);
3055 }
3056 *al = SSL_AD_UNRECOGNIZED_NAME;
3057 return SSL_CLIENT_HELLO_ERROR;
3058 }
3059
3060 if (sni_tmp) {
3061 OPENSSL_free(sni_tmp);
3062 }
3063 if (coap_session_refresh_psk_hint(session, &new_entry->hint) == 0) {
3064 *al = SSL_AD_INTERNAL_ERROR;
3065 return SSL_CLIENT_HELLO_ERROR;
3066 }
3067 if (coap_session_refresh_psk_key(session, &new_entry->key) == 0) {
3068 *al = SSL_AD_INTERNAL_ERROR;
3069 return SSL_CLIENT_HELLO_ERROR;
3070 }
3071 if (new_entry->hint.s) {
3072 snprintf(lhint, sizeof(lhint), "%.*s",
3073 (int)new_entry->hint.length,
3074 new_entry->hint.s);
3075 SSL_use_psk_identity_hint(ssl, lhint);
3076 }
3077 }
3078 coap_log_debug(" %s: PSK request\n",
3079 coap_session_str(session));
3080 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3081 if (setup_data->additional_tls_setup_call_back) {
3082 /* Additional application setup wanted */
3083 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3084 return 0;
3085 }
3086 return SSL_CLIENT_HELLO_SUCCESS;
3087 }
3088
3089 /*
3090 * Handle Certificate requests
3091 */
3092
3093 /*
3094 * Determine what type of certificate is being requested
3095 */
3096 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
3097 &out, &outlen)) {
3098 size_t ii;
3099 for (ii = 0; ii < outlen; ii++) {
3100 switch (out[ii]) {
3101 case 0:
3102 /* RFC6091 X.509 */
3103 if (outlen >= 2) {
3104 /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
3105 goto is_x509;
3106 }
3107 break;
3108 case 2:
3109 /* RFC7250 RPK - not yet supported */
3110 break;
3111 default:
3112 break;
3113 }
3114 }
3115 *al = SSL_AD_UNSUPPORTED_EXTENSION;
3116 return SSL_CLIENT_HELLO_ERROR;
3117 }
3118
3119is_x509:
3120 if (setup_data->validate_sni_call_back) {
3121 /*
3122 * SNI checking requested
3123 */
3124 coap_dtls_pki_t sni_setup_data;
3125 coap_openssl_context_t *context =
3126 ((coap_openssl_context_t *)session->context->dtls_context);
3127 const char *sni = "";
3128 char *sni_tmp = NULL;
3129 size_t i;
3130
3131 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3132 outlen > 5 &&
3133 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3134 out[2] == TLSEXT_NAMETYPE_host_name &&
3135 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3136 /* Skip over length, type and length */
3137 out += 5;
3138 outlen -= 5;
3139 sni_tmp = OPENSSL_malloc(outlen+1);
3140 sni_tmp[outlen] = '\000';
3141 memcpy(sni_tmp, out, outlen);
3142 sni = sni_tmp;
3143 }
3144 /* Is this a cached entry? */
3145 for (i = 0; i < context->sni_count; i++) {
3146 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
3147 break;
3148 }
3149 }
3150 if (i == context->sni_count) {
3151 /*
3152 * New SNI request
3153 */
3154 coap_dtls_key_t *new_entry;
3155
3156 coap_lock_callback_ret(new_entry,
3157 setup_data->validate_sni_call_back(sni,
3158 setup_data->sni_call_back_arg));
3159 if (!new_entry) {
3160 *al = SSL_AD_UNRECOGNIZED_NAME;
3161 return SSL_CLIENT_HELLO_ERROR;
3162 }
3163
3164
3165 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
3166 (context->sni_count+1)*sizeof(sni_entry));
3167 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
3168 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
3169 context->sni_count++;
3170 }
3171 if (sni_tmp) {
3172 OPENSSL_free(sni_tmp);
3173 }
3174 sni_setup_data = *setup_data;
3175 sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
3176 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
3177 } else {
3178 setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
3179 }
3180
3181 coap_log_debug(" %s: Using PKI ciphers\n",
3182 coap_session_str(session));
3183
3184 if (setup_data->verify_peer_cert) {
3185 SSL_set_verify(ssl,
3186 SSL_VERIFY_PEER |
3187 SSL_VERIFY_CLIENT_ONCE |
3188 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3189 tls_verify_call_back);
3190 } else {
3191 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3192 }
3193
3194 /* Check CA Chain */
3195 if (setup_data->cert_chain_validation)
3196 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
3197
3198 /* Certificate Revocation */
3199 if (setup_data->check_cert_revocation) {
3200 X509_VERIFY_PARAM *param;
3201
3202 param = X509_VERIFY_PARAM_new();
3203 if (param) {
3204 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3205 SSL_set1_param(ssl, param);
3206 X509_VERIFY_PARAM_free(param);
3207 }
3208 }
3209 if (setup_data->additional_tls_setup_call_back) {
3210 /* Additional application setup wanted */
3211 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
3212 return 0;
3213 }
3214 return SSL_CLIENT_HELLO_SUCCESS;
3215}
3216
3217#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3218#endif /* COAP_SERVER_SUPPORT */
3219
3220int
3222 const coap_dtls_pki_t *setup_data,
3223 const coap_dtls_role_t role) {
3224 coap_openssl_context_t *context =
3225 ((coap_openssl_context_t *)ctx->dtls_context);
3226 BIO *bio;
3227 if (!setup_data)
3228 return 0;
3229 context->setup_data = *setup_data;
3230
3231#if OPENSSL_VERSION_NUMBER < 0x40000000L
3232 if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3233 if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3234 context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3235 context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3236 if (!defined_engine) {
3237 coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3238 return 0;
3239 }
3240 }
3241 }
3242#endif /* OPENSSL_VERSION_NUMBER < 0x40000000L */
3243
3244 if (!context->setup_data.verify_peer_cert) {
3245 /* Needs to be clear so that no CA DNs are transmitted */
3246 context->setup_data.check_common_ca = 0;
3247 /* Allow all of these but warn if issue */
3248 context->setup_data.allow_self_signed = 1;
3249 context->setup_data.allow_expired_certs = 1;
3250 context->setup_data.cert_chain_validation = 1;
3251 context->setup_data.cert_chain_verify_depth = 10;
3252 context->setup_data.check_cert_revocation = 1;
3253 context->setup_data.allow_no_crl = 1;
3254 context->setup_data.allow_expired_crl = 1;
3255 context->setup_data.allow_bad_md_hash = 1;
3256 context->setup_data.allow_short_rsa_length = 1;
3257 }
3258#if COAP_SERVER_SUPPORT
3259 if (role == COAP_DTLS_ROLE_SERVER) {
3260 if (context->dtls.ctx) {
3261 /* SERVER DTLS */
3262#if OPENSSL_VERSION_NUMBER < 0x10101000L
3263 if (!setup_pki_server(context->dtls.ctx, setup_data))
3264 return 0;
3265#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3266 /* libcoap is managing TLS connection based on setup_data options */
3267 /* Need to set up logic to differentiate between a PSK or PKI session */
3268 /*
3269 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3270 * which is not in 1.1.0
3271 */
3272#if OPENSSL_VERSION_NUMBER < 0x10101000L
3273 if (SSLeay() >= 0x10101000L) {
3274 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3275 "no certificate checking\n",
3276 OPENSSL_VERSION_NUMBER, SSLeay());
3277 }
3278 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3279 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3280 tls_server_name_call_back);
3281#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3282 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3283 tls_client_hello_call_back,
3284 NULL);
3285#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3286 }
3287#if !COAP_DISABLE_TCP
3288 if (context->tls.ctx) {
3289 /* SERVER TLS */
3290#if OPENSSL_VERSION_NUMBER < 0x10101000L
3291 if (!setup_pki_server(context->tls.ctx, setup_data))
3292 return 0;
3293#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3294 /* libcoap is managing TLS connection based on setup_data options */
3295 /* Need to set up logic to differentiate between a PSK or PKI session */
3296 /*
3297 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3298 * which is not in 1.1.0
3299 */
3300#if OPENSSL_VERSION_NUMBER < 0x10101000L
3301 if (SSLeay() >= 0x10101000L) {
3302 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3303 "no certificate checking\n",
3304 OPENSSL_VERSION_NUMBER, SSLeay());
3305 }
3306 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3307 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3308 tls_server_name_call_back);
3309#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3310 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3311 tls_client_hello_call_back,
3312 NULL);
3313#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3314 /* TLS Only */
3315 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3316 }
3317#endif /* !COAP_DISABLE_TCP */
3318 }
3319#else /* ! COAP_SERVER_SUPPORT */
3320 (void)role;
3321#endif /* ! COAP_SERVER_SUPPORT */
3322#if COAP_CLIENT_SUPPORT
3323 if (role == COAP_DTLS_ROLE_CLIENT) {
3324 context->psk_pki_enabled &= ~IS_PSK;
3325 }
3326#endif /* COAP_CLIENT_SUPPORT */
3327
3328 if (!context->dtls.ssl) {
3329 /* This is set up to handle new incoming sessions to a server */
3330 context->dtls.ssl = SSL_new(context->dtls.ctx);
3331 if (!context->dtls.ssl)
3332 return 0;
3333 bio = BIO_new(context->dtls.meth);
3334 if (!bio) {
3335 SSL_free(context->dtls.ssl);
3336 context->dtls.ssl = NULL;
3337 return 0;
3338 }
3339 SSL_set_bio(context->dtls.ssl, bio, bio);
3340 SSL_set_app_data(context->dtls.ssl, NULL);
3341 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3342 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3343 }
3344 context->psk_pki_enabled |= IS_PKI;
3345 if (setup_data->use_cid) {
3346 coap_log_warn("OpenSSL has no Connection-ID support\n");
3347 }
3348 return 1;
3349}
3350
3351int
3353 const char *ca_file,
3354 const char *ca_dir
3355 ) {
3356 coap_openssl_context_t *context =
3357 ((coap_openssl_context_t *)ctx->dtls_context);
3358 if (context->dtls.ctx) {
3359 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3360 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3361 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3362 return 0;
3363 }
3364 }
3365#if !COAP_DISABLE_TCP
3366 if (context->tls.ctx) {
3367 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3368 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3369 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3370 return 0;
3371 }
3372 }
3373#endif /* !COAP_DISABLE_TCP */
3374 return 1;
3375}
3376
3377int
3379#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3380 coap_openssl_context_t *context =
3381 ((coap_openssl_context_t *)ctx->dtls_context);
3382 if (context->dtls.ctx) {
3383 if (!SSL_CTX_set_default_verify_paths(context->dtls.ctx)) {
3384 coap_log_warn("Unable to load trusted root CAs\n");
3385 return 0;
3386 }
3387 }
3388#if !COAP_DISABLE_TCP
3389 if (context->tls.ctx) {
3390 if (!SSL_CTX_set_default_verify_paths(context->tls.ctx)) {
3391 coap_log_warn("Unable to load trusted root CAs\n");
3392 return 0;
3393 }
3394 }
3395#endif /* !COAP_DISABLE_TCP */
3396 return 1;
3397#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3398 (void)ctx;
3399 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3400 "not supported for OpenSSL < v3.0.0\n");
3401 return 0;
3402#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3403}
3404
3405int
3407 coap_openssl_context_t *context =
3408 ((coap_openssl_context_t *)ctx->dtls_context);
3409 return context->psk_pki_enabled ? 1 : 0;
3410}
3411
3412
3413void
3414coap_dtls_free_context(void *handle) {
3415 size_t i;
3416 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3417
3418 if (context->dtls.ssl)
3419 SSL_free(context->dtls.ssl);
3420 if (context->dtls.ctx)
3421 SSL_CTX_free(context->dtls.ctx);
3422 if (context->dtls.cookie_hmac)
3423 HMAC_CTX_free(context->dtls.cookie_hmac);
3424 if (context->dtls.meth)
3425 BIO_meth_free(context->dtls.meth);
3426 if (context->dtls.bio_addr)
3427 BIO_ADDR_free(context->dtls.bio_addr);
3428#if !COAP_DISABLE_TCP
3429 if (context->tls.ctx)
3430 SSL_CTX_free(context->tls.ctx);
3431 if (context->tls.meth)
3432 BIO_meth_free(context->tls.meth);
3433#endif /* !COAP_DISABLE_TCP */
3434 for (i = 0; i < context->sni_count; i++) {
3435 OPENSSL_free(context->sni_entry_list[i].sni);
3436#if OPENSSL_VERSION_NUMBER < 0x10101000L
3437 SSL_CTX_free(context->sni_entry_list[i].ctx);
3438#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3439 }
3440 if (context->sni_count)
3441 OPENSSL_free(context->sni_entry_list);
3442#if OPENSSL_VERSION_NUMBER < 0x10101000L
3443 for (i = 0; i < context->psk_sni_count; i++) {
3444 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3445 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3446 }
3447 if (context->psk_sni_count)
3448 OPENSSL_free(context->psk_sni_entry_list);
3449#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3450 coap_free_type(COAP_STRING, context);
3451}
3452
3453#if COAP_SERVER_SUPPORT
3454void *
3455coap_dtls_new_server_session(coap_session_t *session) {
3456 BIO *nbio = NULL;
3457 SSL *nssl = NULL, *ssl = NULL;
3458 coap_ssl_data *data;
3459 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3460 int r;
3461 const coap_bin_const_t *psk_hint;
3462 BIO *rbio;
3463
3464 nssl = SSL_new(dtls->ctx);
3465 if (!nssl)
3466 goto error;
3467 nbio = BIO_new(dtls->meth);
3468 if (!nbio)
3469 goto error;
3470 SSL_set_bio(nssl, nbio, nbio);
3471 SSL_set_app_data(nssl, NULL);
3472 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3473 SSL_set_mtu(nssl, (long)session->mtu);
3474 ssl = dtls->ssl;
3475 dtls->ssl = nssl;
3476 nssl = NULL;
3477 SSL_set_app_data(ssl, session);
3478
3479 rbio = SSL_get_rbio(ssl);
3480 data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3481 if (!data)
3482 goto error;
3483 data->session = session;
3484
3485 /* hint may get updated if/when handling SNI callback */
3486 psk_hint = coap_get_session_server_psk_hint(session);
3487 if (psk_hint != NULL && psk_hint->length) {
3488 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3489
3490 if (hint) {
3491 memcpy(hint, psk_hint->s, psk_hint->length);
3492 hint[psk_hint->length] = '\000';
3493 SSL_use_psk_identity_hint(ssl, hint);
3494 OPENSSL_free(hint);
3495 } else {
3496 coap_log_warn("hint malloc failure\n");
3497 }
3498 }
3499
3500 r = SSL_accept(ssl);
3501 if (r == -1) {
3502 int err = SSL_get_error(ssl, r);
3503 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3504 r = 0;
3505 }
3506
3507 if (r == 0) {
3508 SSL_free(ssl);
3509 return NULL;
3510 }
3511
3512 return ssl;
3513
3514error:
3515 if (nssl)
3516 SSL_free(nssl);
3517 return NULL;
3518}
3519#endif /* COAP_SERVER_SUPPORT */
3520
3521#if COAP_CLIENT_SUPPORT
3522static int
3523setup_client_ssl_session(coap_session_t *session, SSL *ssl
3524 ) {
3525 coap_openssl_context_t *context =
3526 ((coap_openssl_context_t *)session->context->dtls_context);
3527
3528 if (context->psk_pki_enabled & IS_PSK) {
3529 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3530
3531 /* Issue SNI if requested */
3532 if (setup_data->client_sni &&
3533 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3534 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3535 setup_data->client_sni);
3536 }
3537 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3538#if COAP_SERVER_SUPPORT
3539 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3540#endif /* COAP_SERVER_SUPPORT */
3541 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3542#ifdef COAP_OPENSSL_PSK_SECURITY_LEVEL
3543 /*
3544 * Set to 0 if, for example, PSK-AES128-CCM8 is to be supported (64 bits).
3545 * Potentially opens up security vulnerabilities.
3546 * Default value is 1.
3547 */
3548 SSL_set_security_level(ssl, COAP_OPENSSL_PSK_SECURITY_LEVEL);
3549#endif /* COAP_OPENSSL_PSK_SECURITY_LEVEL */
3550 if (setup_data->validate_ih_call_back) {
3551 if (session->proto == COAP_PROTO_DTLS) {
3552 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3553 }
3554#if !COAP_DISABLE_TCP
3555 else {
3556 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3557 }
3558#endif /* !COAP_DISABLE_TCP */
3559 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3560 }
3561 }
3562 if ((context->psk_pki_enabled & IS_PKI) ||
3563 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3564 /*
3565 * If neither PSK or PKI have been set up, use PKI basics.
3566 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3567 */
3568 coap_dtls_pki_t *setup_data = &context->setup_data;
3569
3570 if (!(context->psk_pki_enabled & IS_PKI)) {
3571 /* PKI not defined - set up some defaults */
3572 setup_data->verify_peer_cert = 1;
3573 setup_data->check_common_ca = 0;
3574 setup_data->allow_self_signed = 1;
3575 setup_data->allow_expired_certs = 1;
3576 setup_data->cert_chain_validation = 1;
3577 setup_data->cert_chain_verify_depth = 2;
3578 setup_data->check_cert_revocation = 1;
3579 setup_data->allow_no_crl = 1;
3580 setup_data->allow_expired_crl = 1;
3581 setup_data->is_rpk_not_cert = 0;
3582 setup_data->use_cid = 0;
3583 }
3584 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3585 return 0;
3586 /* libcoap is managing (D)TLS connection based on setup_data options */
3587#if !COAP_DISABLE_TCP
3588 if (session->proto == COAP_PROTO_TLS)
3589 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3590#endif /* !COAP_DISABLE_TCP */
3591
3592 /* Issue SNI if requested */
3593 if (setup_data->client_sni &&
3594 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3595 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3596 setup_data->client_sni);
3597 }
3598 /* Certificate Revocation */
3599 if (setup_data->check_cert_revocation) {
3600 X509_VERIFY_PARAM *param;
3601
3602 param = X509_VERIFY_PARAM_new();
3603 if (param) {
3604 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3605 SSL_set1_param(ssl, param);
3606 X509_VERIFY_PARAM_free(param);
3607 }
3608 }
3609
3610 /* Verify Peer */
3611 if (setup_data->verify_peer_cert)
3612 SSL_set_verify(ssl,
3613 SSL_VERIFY_PEER |
3614 SSL_VERIFY_CLIENT_ONCE |
3615 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3616 tls_verify_call_back);
3617 else
3618 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3619
3620 /* Check CA Chain */
3621 if (setup_data->cert_chain_validation)
3622 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3623
3624 }
3625#if COAP_DTLS_RETRANSMIT_MS != 1000
3626#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3627 if (session->proto == COAP_PROTO_DTLS) {
3628 DTLS_set_timer_cb(ssl, timer_cb);
3629 }
3630#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3631#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3632 return 1;
3633}
3634
3635void *
3636coap_dtls_new_client_session(coap_session_t *session) {
3637 BIO *bio = NULL;
3638 SSL *ssl = NULL;
3639 coap_ssl_data *data;
3640 int r;
3641 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3642 coap_dtls_context_t *dtls = &context->dtls;
3643
3644 ssl = SSL_new(dtls->ctx);
3645 if (!ssl)
3646 goto error;
3647 bio = BIO_new(dtls->meth);
3648 if (!bio)
3649 goto error;
3650 data = (coap_ssl_data *)BIO_get_data(bio);
3651 if (!data)
3652 goto error;
3653 data->session = session;
3654 SSL_set_bio(ssl, bio, bio);
3655 SSL_set_app_data(ssl, session);
3656 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3657 SSL_set_mtu(ssl, (long)session->mtu);
3658
3659 if (!setup_client_ssl_session(session, ssl))
3660 goto error;
3661
3662 session->dtls_timeout_count = 0;
3663
3664 r = SSL_connect(ssl);
3665 if (r == -1) {
3666 int ret = SSL_get_error(ssl, r);
3667 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3668 r = 0;
3669 }
3670
3671 if (r == 0)
3672 goto error;
3673
3674 session->tls = ssl;
3675 return ssl;
3676
3677error:
3678 if (ssl)
3679 SSL_free(ssl);
3680 return NULL;
3681}
3682
3683void
3685 SSL *ssl = (SSL *)session->tls;
3686 if (ssl)
3687 SSL_set_mtu(ssl, (long)session->mtu);
3688}
3689#endif /* COAP_CLIENT_SUPPORT */
3690
3691void
3693 SSL *ssl = (SSL *)session->tls;
3694 if (ssl) {
3695 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3696 int r = SSL_shutdown(ssl);
3697 if (r == 0)
3698 SSL_shutdown(ssl);
3699 }
3700 SSL_free(ssl);
3701 session->tls = NULL;
3702 if (session->context)
3704 }
3705}
3706
3707ssize_t
3709 const uint8_t *data, size_t data_len) {
3710 int r;
3711 SSL *ssl = (SSL *)session->tls;
3712
3713 if (ssl == NULL) {
3715 return -1;
3716 }
3717
3718 session->dtls_event = -1;
3719 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3720 coap_session_str(session), (int)data_len);
3721 ERR_clear_error();
3722 r = SSL_write(ssl, data, (int)data_len);
3723
3724 if (r <= 0) {
3725 int err = SSL_get_error(ssl, r);
3726 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3727 r = 0;
3728 } else {
3729 if (err == SSL_ERROR_ZERO_RETURN)
3731 else if (err == SSL_ERROR_SSL) {
3732 unsigned long e = ERR_get_error();
3733
3734 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3735 coap_session_str(session),
3736 ERR_GET_REASON(e), ERR_reason_error_string(e));
3738 } else {
3739 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3740 coap_session_str(session), err);
3741 }
3742 r = -1;
3743 }
3744 }
3745
3746 if (session->dtls_event >= 0) {
3747 coap_handle_event_lkd(session->context, session->dtls_event, session);
3748 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3749 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3750 r = -1;
3751 }
3752 }
3753
3754 return r;
3755}
3756
3757int
3759 return 0;
3760}
3761
3763coap_dtls_get_context_timeout(void *dtls_context) {
3764 (void)dtls_context;
3765 return 0;
3766}
3767
3770 SSL *ssl = (SSL *)session->tls;
3771 coap_ssl_data *ssl_data;
3772 BIO *rbio;
3773
3774 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3775 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3776 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3777 return ssl_data ? ssl_data->timeout : 1000;
3778}
3779
3780/*
3781 * return 1 timed out
3782 * 0 still timing out
3783 */
3784int
3786 SSL *ssl = (SSL *)session->tls;
3787
3788 if (ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE) {
3789 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3790 (DTLSv1_handle_timeout(ssl) < 0)) {
3791 /* Too many retries */
3793 return 1;
3794 }
3795 return 0;
3796 }
3797 return 1;
3798}
3799
3800#if COAP_SERVER_SUPPORT
3801int
3802coap_dtls_hello(coap_session_t *session,
3803 const uint8_t *data, size_t data_len) {
3804 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3805 coap_ssl_data *ssl_data;
3806 int r;
3807 BIO *rbio;
3808
3809 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3810 rbio = dtls->ssl ? SSL_get_rbio(dtls->ssl) : NULL;
3811 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3812 assert(ssl_data != NULL);
3813 if (!ssl_data) {
3814 errno = ENOMEM;
3815 return -1;
3816 }
3817 if (ssl_data->pdu_len) {
3818 coap_log_err("** %s: Previous data not read %u bytes\n",
3819 coap_session_str(session), ssl_data->pdu_len);
3820 }
3821 ssl_data->session = session;
3822 ssl_data->pdu = data;
3823 ssl_data->pdu_len = (unsigned)data_len;
3824 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3825 if (r <= 0) {
3826 int err = SSL_get_error(dtls->ssl, r);
3827 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3828 /* Got a ClientHello, sent-out a VerifyRequest */
3829 r = 0;
3830 }
3831 } else {
3832 /* Got a valid answer to a VerifyRequest */
3833 r = 1;
3834 }
3835
3836 /*
3837 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3838 * only does a 'peek' read of the incoming data.
3839 *
3840 */
3841 return r;
3842}
3843#endif /* COAP_SERVER_SUPPORT */
3844
3845int
3846coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3847 coap_ssl_data *ssl_data;
3848 SSL *ssl = (SSL *)session->tls;
3849 int r;
3850 BIO *rbio;
3851#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3852 int retry = 0;
3853#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3854
3855 assert(ssl != NULL);
3856
3857 int in_init = SSL_in_init(ssl);
3858 uint8_t pdu[COAP_RXBUFFER_SIZE];
3859 rbio = ssl ? SSL_get_rbio(ssl) : NULL;
3860 ssl_data = rbio ? (coap_ssl_data *)BIO_get_data(rbio) : NULL;
3861 if (!ssl_data) {
3862 errno = ENOTCONN;
3863 return -1;
3864 }
3865
3866 if (ssl_data->pdu_len) {
3867 coap_log_err("** %s: Previous data not read %u bytes\n",
3868 coap_session_str(session), ssl_data->pdu_len);
3869 }
3870 ssl_data->pdu = data;
3871 ssl_data->pdu_len = (unsigned)data_len;
3872
3873 session->dtls_event = -1;
3874#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3875retry:
3876#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3877 ERR_clear_error();
3878 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3879 if (r > 0) {
3880 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3881 coap_session_str(session), r);
3882 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3883 /* Possible there was a DTLS error */
3884 ssl_data = (coap_ssl_data *)BIO_get_data(rbio);
3885 goto finished;
3886 } else {
3887 int err = SSL_get_error(ssl, r);
3888 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3889 if (in_init && SSL_is_init_finished(ssl)) {
3890 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3891 coap_session_str(session), SSL_get_cipher_name(ssl));
3893 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3894 }
3895 r = 0;
3896 } else {
3897 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3899 else if (err == SSL_ERROR_SSL) {
3900 unsigned long e = ERR_get_error();
3901
3902#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3903#include <openssl/proverr.h>
3904 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3905 /* Loading trust store - first access causes a directory read error */
3906 retry = 1;
3907 goto retry;
3908 }
3909#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3910 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3911 coap_session_str(session),
3912 ERR_GET_REASON(e), ERR_reason_error_string(e));
3914 } else {
3915 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3916 coap_session_str(session), err);
3917 }
3918 r = -1;
3919 }
3920 if (session->dtls_event >= 0) {
3921 coap_handle_event_lkd(session->context, session->dtls_event, session);
3922 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3923 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3924 /* Cause disconnect on a read */
3926 ssl_data = NULL;
3927 r = -1;
3928 }
3929 }
3930 }
3931
3932finished:
3933 if (ssl_data && ssl_data->pdu_len) {
3934 /* pdu data is held on stack which will not stay there */
3935 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3936 ssl_data->pdu_len = 0;
3937 ssl_data->pdu = NULL;
3938 }
3939 return r;
3940}
3941
3942unsigned int
3944 unsigned int overhead = 37;
3945 const SSL_CIPHER *s_ciph = NULL;
3946 if (session->tls != NULL)
3947 s_ciph = SSL_get_current_cipher(session->tls);
3948 if (s_ciph) {
3949 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3950
3951 const EVP_CIPHER *e_ciph;
3952 const EVP_MD *e_md;
3953 char cipher[128];
3954
3955 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3956
3957 switch (EVP_CIPHER_mode(e_ciph)) {
3958 case EVP_CIPH_GCM_MODE:
3959 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3960 maclen = EVP_GCM_TLS_TAG_LEN;
3961 break;
3962
3963 case EVP_CIPH_CCM_MODE:
3964 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3965 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3966 if (strstr(cipher, "CCM8"))
3967 maclen = 8;
3968 else
3969 maclen = 16;
3970 break;
3971
3972 case EVP_CIPH_CBC_MODE:
3973 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3974 blocksize = EVP_CIPHER_block_size(e_ciph);
3975 ivlen = EVP_CIPHER_iv_length(e_ciph);
3976 pad = 1;
3977 maclen = EVP_MD_size(e_md);
3978 break;
3979
3980 case EVP_CIPH_STREAM_CIPHER:
3981 /* Seen with PSK-CHACHA20-POLY1305 */
3982 ivlen = 8;
3983 maclen = 8;
3984 break;
3985
3986 default:
3987 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3988 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3989 cipher);
3990 ivlen = 8;
3991 maclen = 16;
3992 break;
3993 }
3994 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3995 }
3996 return overhead;
3997}
3998
3999#if !COAP_DISABLE_TCP
4000#if COAP_CLIENT_SUPPORT
4001void *
4002coap_tls_new_client_session(coap_session_t *session) {
4003 BIO *bio = NULL;
4004 SSL *ssl = NULL;
4005 int r;
4006 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
4007 coap_tls_context_t *tls = &context->tls;
4008
4009 ssl = SSL_new(tls->ctx);
4010 if (!ssl)
4011 goto error;
4012 bio = BIO_new(tls->meth);
4013 if (!bio)
4014 goto error;
4015 BIO_set_data(bio, session);
4016 SSL_set_bio(ssl, bio, bio);
4017 SSL_set_app_data(ssl, session);
4018
4019 if (!setup_client_ssl_session(session, ssl))
4020 return 0;
4021
4022 r = SSL_connect(ssl);
4023 if (r == -1) {
4024 int ret = SSL_get_error(ssl, r);
4025 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
4026 r = 0;
4027 if (ret == SSL_ERROR_WANT_READ)
4028 session->sock.flags |= COAP_SOCKET_WANT_READ;
4029 if (ret == SSL_ERROR_WANT_WRITE) {
4030 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4031#ifdef COAP_EPOLL_SUPPORT
4032 coap_epoll_ctl_mod(&session->sock,
4033 EPOLLOUT |
4034 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4035 EPOLLIN : 0),
4036 __func__);
4037#endif /* COAP_EPOLL_SUPPORT */
4038 }
4039 }
4040
4041 if (r == 0)
4042 goto error;
4043
4044 session->tls = ssl;
4045 if (SSL_is_init_finished(ssl)) {
4047 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4048 }
4049
4050 return ssl;
4051
4052error:
4053 if (ssl)
4054 SSL_free(ssl);
4055 return NULL;
4056}
4057#endif /* COAP_CLIENT_SUPPORT */
4058
4059#if COAP_SERVER_SUPPORT
4060void *
4061coap_tls_new_server_session(coap_session_t *session) {
4062 BIO *bio = NULL;
4063 SSL *ssl = NULL;
4064 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
4065 int r;
4066 const coap_bin_const_t *psk_hint;
4067
4068 ssl = SSL_new(tls->ctx);
4069 if (!ssl)
4070 goto error;
4071 bio = BIO_new(tls->meth);
4072 if (!bio)
4073 goto error;
4074 BIO_set_data(bio, session);
4075 SSL_set_bio(ssl, bio, bio);
4076 SSL_set_app_data(ssl, session);
4077
4078 psk_hint = coap_get_session_server_psk_hint(session);
4079 if (psk_hint != NULL && psk_hint->length) {
4080 char *hint = OPENSSL_malloc(psk_hint->length + 1);
4081
4082 if (hint) {
4083 memcpy(hint, psk_hint->s, psk_hint->length);
4084 hint[psk_hint->length] = '\000';
4085 SSL_use_psk_identity_hint(ssl, hint);
4086 OPENSSL_free(hint);
4087 } else {
4088 coap_log_warn("hint malloc failure\n");
4089 }
4090 }
4091
4092 r = SSL_accept(ssl);
4093 if (r == -1) {
4094 int err = SSL_get_error(ssl, r);
4095 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
4096 r = 0;
4097 if (err == SSL_ERROR_WANT_READ)
4098 session->sock.flags |= COAP_SOCKET_WANT_READ;
4099 if (err == SSL_ERROR_WANT_WRITE) {
4100 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4101#ifdef COAP_EPOLL_SUPPORT
4102 coap_epoll_ctl_mod(&session->sock,
4103 EPOLLOUT |
4104 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4105 EPOLLIN : 0),
4106 __func__);
4107#endif /* COAP_EPOLL_SUPPORT */
4108 }
4109 }
4110
4111 if (r == 0)
4112 goto error;
4113
4114 session->tls = ssl;
4115 if (SSL_is_init_finished(ssl)) {
4117 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4118 }
4119
4120#if COAP_DTLS_RETRANSMIT_MS != 1000
4121#if OPENSSL_VERSION_NUMBER >= 0x10101000L
4122 if (session->proto == COAP_PROTO_DTLS) {
4123 DTLS_set_timer_cb(ssl, timer_cb);
4124 }
4125#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4126#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4127
4128 return ssl;
4129
4130error:
4131 if (ssl)
4132 SSL_free(ssl);
4133 return NULL;
4134}
4135#endif /* COAP_SERVER_SUPPORT */
4136
4137void
4139 SSL *ssl = (SSL *)session->tls;
4140 if (ssl) {
4141 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4142 int r = SSL_shutdown(ssl);
4143 if (r == 0)
4144 SSL_shutdown(ssl);
4145 }
4146 SSL_free(ssl);
4147 session->tls = NULL;
4148 if (session->context)
4150 }
4151}
4152
4153/*
4154 * strm
4155 * return +ve Number of bytes written.
4156 * -1 Error (error in errno).
4157 */
4158ssize_t
4159coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4160 SSL *ssl = (SSL *)session->tls;
4161 int r, in_init;
4162
4163 if (ssl == NULL)
4164 return -1;
4165
4166 in_init = !SSL_is_init_finished(ssl);
4167 session->dtls_event = -1;
4168 ERR_clear_error();
4169 r = SSL_write(ssl, data, (int)data_len);
4170
4171 if (r <= 0) {
4172 int err = SSL_get_error(ssl, r);
4173 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4174 if (in_init && SSL_is_init_finished(ssl)) {
4175 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4176 coap_session_str(session), SSL_get_cipher_name(ssl));
4178 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4179 }
4180 if (err == SSL_ERROR_WANT_READ)
4181 session->sock.flags |= COAP_SOCKET_WANT_READ;
4182 else if (err == SSL_ERROR_WANT_WRITE) {
4183 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4184#ifdef COAP_EPOLL_SUPPORT
4185 coap_epoll_ctl_mod(&session->sock,
4186 EPOLLOUT |
4187 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4188 EPOLLIN : 0),
4189 __func__);
4190#endif /* COAP_EPOLL_SUPPORT */
4191 }
4192 r = 0;
4193 } else {
4194 if (err == SSL_ERROR_ZERO_RETURN)
4196 else if (err == SSL_ERROR_SSL) {
4197 unsigned long e = ERR_get_error();
4198
4199 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4200 coap_session_str(session),
4201 ERR_GET_REASON(e), ERR_reason_error_string(e));
4203 } else {
4204 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4205 coap_session_str(session), err);
4206 }
4207 r = -1;
4208 }
4209 } else if (in_init && SSL_is_init_finished(ssl)) {
4210 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4211 coap_session_str(session), SSL_get_cipher_name(ssl));
4213 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4214 }
4215
4216 if (session->dtls_event >= 0) {
4217 coap_handle_event_lkd(session->context, session->dtls_event, session);
4218 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4219 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4220 r = -1;
4221 }
4222 }
4223
4224 if (r >= 0) {
4225 if (r == (ssize_t)data_len)
4226 coap_log_debug("* %s: tls: sent %4d bytes\n",
4227 coap_session_str(session), r);
4228 else
4229 coap_log_debug("* %s: tls: sent %4d of %4" PRIdS " bytes\n",
4230 coap_session_str(session), r, data_len);
4231 }
4232 return r;
4233}
4234
4235/*
4236 * strm
4237 * return >=0 Number of bytes read.
4238 * -1 Error (error in errno).
4239 */
4240ssize_t
4241coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4242 SSL *ssl = (SSL *)session->tls;
4243 int r, in_init;
4244
4245 if (ssl == NULL) {
4246 errno = ENOTCONN;
4247 return -1;
4248 }
4249
4250 in_init = !SSL_is_init_finished(ssl);
4251 session->dtls_event = -1;
4252 ERR_clear_error();
4253 r = SSL_read(ssl, data, (int)data_len);
4254 if (r <= 0) {
4255 int err = SSL_get_error(ssl, r);
4256 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4257 if (in_init && SSL_is_init_finished(ssl)) {
4258 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4259 coap_session_str(session), SSL_get_cipher_name(ssl));
4261 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4262 }
4263 if (err == SSL_ERROR_WANT_READ)
4264 session->sock.flags |= COAP_SOCKET_WANT_READ;
4265 if (err == SSL_ERROR_WANT_WRITE) {
4266 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4267#ifdef COAP_EPOLL_SUPPORT
4268 coap_epoll_ctl_mod(&session->sock,
4269 EPOLLOUT |
4270 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4271 EPOLLIN : 0),
4272 __func__);
4273#endif /* COAP_EPOLL_SUPPORT */
4274 }
4275 r = 0;
4276 } else {
4277 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4279 else if (err == SSL_ERROR_SSL) {
4280 unsigned long e = ERR_get_error();
4281
4282 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4283 coap_session_str(session),
4284 ERR_GET_REASON(e), ERR_reason_error_string(e));
4286 } else {
4287 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4288 coap_session_str(session), err);
4289 }
4290 r = -1;
4291 }
4292 } else if (in_init && SSL_is_init_finished(ssl)) {
4293 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4294 coap_session_str(session), SSL_get_cipher_name(ssl));
4296 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4297 }
4298
4299 if (session->dtls_event >= 0) {
4300 coap_handle_event_lkd(session->context, session->dtls_event, session);
4301 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4302 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4303 /* Cause disconnect on a read */
4305 r = -1;
4306 }
4307 }
4308
4309 if (r > 0) {
4310 coap_log_debug("* %s: tls: recv %4d bytes\n",
4311 coap_session_str(session), r);
4312 }
4313 return r;
4314}
4315#endif /* !COAP_DISABLE_TCP */
4316
4317#if COAP_SERVER_SUPPORT
4318coap_digest_ctx_t *
4319coap_digest_setup(void) {
4320 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4321
4322 if (digest_ctx) {
4323 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4324 }
4325 return digest_ctx;
4326}
4327
4328void
4329coap_digest_free(coap_digest_ctx_t *digest_ctx) {
4330 if (digest_ctx)
4331 EVP_MD_CTX_free(digest_ctx);
4332}
4333
4334int
4335coap_digest_update(coap_digest_ctx_t *digest_ctx,
4336 const uint8_t *data,
4337 size_t data_len) {
4338 return EVP_DigestUpdate(digest_ctx, data, data_len);
4339}
4340
4341int
4342coap_digest_final(coap_digest_ctx_t *digest_ctx,
4343 coap_digest_t *digest_buffer) {
4344 unsigned int size = sizeof(coap_digest_t);
4345 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4346
4347 coap_digest_free(digest_ctx);
4348 return ret;
4349}
4350#endif /* COAP_SERVER_SUPPORT */
4351
4352#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4353static void
4354coap_crypto_output_errors(const char *prefix) {
4355#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4356 (void)prefix;
4357#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4358 unsigned long e;
4359
4360 while ((e = ERR_get_error()))
4361 coap_log_warn("%s: %s%s\n",
4362 prefix,
4363 ERR_reason_error_string(e),
4364 ssl_function_definition(e));
4365#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4366}
4367#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4368
4369#if COAP_WS_SUPPORT
4370/*
4371 * The struct hash_algs and the function get_hash_alg() are used to
4372 * determine which hash type to use for creating the required hash object.
4373 */
4374static struct hash_algs {
4375 cose_alg_t alg;
4376 const EVP_MD *(*get_hash)(void);
4377 size_t length; /* in bytes */
4378} hashes[] = {
4379 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4380 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4381 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4382 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4383};
4384
4385static const EVP_MD *
4386get_hash_alg(cose_alg_t alg, size_t *length) {
4387 size_t idx;
4388
4389 for (idx = 0; idx < sizeof(hashes) / sizeof(struct hash_algs); idx++) {
4390 if (hashes[idx].alg == alg) {
4391 *length = hashes[idx].length;
4392 return hashes[idx].get_hash();
4393 }
4394 }
4395 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4396 return NULL;
4397}
4398
4399int
4401 const coap_bin_const_t *data,
4402 coap_bin_const_t **hash) {
4403 unsigned int length;
4404 const EVP_MD *evp_md;
4405 EVP_MD_CTX *evp_ctx = NULL;
4407 size_t hash_length;
4408
4409 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4410 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4411 return 0;
4412 }
4413 evp_ctx = EVP_MD_CTX_new();
4414 if (evp_ctx == NULL)
4415 goto error;
4416 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4417 goto error;
4418 ;
4419 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4420 goto error;
4421 ;
4422 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4423 if (dummy == NULL)
4424 goto error;
4425 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4426 goto error;
4427 dummy->length = length;
4428 if (hash_length < dummy->length)
4429 dummy->length = hash_length;
4430 *hash = (coap_bin_const_t *)(dummy);
4431 EVP_MD_CTX_free(evp_ctx);
4432 return 1;
4433
4434error:
4435 coap_crypto_output_errors("coap_crypto_hash");
4437 if (evp_ctx)
4438 EVP_MD_CTX_free(evp_ctx);
4439 return 0;
4440}
4441#endif /* COAP_WS_SUPPORT */
4442
4443#if COAP_OSCORE_SUPPORT
4444int
4446 return 1;
4447}
4448
4449#include <openssl/evp.h>
4450#include <openssl/hmac.h>
4451
4452/*
4453 * The struct cipher_algs and the function get_cipher_alg() are used to
4454 * determine which cipher type to use for creating the required cipher
4455 * suite object.
4456 */
4457static struct cipher_algs {
4458 cose_alg_t alg;
4459 const EVP_CIPHER *(*get_cipher)(void);
4460} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4461 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4462};
4463
4464static const EVP_CIPHER *
4465get_cipher_alg(cose_alg_t alg) {
4466 size_t idx;
4467
4468 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4469 if (ciphers[idx].alg == alg)
4470 return ciphers[idx].get_cipher();
4471 }
4472 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4473 return NULL;
4474}
4475
4476/*
4477 * The struct hmac_algs and the function get_hmac_alg() are used to
4478 * determine which hmac type to use for creating the required hmac
4479 * suite object.
4480 */
4481static struct hmac_algs {
4482 cose_hmac_alg_t hmac_alg;
4483 const EVP_MD *(*get_hmac)(void);
4484} hmacs[] = {
4485 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4486 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4487 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4488};
4489
4490static const EVP_MD *
4491get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4492 size_t idx;
4493
4494 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4495 if (hmacs[idx].hmac_alg == hmac_alg)
4496 return hmacs[idx].get_hmac();
4497 }
4498 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4499 return NULL;
4500}
4501
4502int
4504 return get_cipher_alg(alg) != NULL;
4505}
4506
4507int
4509 cose_hmac_alg_t hmac_alg;
4510
4511 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4512 return 0;
4513 return get_hmac_alg(hmac_alg) != NULL;
4514}
4515
4516#define C(Func) \
4517 if (1 != (Func)) { \
4518 goto error; \
4519 }
4520
4521int
4523 coap_bin_const_t *data,
4524 coap_bin_const_t *aad,
4525 uint8_t *result,
4526 size_t *max_result_len) {
4527 const EVP_CIPHER *cipher;
4528 const coap_crypto_aes_ccm_t *ccm;
4529 int tmp;
4530 int result_len = (int)(*max_result_len & INT_MAX);
4531 EVP_CIPHER_CTX *ctx;
4532
4533 if (data == NULL)
4534 return 0;
4535
4536 assert(params != NULL);
4537 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4538 return 0;
4539 }
4540
4541 /* TODO: set evp_md depending on params->alg */
4542 ccm = &params->params.aes;
4543
4544 ctx = EVP_CIPHER_CTX_new();
4545 if (!ctx)
4546 return 0;
4547
4548 /* EVP_CIPHER_CTX_init(ctx); */
4549 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4550 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4551 C(EVP_CIPHER_CTX_ctrl(ctx,
4552 EVP_CTRL_AEAD_SET_IVLEN,
4553 (int)(15 - ccm->l),
4554 NULL));
4555 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4556 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4557 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4558
4559 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4560 if (aad && aad->s && (aad->length > 0)) {
4561 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4562 }
4563 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4564 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4565 tmp = result_len;
4566 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4567 result_len += tmp;
4568
4569 /* retrieve the tag */
4570 C(EVP_CIPHER_CTX_ctrl(ctx,
4571 EVP_CTRL_CCM_GET_TAG,
4572 (int)ccm->tag_len,
4573 result + result_len));
4574
4575 *max_result_len = result_len + ccm->tag_len;
4576 EVP_CIPHER_CTX_free(ctx);
4577 return 1;
4578
4579error:
4580 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4581 return 0;
4582}
4583
4584int
4586 coap_bin_const_t *data,
4587 coap_bin_const_t *aad,
4588 uint8_t *result,
4589 size_t *max_result_len) {
4590 const EVP_CIPHER *cipher;
4591 const coap_crypto_aes_ccm_t *ccm;
4592 int tmp;
4593 int len;
4594 const uint8_t *tag;
4595 uint8_t *rwtag;
4596 EVP_CIPHER_CTX *ctx;
4597
4598 if (data == NULL)
4599 return 0;
4600
4601 assert(params != NULL);
4602 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4603 return 0;
4604 }
4605
4606 ccm = &params->params.aes;
4607
4608 if (data->length < ccm->tag_len) {
4609 return 0;
4610 } else {
4611 tag = data->s + data->length - ccm->tag_len;
4612 data->length -= ccm->tag_len;
4613 /* Kludge to stop compiler warning */
4614 memcpy(&rwtag, &tag, sizeof(rwtag));
4615 }
4616
4617 ctx = EVP_CIPHER_CTX_new();
4618 if (!ctx)
4619 return 0;
4620
4621 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4622 C(EVP_CIPHER_CTX_ctrl(ctx,
4623 EVP_CTRL_AEAD_SET_IVLEN,
4624 (int)(15 - ccm->l),
4625 NULL));
4626 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4627 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4628 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4629 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4630
4631 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4632 if (aad && aad->s && (aad->length > 0)) {
4633 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4634 }
4635 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4636 EVP_CIPHER_CTX_free(ctx);
4637 if (tmp <= 0) {
4638 *max_result_len = 0;
4639 return 0;
4640 }
4641 *max_result_len = len;
4642 return 1;
4643
4644error:
4645 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4646 return 0;
4647}
4648
4649int
4651 coap_bin_const_t *key,
4652 coap_bin_const_t *data,
4653 coap_bin_const_t **hmac) {
4654 unsigned int result_len;
4655 const EVP_MD *evp_md;
4657
4658 assert(key);
4659 assert(data);
4660 assert(hmac);
4661
4662 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4663 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4664 return 0;
4665 }
4666 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4667 if (dummy == NULL)
4668 return 0;
4669 result_len = (unsigned int)dummy->length;
4670 if (HMAC(evp_md,
4671 key->s,
4672 (int)key->length,
4673 data->s,
4674 (int)data->length,
4675 dummy->s,
4676 &result_len)) {
4677 dummy->length = result_len;
4678 *hmac = (coap_bin_const_t *)dummy;
4679 return 1;
4680 }
4681
4683 coap_crypto_output_errors("coap_crypto_hmac");
4684 return 0;
4685}
4686
4687#endif /* COAP_OSCORE_SUPPORT */
4688
4689#else /* ! COAP_WITH_LIBOPENSSL */
4690
4691#ifdef __clang__
4692/* Make compilers happy that do not like empty modules. As this function is
4693 * never used, we ignore -Wunused-function at the end of compiling this file
4694 */
4695#pragma GCC diagnostic ignored "-Wunused-function"
4696#endif
4697static inline void
4698dummy(void) {
4699}
4700
4701#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:252
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:364
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:436
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:359
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:378
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:298
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:396
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:268
static coap_log_t dtls_log_level
Definition coap_notls.c:295
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:291
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:347
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:424
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:343
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:260
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:373
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:321
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:339
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:316
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:415
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:195
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:5396
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:3117
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:159
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:288
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:354
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
Triggerrd 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:311
#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:306
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.
union coap_crypto_param_t::@115100030174240050243254031377105115063160056142 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorithm to use.
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
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:285
union coap_dtls_key_t::@355263010106203056112023075220063075203230161256 key
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 returned 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