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