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