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