libcoap 4.3.5-develop-daa4e05
Loading...
Searching...
No Matches
coap_openssl.c
Go to the documentation of this file.
1/*
2 * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3 *
4 * Copyright (C) 2017 Jean-Claude Michelou <jcm@spinetix.com>
5 * Copyright (C) 2018-2025 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 if (ret < 0 && (errno == ENOTCONN || errno == ECONNREFUSED))
641 data->session->dtls_event = COAP_EVENT_DTLS_ERROR;
642 BIO_set_retry_write(a);
643 }
644 } else {
645 BIO_clear_retry_flags(a);
646 ret = -1;
647 }
648 return ret;
649}
650
651static int
652coap_dgram_puts(BIO *a, const char *pstr) {
653 return coap_dgram_write(a, pstr, (int)strlen(pstr));
654}
655
656static long
657coap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) {
658 long ret = 1;
659 coap_ssl_data *data = BIO_get_data(a);
660
661 (void)ptr;
662
663 switch (cmd) {
664 case BIO_CTRL_GET_CLOSE:
665 ret = BIO_get_shutdown(a);
666 break;
667 case BIO_CTRL_SET_CLOSE:
668 BIO_set_shutdown(a, (int)num);
669 ret = 1;
670 break;
671 case BIO_CTRL_DGRAM_SET_PEEK_MODE:
672 data->peekmode = (unsigned)num;
673 break;
674 case BIO_CTRL_DGRAM_CONNECT:
675 case BIO_C_SET_FD:
676 case BIO_C_GET_FD:
677 case BIO_CTRL_DGRAM_SET_DONT_FRAG:
678 case BIO_CTRL_DGRAM_GET_MTU:
679 case BIO_CTRL_DGRAM_SET_MTU:
680 case BIO_CTRL_DGRAM_QUERY_MTU:
681 case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
682 ret = -1;
683 break;
684 case BIO_CTRL_DUP:
685 case BIO_CTRL_FLUSH:
686 case BIO_CTRL_DGRAM_MTU_DISCOVER:
687 case BIO_CTRL_DGRAM_SET_CONNECTED:
688 ret = 1;
689 break;
690 case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
691 data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval *)ptr)->tv_sec * 1000000 + ((
692 struct timeval *)ptr)->tv_usec);
693 ret = 1;
694 break;
695 case BIO_CTRL_RESET:
696 case BIO_C_FILE_SEEK:
697 case BIO_C_FILE_TELL:
698 case BIO_CTRL_INFO:
699 case BIO_CTRL_PENDING:
700 case BIO_CTRL_WPENDING:
701 case BIO_CTRL_DGRAM_GET_PEER:
702 case BIO_CTRL_DGRAM_SET_PEER:
703 case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
704 case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
705 case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
706 case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
707 case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
708 case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
709 case BIO_CTRL_DGRAM_MTU_EXCEEDED:
710 case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
711 default:
712 ret = 0;
713 break;
714 }
715 return ret;
716}
717
718static int
719coap_dtls_generate_cookie(SSL *ssl,
720 unsigned char *cookie,
721 unsigned int *cookie_len) {
722 coap_dtls_context_t *dtls =
723 (coap_dtls_context_t *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
724 coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
725 int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
726 r &= HMAC_Update(dtls->cookie_hmac,
727 (const uint8_t *)&data->session->addr_info.local.addr,
728 (size_t)data->session->addr_info.local.size);
729 r &= HMAC_Update(dtls->cookie_hmac,
730 (const uint8_t *)&data->session->addr_info.remote.addr,
731 (size_t)data->session->addr_info.remote.size);
732 r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
733 return r;
734}
735
736static int
737coap_dtls_verify_cookie(SSL *ssl,
738 const uint8_t *cookie,
739 unsigned int cookie_len) {
740 uint8_t hmac[32];
741 unsigned len = 32;
742 if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
743 cookie_len == len && memcmp(cookie, hmac, len) == 0)
744 return 1;
745 else
746 return 0;
747}
748
749#if COAP_CLIENT_SUPPORT
750static unsigned int
751coap_dtls_psk_client_callback(SSL *ssl,
752 const char *hint,
753 char *identity,
754 unsigned int max_identity_len,
755 unsigned char *psk,
756 unsigned int max_psk_len) {
757 coap_session_t *c_session;
758 coap_openssl_context_t *o_context;
759 coap_dtls_cpsk_t *setup_data;
760 coap_bin_const_t temp;
761 const coap_dtls_cpsk_info_t *cpsk_info;
762 const coap_bin_const_t *psk_key;
763 const coap_bin_const_t *psk_identity;
764
765 c_session = (coap_session_t *)SSL_get_app_data(ssl);
766 if (c_session == NULL)
767 return 0;
768 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
769 if (o_context == NULL)
770 return 0;
771 setup_data = &c_session->cpsk_setup_data;
772
773 temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
774 temp.length = strlen((const char *)temp.s);
775 coap_session_refresh_psk_hint(c_session, &temp);
776
777 coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
778 (const char *)temp.s);
779
780 if (setup_data->validate_ih_call_back) {
781 coap_str_const_t lhint;
782
783 lhint.s = temp.s;
784 lhint.length = temp.length;
785 coap_lock_callback_ret(cpsk_info, c_session->context,
786 setup_data->validate_ih_call_back(&lhint,
787 c_session,
788 setup_data->ih_call_back_arg));
789
790 if (cpsk_info == NULL)
791 return 0;
792
793 coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
794 coap_session_refresh_psk_key(c_session, &cpsk_info->key);
795 psk_identity = &cpsk_info->identity;
796 psk_key = &cpsk_info->key;
797 } else {
798 psk_identity = coap_get_session_client_psk_identity(c_session);
799 psk_key = coap_get_session_client_psk_key(c_session);
800 }
801
802 if (psk_identity == NULL || psk_key == NULL) {
803 coap_log_warn("no PSK available\n");
804 return 0;
805 }
806
807 /* identity has to be NULL terminated */
808 if (!max_identity_len)
809 return 0;
810 max_identity_len--;
811 if (psk_identity->length > max_identity_len) {
812 coap_log_warn("psk_identity too large, truncated to %d bytes\n",
813 max_identity_len);
814 } else {
815 /* Reduce to match */
816 max_identity_len = (unsigned int)psk_identity->length;
817 }
818 memcpy(identity, psk_identity->s, max_identity_len);
819 identity[max_identity_len] = '\000';
820
821 if (psk_key->length > max_psk_len) {
822 coap_log_warn("psk_key too large, truncated to %d bytes\n",
823 max_psk_len);
824 } else {
825 /* Reduce to match */
826 max_psk_len = (unsigned int)psk_key->length;
827 }
828 memcpy(psk, psk_key->s, max_psk_len);
829 return max_psk_len;
830}
831#endif /* COAP_CLIENT_SUPPORT */
832
833#if COAP_SERVER_SUPPORT
834static unsigned int
835coap_dtls_psk_server_callback(
836 SSL *ssl,
837 const char *identity,
838 unsigned char *psk,
839 unsigned int max_psk_len
840) {
841 coap_session_t *c_session;
842 coap_dtls_spsk_t *setup_data;
843 coap_bin_const_t lidentity;
844 const coap_bin_const_t *psk_key;
845
846 c_session = (coap_session_t *)SSL_get_app_data(ssl);
847 if (c_session == NULL)
848 return 0;
849
850 setup_data = &c_session->context->spsk_setup_data;
851
852 /* Track the Identity being used */
853 lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
854 lidentity.length = strlen((const char *)lidentity.s);
855 coap_session_refresh_psk_identity(c_session, &lidentity);
856
857 coap_log_debug("got psk_identity: '%.*s'\n",
858 (int)lidentity.length, (const char *)lidentity.s);
859
860 if (setup_data->validate_id_call_back) {
861 psk_key = setup_data->validate_id_call_back(&lidentity,
862 c_session,
863 setup_data->id_call_back_arg);
864
865 coap_session_refresh_psk_key(c_session, psk_key);
866 } else {
867 psk_key = coap_get_session_server_psk_key(c_session);
868 }
869
870 if (psk_key == NULL)
871 return 0;
872
873 if (psk_key->length > max_psk_len) {
874 coap_log_warn("psk_key too large, truncated to %d bytes\n",
875 max_psk_len);
876 } else {
877 /* Reduce to match */
878 max_psk_len = (unsigned int)psk_key->length;
879 }
880 memcpy(psk, psk_key->s, max_psk_len);
881 return max_psk_len;
882}
883#endif /* COAP_SERVER_SUPPORT */
884
885static const char *
886ssl_function_definition(unsigned long e) {
887#if OPENSSL_VERSION_NUMBER >= 0x30000000L
888 (void)e;
889 return "";
890#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
891 static char buff[80];
892
893 snprintf(buff, sizeof(buff), " at %s:%s",
894 ERR_lib_error_string(e), ERR_func_error_string(e));
895 return buff;
896#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
897}
898
899static void
900coap_dtls_info_callback(const SSL *ssl, int where, int ret) {
901 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
902 const char *pstr;
903 int w = where &~SSL_ST_MASK;
904
905 if (w & SSL_ST_CONNECT)
906 pstr = "SSL_connect";
907 else if (w & SSL_ST_ACCEPT)
908 pstr = "SSL_accept";
909 else
910 pstr = "undefined";
911
912 if (where & SSL_CB_LOOP) {
913 coap_dtls_log(COAP_LOG_DEBUG, "* %s: %s:%s\n",
914 coap_session_str(session), pstr, SSL_state_string_long(ssl));
915 } else if (where & SSL_CB_ALERT) {
916 coap_log_t log_level = COAP_LOG_INFO;
917 pstr = (where & SSL_CB_READ) ? "read" : "write";
918 if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
920 if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
921 log_level = COAP_LOG_WARN;
922 }
923 /* Need to let CoAP logging know why this session is dying */
924 coap_log(log_level, "* %s: SSL3 alert %s:%s:%s\n",
925 coap_session_str(session),
926 pstr,
927 SSL_alert_type_string_long(ret),
928 SSL_alert_desc_string_long(ret));
929 } else if (where & SSL_CB_EXIT) {
930 if (ret == 0) {
932 unsigned long e;
933 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:failed in %s\n",
934 coap_session_str(session), pstr, SSL_state_string_long(ssl));
935 while ((e = ERR_get_error()))
936 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
937 coap_session_str(session), ERR_reason_error_string(e),
938 ssl_function_definition(e));
939 }
940 } else if (ret < 0) {
942 int err = SSL_get_error(ssl, ret);
943 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
944 err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
945 err != SSL_ERROR_WANT_X509_LOOKUP) {
946 long e;
947 coap_dtls_log(COAP_LOG_WARN, "* %s: %s:error in %s\n",
948 coap_session_str(session), pstr, SSL_state_string_long(ssl));
949 while ((e = ERR_get_error()))
950 coap_dtls_log(COAP_LOG_WARN, "* %s: %s%s\n",
951 coap_session_str(session), ERR_reason_error_string(e),
952 ssl_function_definition(e));
953 }
954 }
955 }
956 }
957
958 if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
960}
961
962#if !COAP_DISABLE_TCP
963static int
964coap_sock_create(BIO *a) {
965 BIO_set_init(a, 1);
966 return 1;
967}
968
969static int
970coap_sock_destroy(BIO *a) {
971 (void)a;
972 return 1;
973}
974
975/*
976 * strm
977 * return +ve data amount
978 * 0 no more
979 * -1 error
980 */
981static int
982coap_sock_read(BIO *a, char *out, int outl) {
983 int ret = 0;
984 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
985
986 if (out != NULL) {
987 ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (uint8_t *)out,
988 outl);
989 /* Translate layer returns into what OpenSSL expects */
990 if (ret == 0) {
991 BIO_set_retry_read(a);
992 ret = -1;
993 } else {
994 BIO_clear_retry_flags(a);
995 }
996 }
997 return ret;
998}
999
1000/*
1001 * strm
1002 * return +ve data amount
1003 * 0 no more
1004 * -1 error (error in errno)
1005 */
1006static int
1007coap_sock_write(BIO *a, const char *in, int inl) {
1008 int ret = 0;
1009 coap_session_t *session = (coap_session_t *)BIO_get_data(a);
1010
1011 ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
1012 (const uint8_t *)in,
1013 inl);
1014 /* Translate layer what returns into what OpenSSL expects */
1015 BIO_clear_retry_flags(a);
1016 if (ret == 0) {
1017 BIO_set_retry_read(a);
1018 ret = -1;
1019 } else {
1020 BIO_clear_retry_flags(a);
1021 if (ret == -1) {
1022 if ((session->state == COAP_SESSION_STATE_CSM ||
1023 session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1024 (errno == EPIPE || errno == ECONNRESET)) {
1025 /*
1026 * Need to handle a TCP timing window where an agent continues with
1027 * the sending of the next handshake or a CSM.
1028 * However, the peer does not like a certificate and so sends a
1029 * fatal alert and closes the TCP session.
1030 * The sending of the next handshake or CSM may get terminated because
1031 * of the closed TCP session, but there is still an outstanding alert
1032 * to be read in and reported on.
1033 * In this case, pretend that sending the info was fine so that the
1034 * alert can be read (which effectively is what happens with DTLS).
1035 */
1036 ret = inl;
1037 }
1038 }
1039 }
1040 return ret;
1041}
1042
1043static int
1044coap_sock_puts(BIO *a, const char *pstr) {
1045 return coap_sock_write(a, pstr, (int)strlen(pstr));
1046}
1047
1048static long
1049coap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
1050 int r = 1;
1051 (void)a;
1052 (void)ptr;
1053 (void)num;
1054
1055 switch (cmd) {
1056 case BIO_C_SET_FD:
1057 case BIO_C_GET_FD:
1058 r = -1;
1059 break;
1060 case BIO_CTRL_SET_CLOSE:
1061 case BIO_CTRL_DUP:
1062 case BIO_CTRL_FLUSH:
1063 r = 1;
1064 break;
1065 default:
1066 case BIO_CTRL_GET_CLOSE:
1067 r = 0;
1068 break;
1069 }
1070 return r;
1071}
1072#endif /* !COAP_DISABLE_TCP */
1073
1074static void
1075coap_set_user_prefs(SSL_CTX *ctx) {
1076 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
1077
1078#ifdef COAP_OPENSSL_SIGALGS
1079 SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1080 SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
1081#endif
1082
1083#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
1084 SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
1085#endif
1086}
1087
1088#if COAP_DTLS_RETRANSMIT_MS != 1000
1089#if OPENSSL_VERSION_NUMBER >= 0x10101000L
1090static unsigned int
1091timer_cb(SSL *s, unsigned int timer_us) {
1092 (void)s;
1093 if (timer_us == 0)
1094 return COAP_DTLS_RETRANSMIT_MS * 1000;
1095 else
1096 return 2 * timer_us;
1097}
1098#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1099#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
1100
1101void *
1103 coap_openssl_context_t *context;
1104 (void)coap_context;
1105
1106 context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
1107 if (context) {
1108 uint8_t cookie_secret[32];
1109
1110 memset(context, 0, sizeof(coap_openssl_context_t));
1111
1112 /* Set up DTLS context */
1113 context->dtls.ctx = SSL_CTX_new(DTLS_method());
1114 if (!context->dtls.ctx)
1115 goto error;
1116 SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
1117 SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
1118 SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
1119 coap_set_user_prefs(context->dtls.ctx);
1120 memset(cookie_secret, 0, sizeof(cookie_secret));
1121 if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
1123 "Insufficient entropy for random cookie generation");
1124 coap_prng_lkd(cookie_secret, sizeof(cookie_secret));
1125 }
1126 context->dtls.cookie_hmac = HMAC_CTX_new();
1127 if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
1128 EVP_sha256(), NULL))
1129 goto error;
1130 SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
1131 SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
1132 SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
1133 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
1134#if OPENSSL_VERSION_NUMBER >= 0x30000000L
1135 SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
1136#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
1137 context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
1138 if (!context->dtls.meth)
1139 goto error;
1140 context->dtls.bio_addr = BIO_ADDR_new();
1141 if (!context->dtls.bio_addr)
1142 goto error;
1143 BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
1144 BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
1145 BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
1146 BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
1147 BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
1148 BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
1149
1150#if !COAP_DISABLE_TCP
1151 /* Set up TLS context */
1152 context->tls.ctx = SSL_CTX_new(TLS_method());
1153 if (!context->tls.ctx)
1154 goto error;
1155 SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
1156 SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
1157 coap_set_user_prefs(context->tls.ctx);
1158 SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
1159 context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
1160 if (!context->tls.meth)
1161 goto error;
1162 BIO_meth_set_write(context->tls.meth, coap_sock_write);
1163 BIO_meth_set_read(context->tls.meth, coap_sock_read);
1164 BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
1165 BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
1166 BIO_meth_set_create(context->tls.meth, coap_sock_create);
1167 BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
1168#endif /* !COAP_DISABLE_TCP */
1169 }
1170
1171 return context;
1172
1173error:
1174 coap_dtls_free_context(context);
1175 return NULL;
1176}
1177
1178#if COAP_SERVER_SUPPORT
1179int
1181 coap_dtls_spsk_t *setup_data
1182 ) {
1183 coap_openssl_context_t *o_context =
1184 ((coap_openssl_context_t *)c_context->dtls_context);
1185 BIO *bio;
1186
1187 if (!setup_data || !o_context)
1188 return 0;
1189
1190 SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
1191 coap_dtls_psk_server_callback);
1192#if !COAP_DISABLE_TCP
1193 SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
1194 coap_dtls_psk_server_callback);
1195#endif /* !COAP_DISABLE_TCP */
1196 if (setup_data->psk_info.hint.s) {
1197 char hint[COAP_DTLS_HINT_LENGTH];
1198 snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
1199 setup_data->psk_info.hint.s);
1200 SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
1201#if !COAP_DISABLE_TCP
1202 SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
1203#endif /* !COAP_DISABLE_TCP */
1204 }
1205 if (setup_data->validate_sni_call_back) {
1206#if OPENSSL_VERSION_NUMBER < 0x10101000L
1207 SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
1208 &c_context->spsk_setup_data);
1209 SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
1210 psk_tls_server_name_call_back);
1211#if !COAP_DISABLE_TCP
1212 SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
1213 &c_context->spsk_setup_data);
1214 SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
1215 psk_tls_server_name_call_back);
1216#endif /* !COAP_DISABLE_TCP */
1217#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1218 SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
1219 psk_tls_client_hello_call_back,
1220 NULL);
1221#if !COAP_DISABLE_TCP
1222 SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
1223 psk_tls_client_hello_call_back,
1224 NULL);
1225#endif /* !COAP_DISABLE_TCP */
1226#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
1227 }
1228
1229 if (!o_context->dtls.ssl) {
1230 /* This is set up to handle new incoming sessions to a server */
1231 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1232 if (!o_context->dtls.ssl)
1233 return 0;
1234 bio = BIO_new(o_context->dtls.meth);
1235 if (!bio) {
1236 SSL_free(o_context->dtls.ssl);
1237 o_context->dtls.ssl = NULL;
1238 return 0;
1239 }
1240 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1241 SSL_set_app_data(o_context->dtls.ssl, NULL);
1242 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1243 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1244 }
1245 if (setup_data->ec_jpake) {
1246 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1247 }
1248 o_context->psk_pki_enabled |= IS_PSK;
1249 return 1;
1250}
1251#endif /* COAP_SERVER_SUPPORT */
1252
1253#if COAP_CLIENT_SUPPORT
1254int
1256 coap_dtls_cpsk_t *setup_data
1257 ) {
1258 coap_openssl_context_t *o_context =
1259 ((coap_openssl_context_t *)c_context->dtls_context);
1260 BIO *bio;
1261
1262 if (!setup_data || !o_context)
1263 return 0;
1264
1265 if (!o_context->dtls.ssl) {
1266 /* This is set up to handle new incoming sessions to a server */
1267 o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
1268 if (!o_context->dtls.ssl)
1269 return 0;
1270 bio = BIO_new(o_context->dtls.meth);
1271 if (!bio) {
1272 SSL_free(o_context->dtls.ssl);
1273 o_context->dtls.ssl = NULL;
1274 return 0;
1275 }
1276 SSL_set_bio(o_context->dtls.ssl, bio, bio);
1277 SSL_set_app_data(o_context->dtls.ssl, NULL);
1278 SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1279 SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1280 }
1281 if (setup_data->ec_jpake) {
1282 coap_log_warn("OpenSSL has no EC-JPAKE support\n");
1283 }
1284 if (setup_data->use_cid) {
1285 coap_log_warn("OpenSSL has no Connection-ID support\n");
1286 }
1287 o_context->psk_pki_enabled |= IS_PSK;
1288 return 1;
1289}
1290#endif /* COAP_CLIENT_SUPPORT */
1291
1292static int
1293map_key_type(int asn1_private_key_type
1294 ) {
1295 switch (asn1_private_key_type) {
1297 return EVP_PKEY_NONE;
1298 case COAP_ASN1_PKEY_RSA:
1299 return EVP_PKEY_RSA;
1301 return EVP_PKEY_RSA2;
1302 case COAP_ASN1_PKEY_DSA:
1303 return EVP_PKEY_DSA;
1305 return EVP_PKEY_DSA1;
1307 return EVP_PKEY_DSA2;
1309 return EVP_PKEY_DSA3;
1311 return EVP_PKEY_DSA4;
1312 case COAP_ASN1_PKEY_DH:
1313 return EVP_PKEY_DH;
1314 case COAP_ASN1_PKEY_DHX:
1315 return EVP_PKEY_DHX;
1316 case COAP_ASN1_PKEY_EC:
1317 return EVP_PKEY_EC;
1319 return EVP_PKEY_HMAC;
1321 return EVP_PKEY_CMAC;
1323 return EVP_PKEY_TLS1_PRF;
1325 return EVP_PKEY_HKDF;
1326 default:
1327 coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1328 asn1_private_key_type);
1329 break;
1330 }
1331 return 0;
1332}
1333#if !COAP_DISABLE_TCP
1334static uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1335
1336#if COAP_SERVER_SUPPORT
1337static int
1338server_alpn_callback(SSL *ssl COAP_UNUSED,
1339 const unsigned char **out,
1340 unsigned char *outlen,
1341 const unsigned char *in,
1342 unsigned int inlen,
1343 void *arg COAP_UNUSED
1344 ) {
1345 unsigned char *tout = NULL;
1346 int ret;
1347 if (inlen == 0)
1348 return SSL_TLSEXT_ERR_NOACK;
1349 ret = SSL_select_next_proto(&tout,
1350 outlen,
1351 coap_alpn,
1352 sizeof(coap_alpn),
1353 in,
1354 inlen);
1355 *out = tout;
1356 return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1357}
1358#endif /* COAP_SERVER_SUPPORT */
1359#endif /* !COAP_DISABLE_TCP */
1360
1361static void
1362add_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1363 long e;
1364
1365 /* Flush out existing errors */
1366 while (ERR_get_error() != 0) {
1367 }
1368
1369 if (!X509_STORE_add_cert(st, x509)) {
1370 while ((e = ERR_get_error()) != 0) {
1371 int r = ERR_GET_REASON(e);
1372 if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1373 /* Not already added */
1374 coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1375 ERR_reason_error_string(e),
1376 ssl_function_definition(e));
1377 }
1378 }
1379 }
1380}
1381
1382static X509 *
1383missing_ENGINE_load_cert(ENGINE *engine, const char *cert_id) {
1384 struct {
1385 const char *cert_id;
1386 X509 *cert;
1387 } params;
1388
1389 params.cert_id = cert_id;
1390 params.cert = NULL;
1391
1392 /* There is no ENGINE_load_cert() */
1393 if (!ENGINE_ctrl_cmd(engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1394 params.cert = NULL;
1395 }
1396 return params.cert;
1397}
1398
1399static int
1400check_pkcs11_engine(void) {
1401 static int already_tried = 0;
1402
1403 if (already_tried)
1404 return 0;
1405
1406 if (!pkcs11_engine) {
1407 pkcs11_engine = ENGINE_by_id(COAP_OPENSSL_PKCS11_ENGINE_ID);
1408 if (!pkcs11_engine) {
1409 coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL %s engine\n",
1410 COAP_OPENSSL_PKCS11_ENGINE_ID);
1411 already_tried = 1;
1412 return 0;
1413 }
1414 if (!ENGINE_init(pkcs11_engine)) {
1415 /* the engine couldn't initialise, release 'pkcs11_engine' */
1416 ENGINE_free(pkcs11_engine);
1417 pkcs11_engine = NULL;
1418 coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1419 already_tried = 1;
1420 return 0;
1421 }
1422 /*
1423 * ENGINE_init() returned a functional reference, so free the structural
1424 * reference from ENGINE_by_id().
1425 */
1426 ENGINE_free(pkcs11_engine);
1427 }
1428 return 1;
1429}
1430
1431#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1432
1433static int
1434install_engine_public_cert_ctx(ENGINE *engine, SSL_CTX *ctx,
1435 const char *public_cert) {
1436 X509 *x509;
1437
1438 x509 = missing_ENGINE_load_cert(engine, public_cert);
1439 if (!x509) {
1440 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1441 "%s Certificate\n",
1442 public_cert,
1443 "Server");
1444 return 0;
1445 }
1446 if (!SSL_CTX_use_certificate(ctx, x509)) {
1447 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1448 "%s Certificate\n",
1449 public_cert,
1450 "Server");
1451 X509_free(x509);
1452 return 0;
1453 }
1454 X509_free(x509);
1455 return 1;
1456}
1457
1458static int
1459install_engine_private_key_ctx(ENGINE *engine, SSL_CTX *ctx,
1460 const char *private_key) {
1461 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1462 private_key,
1463 NULL, NULL);
1464
1465 if (!pkey) {
1466 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1467 "%s Private Key\n",
1468 private_key,
1469 "Server");
1470 return 0;
1471 }
1472 if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1473 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1474 "%s Private Key\n",
1475 private_key,
1476 "Server");
1477 EVP_PKEY_free(pkey);
1478 return 0;
1479 }
1480 EVP_PKEY_free(pkey);
1481 return 1;
1482}
1483
1484static int
1485install_engine_ca_ctx(ENGINE *engine, SSL_CTX *ctx, const char *ca) {
1486 X509 *x509;
1487 X509_STORE *st;
1488
1489 x509 = missing_ENGINE_load_cert(engine,
1490 ca);
1491 if (!x509) {
1492 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1493 "%s CA Certificate\n",
1494 ca,
1495 "Server");
1496 return 0;
1497 }
1498 if (!SSL_CTX_add_client_CA(ctx, x509)) {
1499 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1500 "%s CA Certificate\n",
1501 ca,
1502 "Server");
1503 X509_free(x509);
1504 return 0;
1505 }
1506 st = SSL_CTX_get_cert_store(ctx);
1507 add_ca_to_cert_store(st, x509);
1508 X509_free(x509);
1509 return 1;
1510}
1511
1512static int
1513load_in_cas_ctx(SSL_CTX *ctx,
1514 const char *ca_file) {
1515 STACK_OF(X509_NAME) *cert_names;
1516 X509_STORE *st;
1517 BIO *in;
1518 X509 *x = NULL;
1519 char *rw_var = NULL;
1520 cert_names = SSL_load_client_CA_file(ca_file);
1521 if (cert_names != NULL)
1522 SSL_CTX_set_client_CA_list(ctx, cert_names);
1523 else {
1524 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1525 "client CA File\n",
1526 ca_file);
1527 return 0;
1528 }
1529
1530 /* Add CA to the trusted root CA store */
1531 st = SSL_CTX_get_cert_store(ctx);
1532 in = BIO_new(BIO_s_file());
1533 /* Need to do this to not get a compiler warning about const parameters */
1534 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1535 if (!BIO_read_filename(in, rw_var)) {
1536 BIO_free(in);
1537 X509_free(x);
1538 return 0;
1539 }
1540
1541 for (;;) {
1542 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1543 break;
1544 add_ca_to_cert_store(st, x);
1545 X509_free(x);
1546 }
1547 BIO_free(in);
1548 return 1;
1549}
1550
1551static int
1552setup_pki_server(SSL_CTX *ctx,
1553 const coap_dtls_pki_t *setup_data) {
1554 coap_dtls_key_t key;
1555
1556 /* Map over to the new define format to save code duplication */
1557 coap_dtls_map_key_type_to_define(setup_data, &key);
1558
1559 assert(key.key_type == COAP_PKI_KEY_DEFINE);
1560
1561 /*
1562 * Configure the Private Key
1563 */
1564 if (key.key.define.private_key.u_byte &&
1565 key.key.define.private_key.u_byte[0]) {
1566 switch (key.key.define.private_key_def) {
1567 case COAP_PKI_KEY_DEF_PEM: /* define private key */
1568 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1570 SSL_FILETYPE_PEM))) {
1573 &key, COAP_DTLS_ROLE_SERVER, 0);
1574 }
1575 break;
1576 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
1577 if (key.key.define.private_key_len) {
1578 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
1579 (int)key.key.define.private_key_len);
1580 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1581
1582 if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1583 if (bp)
1584 BIO_free(bp);
1585 if (pkey)
1586 EVP_PKEY_free(pkey);
1589 &key, COAP_DTLS_ROLE_SERVER, 0);
1590 }
1591 if (bp)
1592 BIO_free(bp);
1593 if (pkey)
1594 EVP_PKEY_free(pkey);
1595 } else {
1598 &key, COAP_DTLS_ROLE_SERVER, 0);
1599 }
1600 break;
1601 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
1604 &key, COAP_DTLS_ROLE_SERVER, 0);
1605 case COAP_PKI_KEY_DEF_DER: /* define private key */
1606 if (!(SSL_CTX_use_PrivateKey_file(ctx,
1608 SSL_FILETYPE_ASN1))) {
1611 &key, COAP_DTLS_ROLE_SERVER, 0);
1612 }
1613 break;
1614 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
1615 if (key.key.define.private_key_len == 0 ||
1616 !(SSL_CTX_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
1617 ctx,
1619 (long)key.key.define.private_key_len))) {
1622 &key, COAP_DTLS_ROLE_SERVER, 0);
1623 }
1624 break;
1625 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
1626 if (!check_pkcs11_engine()) {
1627 return 0;
1628 }
1629 if (key.key.define.user_pin) {
1630 /* If not set, pin-value may be held in pkcs11: URI */
1631 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
1632 "PIN",
1633 key.key.define.user_pin, 0) == 0) {
1634 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1635 key.key.define.user_pin);
1636 return 0;
1637 }
1638 }
1639 if (!install_engine_private_key_ctx(pkcs11_engine, ctx,
1643 &key, COAP_DTLS_ROLE_SERVER, 0);
1644 }
1645 break;
1646 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
1647 if (!defined_engine ||
1648 !install_engine_private_key_ctx(defined_engine, ctx,
1652 &key, COAP_DTLS_ROLE_SERVER, 0);
1653 }
1654 break;
1655 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
1656 default:
1659 &key, COAP_DTLS_ROLE_SERVER, 0);
1660 }
1661 } else if (key.key.define.public_cert.u_byte && key.key.define.public_cert.u_byte[0]) {
1664 &key, COAP_DTLS_ROLE_SERVER, 0);
1665 }
1666
1667 /*
1668 * Configure the Public Certificate / Key
1669 * OpenSSL < 1.1.1 and Server
1670 */
1671 if (key.key.define.public_cert.u_byte &&
1672 key.key.define.public_cert.u_byte[0]) {
1673 switch (key.key.define.public_cert_def) {
1674 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
1675 if (key.key.define.ca.u_byte &&
1676 key.key.define.ca.u_byte[0]) {
1677 if (!(SSL_use_certificate_file(ssl,
1679 SSL_FILETYPE_PEM))) {
1682 &key, role, 0);
1683 }
1684 } else {
1685 if (!SSL_use_certificate_chain_file(ssl,
1689 &key, role, 0);
1690 }
1691 }
1692 break;
1693 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
1694 if (key.key.define.public_cert_len) {
1695 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.u_byte,
1696 (int)key.key.define.public_cert_len);
1697 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1698
1699 if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1700 if (bp)
1701 BIO_free(bp);
1702 if (cert)
1703 X509_free(cert);
1706 &key, COAP_DTLS_ROLE_SERVER, 0);
1707 }
1708 if (bp)
1709 BIO_free(bp);
1710 if (cert)
1711 X509_free(cert);
1712 } else {
1715 &key, COAP_DTLS_ROLE_SERVER, 0);
1716 }
1717 break;
1718 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
1721 &key, COAP_DTLS_ROLE_SERVER, 0);
1722 case COAP_PKI_KEY_DEF_DER: /* define public cert */
1723 if (!(SSL_CTX_use_certificate_file(ctx,
1725 SSL_FILETYPE_ASN1))) {
1728 &key, COAP_DTLS_ROLE_SERVER, 0);
1729 }
1730 break;
1731 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
1732 if (key.key.define.public_cert_len == 0 ||
1733 !(SSL_CTX_use_certificate_ASN1(ctx,
1734 (int)key.key.define.public_cert_len,
1735 key.key.define.public_cert.u_byte))) {
1738 &key, COAP_DTLS_ROLE_SERVER, 0);
1739 }
1740 break;
1741 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
1742 if (!check_pkcs11_engine()) {
1743 return 0;
1744 }
1745 if (!install_engine_public_cert_ctx(pkcs11_engine, ctx,
1749 &key, COAP_DTLS_ROLE_SERVER, 0);
1750 }
1751 break;
1752 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
1753 if (!defined_engine ||
1754 !install_engine_public_cert_ctx(defined_engine, ctx,
1758 &key, COAP_DTLS_ROLE_SERVER, 0);
1759 }
1760 break;
1761 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
1762 default:
1765 &key, COAP_DTLS_ROLE_SERVER, 0);
1766 }
1767 } else if (key.key.define.private_key.u_byte &&
1768 key.key.define.private_key.u_byte[0]) {
1771 &key, COAP_DTLS_ROLE_SERVER, 0);
1772 }
1773
1774 /*
1775 * Configure the CA
1776 */
1777 if (key.key.define.ca.u_byte &&
1778 key.key.define.ca.u_byte[0]) {
1779 switch (key.key.define.ca_def) {
1781 if (!load_in_cas_ctx(ctx, key.key.define.ca.s_byte)) {
1784 &key, COAP_DTLS_ROLE_SERVER, 0);
1785 }
1786 break;
1787 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
1788 if (key.key.define.ca_len) {
1789 BIO *bp = BIO_new_mem_buf(key.key.define.ca.s_byte,
1790 (int)key.key.define.ca_len);
1791 X509 *x;
1792 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1793
1794 if (bp) {
1795 for (;;) {
1796 if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1797 break;
1798 add_ca_to_cert_store(st, x);
1799 SSL_CTX_add_client_CA(ctx, x);
1800 X509_free(x);
1801 }
1802 BIO_free(bp);
1803 }
1804 } else {
1807 &key, COAP_DTLS_ROLE_SERVER, 0);
1808 }
1809 break;
1810 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
1813 &key, COAP_DTLS_ROLE_SERVER, 0);
1814 case COAP_PKI_KEY_DEF_DER: /* define ca */
1815 if (!(SSL_CTX_use_certificate_file(ctx,
1816 key.key.define.ca.s_byte,
1817 SSL_FILETYPE_ASN1))) {
1820 &key, COAP_DTLS_ROLE_SERVER, 0);
1821 }
1822 break;
1823 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
1824 if (key.key.define.ca_len > 0) {
1825 /* Need to use a temp variable as it gets incremented*/
1826 const uint8_t *p = key.key.define.ca.u_byte;
1827 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
1828 X509_STORE *st;
1829
1830 if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1831 X509_free(x509);
1834 &key, COAP_DTLS_ROLE_SERVER, 0);
1835 }
1836
1837 /* Add CA to the trusted root CA store */
1838 st = SSL_CTX_get_cert_store(ctx);
1839 add_ca_to_cert_store(st, x509);
1840 X509_free(x509);
1841 }
1842 break;
1843 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
1844 if (!check_pkcs11_engine()) {
1845 return 0;
1846 }
1847 if (!install_engine_ca_ctx(pkcs11_engine, ctx,
1848 key.key.define.ca.s_byte)) {
1851 &key, COAP_DTLS_ROLE_SERVER, 0);
1852 }
1853 break;
1854 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
1855 if (!defined_engine ||
1856 !install_engine_ca_ctx(defined_engine, ctx,
1857 key.key.define.ca.s_byte)) {
1860 &key, COAP_DTLS_ROLE_SERVER, 0);
1861 }
1862 break;
1863 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
1864 default:
1867 &key, COAP_DTLS_ROLE_SERVER, 0);
1868 }
1869 }
1870
1871 return 1;
1872}
1873#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1874
1875#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1876
1877static int
1878install_engine_public_cert(ENGINE *engine, SSL *ssl, const char *public_cert,
1879 coap_dtls_role_t role) {
1880 X509 *x509;
1881
1882 x509 = missing_ENGINE_load_cert(engine, public_cert);
1883 if (!x509) {
1884 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1885 "%s Certificate\n",
1886 public_cert,
1887 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1888 return 0;
1889 }
1890 if (!SSL_use_certificate(ssl, x509)) {
1891 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1892 "%s Certificate\n",
1893 public_cert,
1894 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1895 X509_free(x509);
1896 return 0;
1897 }
1898 X509_free(x509);
1899 return 1;
1900}
1901
1902static int
1903install_engine_private_key(ENGINE *engine, SSL *ssl, const char *private_key,
1904 coap_dtls_role_t role) {
1905 EVP_PKEY *pkey = ENGINE_load_private_key(engine,
1906 private_key,
1907 NULL, NULL);
1908
1909 if (!pkey) {
1910 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1911 "%s Private Key\n",
1912 private_key,
1913 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1914 return 0;
1915 }
1916 if (!SSL_use_PrivateKey(ssl, pkey)) {
1917 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1918 "%s Private Key\n",
1919 private_key,
1920 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1921 EVP_PKEY_free(pkey);
1922 return 0;
1923 }
1924 EVP_PKEY_free(pkey);
1925 return 1;
1926}
1927
1928static int
1929install_engine_ca(ENGINE *engine, SSL *ssl, const char *ca,
1930 coap_dtls_role_t role) {
1931 X509 *x509;
1932 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1933 X509_STORE *st;
1934
1935 x509 = missing_ENGINE_load_cert(engine,
1936 ca);
1937 if (!x509) {
1938 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1939 "%s CA Certificate\n",
1940 ca,
1941 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1942 return 0;
1943 }
1944 if (!SSL_add_client_CA(ssl, x509)) {
1945 coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1946 "%s CA Certificate\n",
1947 ca,
1948 role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1949 X509_free(x509);
1950 return 0;
1951 }
1952 st = SSL_CTX_get_cert_store(ctx);
1953 add_ca_to_cert_store(st, x509);
1954 X509_free(x509);
1955 return 1;
1956}
1957
1958static int
1959load_in_cas(SSL *ssl,
1960 const char *ca_file, coap_dtls_role_t role) {
1961 X509_STORE *st;
1962 BIO *in;
1963 X509 *x = NULL;
1964 char *rw_var = NULL;
1965 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1966
1967 if (role == COAP_DTLS_ROLE_SERVER) {
1968 STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(ca_file);
1969
1970 if (cert_names != NULL)
1971 SSL_set_client_CA_list(ssl, cert_names);
1972 else {
1973 return 0;
1974 }
1975 }
1976
1977 /* Add CA to the trusted root CA store */
1978 in = BIO_new(BIO_s_file());
1979 /* Need to do this to not get a compiler warning about const parameters */
1980 memcpy(&rw_var, &ca_file, sizeof(rw_var));
1981 if (!BIO_read_filename(in, rw_var)) {
1982 BIO_free(in);
1983 return 0;
1984 }
1985 st = SSL_CTX_get_cert_store(ctx);
1986 for (;;) {
1987 if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1988 break;
1989 add_ca_to_cert_store(st, x);
1990 X509_free(x);
1991 }
1992 BIO_free(in);
1993 return 1;
1994}
1995
1996static int
1997setup_pki_ssl(SSL *ssl,
1998 coap_dtls_pki_t *setup_data, coap_dtls_role_t role) {
1999 coap_dtls_key_t key;
2000
2001 /* Map over to the new define format to save code duplication */
2002 coap_dtls_map_key_type_to_define(setup_data, &key);
2003
2004 assert(key.key_type == COAP_PKI_KEY_DEFINE);
2005
2006 /*
2007 * Configure the Private Key
2008 */
2009 if (key.key.define.private_key.u_byte &&
2010 key.key.define.private_key.u_byte[0]) {
2011 switch (key.key.define.private_key_def) {
2012 case COAP_PKI_KEY_DEF_PEM: /* define private key */
2013 if (!(SSL_use_PrivateKey_file(ssl,
2015 SSL_FILETYPE_PEM))) {
2018 &key, role, 0);
2019 }
2020 break;
2021 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
2022 if (key.key.define.private_key_len) {
2023 BIO *bp = BIO_new_mem_buf(key.key.define.private_key.u_byte,
2024 (int)key.key.define.private_key_len);
2025 EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
2026
2027 if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
2028 if (bp)
2029 BIO_free(bp);
2030 if (pkey)
2031 EVP_PKEY_free(pkey);
2034 &key, role, 0);
2035 }
2036 if (bp)
2037 BIO_free(bp);
2038 if (pkey)
2039 EVP_PKEY_free(pkey);
2040 } else {
2043 &key, role, 0);
2044 }
2045 break;
2046 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
2049 &key, role, 0);
2050 case COAP_PKI_KEY_DEF_DER: /* define private key */
2051 if (!(SSL_use_PrivateKey_file(ssl,
2053 SSL_FILETYPE_ASN1))) {
2056 &key, role, 0);
2057 }
2058 break;
2059 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
2060 if (key.key.define.private_key_len == 0 ||
2061 !(SSL_use_PrivateKey_ASN1(map_key_type(key.key.define.private_key_type),
2062 ssl,
2064 (long)key.key.define.private_key_len))) {
2067 &key, role, 0);
2068 }
2069 break;
2070 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
2071 if (!check_pkcs11_engine()) {
2072 return 0;
2073 }
2074 if (key.key.define.user_pin) {
2075 /* If not set, pin-value may be held in pkcs11: URI */
2076 if (ENGINE_ctrl_cmd_string(pkcs11_engine,
2077 "PIN",
2078 key.key.define.user_pin, 0) == 0) {
2079 coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
2080 key.key.define.user_pin);
2081 return 0;
2082 }
2083 }
2084 if (!install_engine_private_key(pkcs11_engine, ssl,
2086 role)) {
2089 &key, role, 0);
2090 }
2091 break;
2092 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
2093 if (!defined_engine ||
2094 !install_engine_private_key(defined_engine, ssl,
2096 role)) {
2099 &key, role, 0);
2100 }
2101 break;
2102 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
2103 default:
2106 &key, role, 0);
2107 }
2108 } else if (role == COAP_DTLS_ROLE_SERVER ||
2110 key.key.define.public_cert.u_byte[0])) {
2113 &key, role, 0);
2114 }
2115
2116 /*
2117 * Configure the Public Certificate / Key
2118 */
2119 if (key.key.define.public_cert.u_byte &&
2120 key.key.define.public_cert.u_byte[0]) {
2121 switch (key.key.define.public_cert_def) {
2122 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
2123 if (key.key.define.ca.u_byte &&
2124 key.key.define.ca.u_byte[0]) {
2125 /* If CA is separately defined */
2126 if (!(SSL_use_certificate_file(ssl,
2128 SSL_FILETYPE_PEM))) {
2131 &key, role, 0);
2132 }
2133 } else {
2134 if (!SSL_use_certificate_chain_file(ssl,
2138 &key, role, 0);
2139 }
2140 }
2141 break;
2142 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
2143 if (key.key.define.public_cert_len) {
2144 BIO *bp = BIO_new_mem_buf(key.key.define.public_cert.s_byte,
2145 (int)key.key.define.public_cert_len);
2146 X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
2147
2148 if (!cert || !SSL_use_certificate(ssl, cert)) {
2149 if (bp)
2150 BIO_free(bp);
2151 if (cert)
2152 X509_free(cert);
2155 &key, role, 0);
2156 }
2157 if (bp)
2158 BIO_free(bp);
2159 if (cert)
2160 X509_free(cert);
2161 } else {
2164 &key, role, 0);
2165 }
2166 break;
2167 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
2170 &key, role, 0);
2171 case COAP_PKI_KEY_DEF_DER: /* define public cert */
2172 if (!(SSL_use_certificate_file(ssl,
2174 SSL_FILETYPE_ASN1))) {
2177 &key, role, 0);
2178 }
2179 break;
2180 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
2181 if (key.key.define.public_cert_len == 0 ||
2182 !(SSL_use_certificate_ASN1(ssl,
2184 (int)key.key.define.public_cert_len))) {
2187 &key, role, 0);
2188 }
2189 break;
2190 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
2191 if (!check_pkcs11_engine()) {
2192 return 0;
2193 }
2194 if (!install_engine_public_cert(pkcs11_engine, ssl,
2196 role)) {
2199 &key, role, 0);
2200 }
2201 break;
2202 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
2203 if (!defined_engine ||
2204 !install_engine_public_cert(defined_engine, ssl,
2206 role)) {
2209 &key, role, 0);
2210 }
2211 break;
2212 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
2213 default:
2216 &key, role, 0);
2217 }
2218 } else if (role == COAP_DTLS_ROLE_SERVER ||
2220 key.key.define.private_key.u_byte[0])) {
2223 &key, role, 0);
2224 }
2225
2226 /*
2227 * Configure the CA
2228 */
2229 if (key.key.define.ca.u_byte &&
2230 key.key.define.ca.u_byte[0]) {
2231 switch (key.key.define.ca_def) {
2233 if (!load_in_cas(ssl, key.key.define.ca.s_byte, role)) {
2236 &key, role, 0);
2237 }
2238 break;
2239 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
2240 if (key.key.define.ca_len) {
2241 BIO *bp = BIO_new_mem_buf(key.key.define.ca.u_byte,
2242 (int)key.key.define.ca_len);
2243 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2244 X509 *x;
2245 X509_STORE *st = SSL_CTX_get_cert_store(ctx);
2246
2247 if (bp) {
2248 for (;;) {
2249 if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
2250 break;
2251 add_ca_to_cert_store(st, x);
2252 SSL_add_client_CA(ssl, x);
2253 X509_free(x);
2254 }
2255 BIO_free(bp);
2256 }
2257 } else {
2260 &key, role, 0);
2261 }
2262 break;
2263 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
2266 &key, role, 0);
2267 case COAP_PKI_KEY_DEF_DER: /* define ca */
2268 if (!(SSL_use_certificate_file(ssl,
2269 key.key.define.ca.s_byte,
2270 SSL_FILETYPE_ASN1))) {
2273 &key, role, 0);
2274 }
2275 break;
2276 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
2277 if (key.key.define.ca_len > 0) {
2278 /* Need to use a temp variable as it gets incremented*/
2279 const uint8_t *p = key.key.define.ca.u_byte;
2280 X509 *x509 = d2i_X509(NULL, &p, (long)key.key.define.ca_len);
2281 X509_STORE *st;
2282 SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
2283
2284 if (role == COAP_DTLS_ROLE_SERVER) {
2285 if (!x509 || !SSL_add_client_CA(ssl, x509)) {
2286 X509_free(x509);
2289 &key, role, 0);
2290 }
2291 }
2292
2293 /* Add CA to the trusted root CA store */
2294 st = SSL_CTX_get_cert_store(ctx);
2295 add_ca_to_cert_store(st, x509);
2296 X509_free(x509);
2297 }
2298 break;
2299 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
2300 if (!check_pkcs11_engine()) {
2301 return 0;
2302 }
2303 if (!install_engine_ca(pkcs11_engine, ssl,
2304 key.key.define.ca.s_byte,
2305 role)) {
2308 &key, role, 0);
2309 }
2310 break;
2311 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
2312 if (!defined_engine ||
2313 !install_engine_ca(defined_engine, ssl,
2314 key.key.define.ca.s_byte,
2315 role)) {
2318 &key, role, 0);
2319 }
2320 break;
2321 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
2322 default:
2325 &key, role, 0);
2326 }
2327 }
2328
2329 return 1;
2330}
2331#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
2332
2333static char *
2334get_san_or_cn_from_cert(X509 *x509) {
2335 if (x509) {
2336 char *cn;
2337 int n;
2338 STACK_OF(GENERAL_NAME) *san_list;
2339 char buffer[256];
2340
2341 san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
2342 if (san_list) {
2343 int san_count = sk_GENERAL_NAME_num(san_list);
2344
2345 for (n = 0; n < san_count; n++) {
2346 const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
2347
2348 if (name->type == GEN_DNS) {
2349 const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
2350
2351 /* Make sure that there is not an embedded NUL in the dns_name */
2352 if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
2353 continue;
2354 cn = OPENSSL_strdup(dns_name);
2355 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2356 return cn;
2357 }
2358 }
2359 sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
2360 }
2361 /* Otherwise look for the CN= field */
2362 X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
2363
2364 /* Need to emulate strcasestr() here. Looking for CN= */
2365 n = (int)strlen(buffer) - 3;
2366 cn = buffer;
2367 while (n > 0) {
2368 if (((cn[0] == 'C') || (cn[0] == 'c')) &&
2369 ((cn[1] == 'N') || (cn[1] == 'n')) &&
2370 (cn[2] == '=')) {
2371 cn += 3;
2372 break;
2373 }
2374 cn++;
2375 n--;
2376 }
2377 if (n > 0) {
2378 char *ecn = strchr(cn, '/');
2379 if (ecn) {
2380 return OPENSSL_strndup(cn, ecn-cn);
2381 } else {
2382 return OPENSSL_strdup(cn);
2383 }
2384 }
2385 }
2386 return NULL;
2387}
2388
2389static int
2390tls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
2391 SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
2392 SSL_get_ex_data_X509_STORE_CTX_idx());
2393 coap_session_t *session = SSL_get_app_data(ssl);
2394 coap_openssl_context_t *context =
2395 ((coap_openssl_context_t *)session->context->dtls_context);
2396 coap_dtls_pki_t *setup_data = &context->setup_data;
2397 int depth = X509_STORE_CTX_get_error_depth(ctx);
2398 int err = X509_STORE_CTX_get_error(ctx);
2399 X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
2400 char *cn = get_san_or_cn_from_cert(x509);
2401 int keep_preverify_ok = preverify_ok;
2402
2403 coap_dtls_log(COAP_LOG_DEBUG, "depth %d error %x preverify %d cert '%s'\n",
2404 depth, err, preverify_ok, cn);
2405 if (!preverify_ok) {
2406 switch (err) {
2407 case X509_V_ERR_CERT_NOT_YET_VALID:
2408 case X509_V_ERR_CERT_HAS_EXPIRED:
2409 if (setup_data->allow_expired_certs)
2410 preverify_ok = 1;
2411 break;
2412 case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
2413 if (setup_data->allow_self_signed && !setup_data->check_common_ca)
2414 preverify_ok = 1;
2415 break;
2416 case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
2417 if (!setup_data->verify_peer_cert)
2418 preverify_ok = 1;
2419 break;
2420 case X509_V_ERR_UNABLE_TO_GET_CRL:
2421 if (setup_data->allow_no_crl)
2422 preverify_ok = 1;
2423 break;
2424 case X509_V_ERR_CRL_NOT_YET_VALID:
2425 case X509_V_ERR_CRL_HAS_EXPIRED:
2426 if (setup_data->allow_expired_crl)
2427 preverify_ok = 1;
2428 break;
2429 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
2430 case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
2431 case X509_V_ERR_AKID_SKID_MISMATCH:
2432 if (!setup_data->verify_peer_cert)
2433 preverify_ok = 1;
2434 break;
2435 default:
2436 break;
2437 }
2438 if (setup_data->cert_chain_validation &&
2439 depth > (setup_data->cert_chain_verify_depth + 1)) {
2440 preverify_ok = 0;
2441 err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
2442 X509_STORE_CTX_set_error(ctx, err);
2443 }
2444 if (!preverify_ok) {
2445 if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
2446 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2447 coap_session_str(session),
2448 "Unknown CA", cn ? cn : "?", depth);
2449 } else {
2450 coap_log_warn(" %s: %s: '%s' depth=%d\n",
2451 coap_session_str(session),
2452 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2453 }
2454 } else {
2455 coap_log_info(" %s: %s: overridden: '%s' depth=%d\n",
2456 coap_session_str(session),
2457 X509_verify_cert_error_string(err), cn ? cn : "?", depth);
2458 }
2459 }
2460 /* Certificate - depth == 0 is the Client Cert */
2461 if (setup_data->validate_cn_call_back && keep_preverify_ok) {
2462 int length = i2d_X509(x509, NULL);
2463 uint8_t *base_buf;
2464 uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
2465 int ret;
2466
2467 /* base_buf2 gets moved to the end */
2468 i2d_X509(x509, &base_buf2);
2469 coap_lock_callback_ret(ret, session->context,
2470 setup_data->validate_cn_call_back(cn, base_buf, length, session,
2471 depth, preverify_ok,
2472 setup_data->cn_call_back_arg));
2473 if (!ret) {
2474 if (depth == 0) {
2475 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
2476 } else {
2477 X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
2478 }
2479 preverify_ok = 0;
2480 }
2481 OPENSSL_free(base_buf);
2482 }
2483 OPENSSL_free(cn);
2484 return preverify_ok;
2485}
2486
2487#if COAP_SERVER_SUPPORT
2488#if OPENSSL_VERSION_NUMBER < 0x10101000L
2489/* OpenSSL < 1.1.1 */
2490/*
2491 * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2492 * it is possible to determine whether this is a PKI or PSK incoming
2493 * request and adjust the ciphers if necessary
2494 *
2495 * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2496 */
2497static int
2498tls_secret_call_back(SSL *ssl,
2499 void *secret,
2500 int *secretlen,
2501 STACK_OF(SSL_CIPHER) *peer_ciphers,
2502 const SSL_CIPHER **cipher COAP_UNUSED,
2503 void *arg) {
2504 int ii;
2505 int psk_requested = 0;
2506 coap_session_t *session;
2507 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2508
2509 session = (coap_session_t *)SSL_get_app_data(ssl);
2510 assert(session != NULL);
2511 assert(session->context != NULL);
2512 if (session == NULL ||
2513 session->context == NULL)
2514 return 0;
2515
2516 if ((session->psk_key) ||
2517 (session->context->spsk_setup_data.psk_info.key.s &&
2519 /* Is PSK being requested - if so, we need to change algorithms */
2520 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2521 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2522
2523 coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2524 SSL_CIPHER_get_name(peer_cipher));
2525 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2526 psk_requested = 1;
2527 break;
2528 }
2529 }
2530 }
2531 if (!psk_requested) {
2532 coap_log_debug(" %s: Using PKI ciphers\n",
2533 coap_session_str(session));
2534
2535 if (setup_data->verify_peer_cert) {
2536 SSL_set_verify(ssl,
2537 SSL_VERIFY_PEER |
2538 SSL_VERIFY_CLIENT_ONCE |
2539 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2540 tls_verify_call_back);
2541 } else {
2542 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2543 }
2544
2545 /* Check CA Chain */
2546 if (setup_data->cert_chain_validation)
2547 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2548
2549 /* Certificate Revocation */
2550 if (setup_data->check_cert_revocation) {
2551 X509_VERIFY_PARAM *param;
2552
2553 param = X509_VERIFY_PARAM_new();
2554 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2555 SSL_set1_param(ssl, param);
2556 X509_VERIFY_PARAM_free(param);
2557 }
2558 if (setup_data->additional_tls_setup_call_back) {
2559 /* Additional application setup wanted */
2560 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2561 return 0;
2562 }
2563 } else {
2564 if (session->psk_key) {
2565 memcpy(secret, session->psk_key->s, session->psk_key->length);
2566 *secretlen = session->psk_key->length;
2567 } else if (session->context->spsk_setup_data.psk_info.key.s &&
2569 memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2571 *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2572 }
2573 coap_log_debug(" %s: Setting PSK ciphers\n",
2574 coap_session_str(session));
2575 /*
2576 * Force a PSK algorithm to be used, so we do PSK
2577 */
2578 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2579 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2580 }
2581 return 0;
2582}
2583
2584/* OpenSSL < 1.1.1 */
2585/*
2586 * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2587 * called so it is possible to set up an extra callback to determine whether
2588 * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2589 *
2590 * Set up by SSL_CTX_set_tlsext_servername_callback() in
2591 * coap_dtls_context_set_pki()
2592 */
2593static int
2594tls_server_name_call_back(SSL *ssl,
2595 int *sd COAP_UNUSED,
2596 void *arg) {
2597 coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2598
2599 if (!ssl) {
2600 return SSL_TLSEXT_ERR_NOACK;
2601 }
2602
2603 if (setup_data->validate_sni_call_back) {
2604 /* SNI checking requested */
2605 coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2606 coap_openssl_context_t *context =
2607 ((coap_openssl_context_t *)session->context->dtls_context);
2608 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2609 size_t i;
2610
2611 if (!sni || !sni[0]) {
2612 sni = "";
2613 }
2614 for (i = 0; i < context->sni_count; i++) {
2615 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2616 break;
2617 }
2618 }
2619 if (i == context->sni_count) {
2620 SSL_CTX *ctx;
2621 coap_dtls_pki_t sni_setup_data;
2622 coap_dtls_key_t *new_entry;
2623
2624 coap_lock_callback_ret(new_entry, session->context,
2625 setup_data->validate_sni_call_back(sni,
2626 setup_data->sni_call_back_arg));
2627 if (!new_entry) {
2628 return SSL_TLSEXT_ERR_ALERT_FATAL;
2629 }
2630 /* Need to set up a new SSL_CTX to switch to */
2631 if (session->proto == COAP_PROTO_DTLS) {
2632 /* Set up DTLS context */
2633 ctx = SSL_CTX_new(DTLS_method());
2634 if (!ctx)
2635 goto error;
2636 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2637 SSL_CTX_set_app_data(ctx, &context->dtls);
2638 SSL_CTX_set_read_ahead(ctx, 1);
2639 coap_set_user_prefs(ctx);
2640 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2641 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2642 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2643 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2644 }
2645#if !COAP_DISABLE_TCP
2646 else {
2647 /* Set up TLS context */
2648 ctx = SSL_CTX_new(TLS_method());
2649 if (!ctx)
2650 goto error;
2651 SSL_CTX_set_app_data(ctx, &context->tls);
2652 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2653 coap_set_user_prefs(ctx);
2654 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2655 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2656 }
2657#endif /* !COAP_DISABLE_TCP */
2658 sni_setup_data = *setup_data;
2659 sni_setup_data.pki_key = *new_entry;
2660 setup_pki_server(ctx, &sni_setup_data);
2661
2662 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2663 (context->sni_count+1)*sizeof(sni_entry));
2664 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2665 context->sni_entry_list[context->sni_count].ctx = ctx;
2666 context->sni_count++;
2667 }
2668 SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2669 SSL_clear_options(ssl, 0xFFFFFFFFL);
2670 SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2671 }
2672
2673 /*
2674 * Have to do extra call back next to get client algorithms
2675 * SSL_get_client_ciphers() does not work this early on
2676 */
2677 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2678 return SSL_TLSEXT_ERR_OK;
2679
2680error:
2681 return SSL_TLSEXT_ERR_ALERT_WARNING;
2682}
2683
2684/* OpenSSL < 1.1.1 */
2685/*
2686 * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2687 * called to see if SNI is being used.
2688 *
2689 * Set up by SSL_CTX_set_tlsext_servername_callback()
2690 * in coap_dtls_context_set_spsk()
2691 */
2692static int
2693psk_tls_server_name_call_back(SSL *ssl,
2694 int *sd COAP_UNUSED,
2695 void *arg
2696 ) {
2697 coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2698
2699 if (!ssl) {
2700 return SSL_TLSEXT_ERR_NOACK;
2701 }
2702
2703 if (setup_data->validate_sni_call_back) {
2704 /* SNI checking requested */
2705 coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2706 coap_openssl_context_t *o_context =
2707 ((coap_openssl_context_t *)c_session->context->dtls_context);
2708 const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2709 size_t i;
2710 char lhint[COAP_DTLS_HINT_LENGTH];
2711
2712 if (!sni || !sni[0]) {
2713 sni = "";
2714 }
2715 for (i = 0; i < o_context->psk_sni_count; i++) {
2716 if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2717 break;
2718 }
2719 }
2720 if (i == o_context->psk_sni_count) {
2721 SSL_CTX *ctx;
2722 const coap_dtls_spsk_info_t *new_entry;
2723
2724 coap_lock_callback_ret(new_entry, c_session->context,
2725 setup_data->validate_sni_call_back(sni,
2726 c_session,
2727 setup_data->sni_call_back_arg));
2728 if (!new_entry) {
2729 return SSL_TLSEXT_ERR_ALERT_FATAL;
2730 }
2731 /* Need to set up a new SSL_CTX to switch to */
2732 if (c_session->proto == COAP_PROTO_DTLS) {
2733 /* Set up DTLS context */
2734 ctx = SSL_CTX_new(DTLS_method());
2735 if (!ctx)
2736 goto error;
2737 SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2738 SSL_CTX_set_app_data(ctx, &o_context->dtls);
2739 SSL_CTX_set_read_ahead(ctx, 1);
2740 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2741 SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2742 SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2743 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2744 SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2745 }
2746#if !COAP_DISABLE_TCP
2747 else {
2748 /* Set up TLS context */
2749 ctx = SSL_CTX_new(TLS_method());
2750 if (!ctx)
2751 goto error;
2752 SSL_CTX_set_app_data(ctx, &o_context->tls);
2753 SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2754 SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2755 SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2756 SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2757 }
2758#endif /* !COAP_DISABLE_TCP */
2759
2760 o_context->psk_sni_entry_list =
2761 OPENSSL_realloc(o_context->psk_sni_entry_list,
2762 (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2763 o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2764 OPENSSL_strdup(sni);
2765 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2766 *new_entry;
2767 o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2768 ctx;
2769 o_context->psk_sni_count++;
2770 }
2771 SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2772 SSL_clear_options(ssl, 0xFFFFFFFFL);
2773 SSL_set_options(ssl,
2774 SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2776 &o_context->psk_sni_entry_list[i].psk_info.key);
2777 snprintf(lhint, sizeof(lhint), "%.*s",
2778 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2779 o_context->psk_sni_entry_list[i].psk_info.hint.s);
2780 SSL_use_psk_identity_hint(ssl, lhint);
2781 }
2782
2783 /*
2784 * Have to do extra call back next to get client algorithms
2785 * SSL_get_client_ciphers() does not work this early on
2786 */
2787 SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2788 return SSL_TLSEXT_ERR_OK;
2789
2790error:
2791 return SSL_TLSEXT_ERR_ALERT_WARNING;
2792}
2793#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2794/* OpenSSL >= 1.1.1 */
2795/*
2796 * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2797 * called early in the Client Hello processing so it is possible to determine
2798 * whether this is a PKI or PSK incoming request and adjust the ciphers if
2799 * necessary.
2800 *
2801 * Set up by SSL_CTX_set_client_hello_cb().
2802 */
2803static int
2804tls_client_hello_call_back(SSL *ssl,
2805 int *al,
2806 void *arg COAP_UNUSED
2807 ) {
2808 coap_session_t *session;
2809 coap_openssl_context_t *dtls_context;
2810 coap_dtls_pki_t *setup_data;
2811 int psk_requested = 0;
2812 const unsigned char *out;
2813 size_t outlen;
2814
2815 if (!ssl) {
2816 *al = SSL_AD_INTERNAL_ERROR;
2817 return SSL_CLIENT_HELLO_ERROR;
2818 }
2819 session = (coap_session_t *)SSL_get_app_data(ssl);
2820 assert(session != NULL);
2821 assert(session->context != NULL);
2822 assert(session->context->dtls_context != NULL);
2823 if (session == NULL ||
2824 session->context == NULL ||
2825 session->context->dtls_context == NULL) {
2826 *al = SSL_AD_INTERNAL_ERROR;
2827 return SSL_CLIENT_HELLO_ERROR;
2828 }
2829 dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2830 setup_data = &dtls_context->setup_data;
2831
2832 /*
2833 * See if PSK being requested
2834 */
2835 if ((session->psk_key) ||
2836 (session->context->spsk_setup_data.psk_info.key.s &&
2838 size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2839 STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2840 STACK_OF(SSL_CIPHER) *scsvc = NULL;
2841
2842 if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2843 SSL_client_hello_isv2(ssl),
2844 &peer_ciphers, &scsvc)) {
2845 int ii;
2846 for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2847 const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2848
2850 "Client cipher: %s (%04x)\n",
2851 SSL_CIPHER_get_name(peer_cipher),
2852 SSL_CIPHER_get_protocol_id(peer_cipher));
2853 if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2854 psk_requested = 1;
2855 break;
2856 }
2857 }
2858 }
2859 sk_SSL_CIPHER_free(peer_ciphers);
2860 sk_SSL_CIPHER_free(scsvc);
2861 }
2862
2863 if (psk_requested) {
2864 /*
2865 * Client has requested PSK and it is supported
2866 */
2867 coap_log_debug(" %s: PSK request\n",
2868 coap_session_str(session));
2869 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2870 if (setup_data->additional_tls_setup_call_back) {
2871 /* Additional application setup wanted */
2872 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2873 return 0;
2874 }
2875 return SSL_CLIENT_HELLO_SUCCESS;
2876 }
2877
2878 /*
2879 * Handle Certificate requests
2880 */
2881
2882 /*
2883 * Determine what type of certificate is being requested
2884 */
2885 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
2886 &out, &outlen)) {
2887 size_t ii;
2888 for (ii = 0; ii < outlen; ii++) {
2889 switch (out[ii]) {
2890 case 0:
2891 /* RFC6091 X.509 */
2892 if (outlen >= 2) {
2893 /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
2894 goto is_x509;
2895 }
2896 break;
2897 case 2:
2898 /* RFC7250 RPK - not yet supported */
2899 break;
2900 default:
2901 break;
2902 }
2903 }
2904 *al = SSL_AD_UNSUPPORTED_EXTENSION;
2905 return SSL_CLIENT_HELLO_ERROR;
2906 }
2907
2908is_x509:
2909 if (setup_data->validate_sni_call_back) {
2910 /*
2911 * SNI checking requested
2912 */
2913 coap_dtls_pki_t sni_setup_data;
2914 coap_openssl_context_t *context =
2915 ((coap_openssl_context_t *)session->context->dtls_context);
2916 const char *sni = "";
2917 char *sni_tmp = NULL;
2918 size_t i;
2919
2920 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2921 outlen > 5 &&
2922 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2923 out[2] == TLSEXT_NAMETYPE_host_name &&
2924 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2925 /* Skip over length, type and length */
2926 out += 5;
2927 outlen -= 5;
2928 sni_tmp = OPENSSL_malloc(outlen+1);
2929 sni_tmp[outlen] = '\000';
2930 memcpy(sni_tmp, out, outlen);
2931 sni = sni_tmp;
2932 }
2933 /* Is this a cached entry? */
2934 for (i = 0; i < context->sni_count; i++) {
2935 if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2936 break;
2937 }
2938 }
2939 if (i == context->sni_count) {
2940 /*
2941 * New SNI request
2942 */
2943 coap_dtls_key_t *new_entry;
2944
2945 coap_lock_callback_ret(new_entry, session->context,
2946 setup_data->validate_sni_call_back(sni,
2947 setup_data->sni_call_back_arg));
2948 if (!new_entry) {
2949 *al = SSL_AD_UNRECOGNIZED_NAME;
2950 return SSL_CLIENT_HELLO_ERROR;
2951 }
2952
2953
2954 context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2955 (context->sni_count+1)*sizeof(sni_entry));
2956 context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2957 context->sni_entry_list[context->sni_count].pki_key = *new_entry;
2958 context->sni_count++;
2959 }
2960 if (sni_tmp) {
2961 OPENSSL_free(sni_tmp);
2962 }
2963 sni_setup_data = *setup_data;
2964 sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
2965 setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
2966 } else {
2967 setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
2968 }
2969
2970 coap_log_debug(" %s: Using PKI ciphers\n",
2971 coap_session_str(session));
2972
2973 if (setup_data->verify_peer_cert) {
2974 SSL_set_verify(ssl,
2975 SSL_VERIFY_PEER |
2976 SSL_VERIFY_CLIENT_ONCE |
2977 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2978 tls_verify_call_back);
2979 } else {
2980 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2981 }
2982
2983 /* Check CA Chain */
2984 if (setup_data->cert_chain_validation)
2985 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2986
2987 /* Certificate Revocation */
2988 if (setup_data->check_cert_revocation) {
2989 X509_VERIFY_PARAM *param;
2990
2991 param = X509_VERIFY_PARAM_new();
2992 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2993 SSL_set1_param(ssl, param);
2994 X509_VERIFY_PARAM_free(param);
2995 }
2996 if (setup_data->additional_tls_setup_call_back) {
2997 /* Additional application setup wanted */
2998 if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2999 return 0;
3000 }
3001 return SSL_CLIENT_HELLO_SUCCESS;
3002}
3003
3004/* OpenSSL >= 1.1.1 */
3005/*
3006 * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is
3007 * called early in the Client Hello processing so it is possible to determine
3008 * whether SNI needs to be handled
3009 *
3010 * Set up by SSL_CTX_set_client_hello_cb().
3011 */
3012static int
3013psk_tls_client_hello_call_back(SSL *ssl,
3014 int *al,
3015 void *arg COAP_UNUSED
3016 ) {
3017 coap_session_t *c_session;
3018 coap_openssl_context_t *o_context;
3019 coap_dtls_spsk_t *setup_data;
3020 const unsigned char *out;
3021 size_t outlen;
3022
3023 if (!ssl)
3024 goto int_err;
3025 c_session = (coap_session_t *)SSL_get_app_data(ssl);
3026 if (!c_session || !c_session->context) {
3027 goto int_err;
3028 }
3029 o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
3030 if (!o_context) {
3031 goto int_err;
3032 }
3033 setup_data = &c_session->context->spsk_setup_data;
3034
3035 if (setup_data->validate_sni_call_back) {
3036 /*
3037 * SNI checking requested
3038 */
3039 const char *sni = "";
3040 char *sni_tmp = NULL;
3041 size_t i;
3042 char lhint[COAP_DTLS_HINT_LENGTH];
3043
3044 if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
3045 outlen > 5 &&
3046 (((out[0]<<8) + out[1] +2) == (int)outlen) &&
3047 out[2] == TLSEXT_NAMETYPE_host_name &&
3048 (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
3049 /* Skip over length, type and length */
3050 out += 5;
3051 outlen -= 5;
3052 sni_tmp = OPENSSL_malloc(outlen+1);
3053 if (sni_tmp) {
3054 sni_tmp[outlen] = '\000';
3055 memcpy(sni_tmp, out, outlen);
3056 sni = sni_tmp;
3057 }
3058 }
3059
3060 /* Is this a cached entry? */
3061 for (i = 0; i < o_context->psk_sni_count; i++) {
3062 if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) {
3063 break;
3064 }
3065 }
3066 if (i == o_context->psk_sni_count) {
3067 /*
3068 * New SNI request
3069 */
3070 psk_sni_entry *tmp_entry;
3071 const coap_dtls_spsk_info_t *new_entry;
3072
3073 coap_lock_callback_ret(new_entry, c_session->context,
3074 setup_data->validate_sni_call_back(
3075 sni,
3076 c_session,
3077 setup_data->sni_call_back_arg));
3078 if (!new_entry) {
3079 *al = SSL_AD_UNRECOGNIZED_NAME;
3080 return SSL_CLIENT_HELLO_ERROR;
3081 }
3082
3083 tmp_entry =
3084 OPENSSL_realloc(o_context->psk_sni_entry_list,
3085 (o_context->psk_sni_count+1)*sizeof(sni_entry));
3086 if (tmp_entry) {
3087 o_context->psk_sni_entry_list = tmp_entry;
3088 o_context->psk_sni_entry_list[o_context->psk_sni_count]
3089 .sni =
3090 OPENSSL_strdup(sni);
3091 if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) {
3092 o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
3093 *new_entry;
3094 o_context->psk_sni_count++;
3095 }
3096 }
3097 }
3098 if (sni_tmp) {
3099 OPENSSL_free(sni_tmp);
3100 }
3101 if (coap_session_refresh_psk_hint(c_session,
3102 &o_context->psk_sni_entry_list[i].psk_info.hint)
3103 == 0) {
3104 goto int_err;
3105 }
3106 if (coap_session_refresh_psk_key(c_session,
3107 &o_context->psk_sni_entry_list[i].psk_info.key)
3108 == 0) {
3109 goto int_err;
3110 }
3111 if (o_context->psk_sni_entry_list[i].psk_info.hint.s) {
3112 snprintf(lhint, sizeof(lhint), "%.*s",
3113 (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
3114 o_context->psk_sni_entry_list[i].psk_info.hint.s);
3115 SSL_use_psk_identity_hint(ssl, lhint);
3116 }
3117 }
3118 return SSL_CLIENT_HELLO_SUCCESS;
3119
3120int_err:
3121 *al = SSL_AD_INTERNAL_ERROR;
3122 return SSL_CLIENT_HELLO_ERROR;
3123}
3124#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3125#endif /* COAP_SERVER_SUPPORT */
3126
3127int
3129 const coap_dtls_pki_t *setup_data,
3130 const coap_dtls_role_t role) {
3131 coap_openssl_context_t *context =
3132 ((coap_openssl_context_t *)ctx->dtls_context);
3133 BIO *bio;
3134 if (!setup_data)
3135 return 0;
3136 context->setup_data = *setup_data;
3137
3138 if (context->setup_data.pki_key.key_type == COAP_PKI_KEY_DEFINE) {
3139 if (context->setup_data.pki_key.key.define.ca_def == COAP_PKI_KEY_DEF_ENGINE ||
3140 context->setup_data.pki_key.key.define.public_cert_def == COAP_PKI_KEY_DEF_ENGINE ||
3141 context->setup_data.pki_key.key.define.private_key_def == COAP_PKI_KEY_DEF_ENGINE) {
3142 if (!defined_engine) {
3143 coap_log_warn("setup_pki: OpenSSL Engine not configured, PKI not set up\n");
3144 return 0;
3145 }
3146 }
3147 }
3148
3149 if (!context->setup_data.verify_peer_cert) {
3150 /* Needs to be clear so that no CA DNs are transmitted */
3151 context->setup_data.check_common_ca = 0;
3152 /* Allow all of these but warn if issue */
3153 context->setup_data.allow_self_signed = 1;
3154 context->setup_data.allow_expired_certs = 1;
3155 context->setup_data.cert_chain_validation = 1;
3156 context->setup_data.cert_chain_verify_depth = 10;
3157 context->setup_data.check_cert_revocation = 1;
3158 context->setup_data.allow_no_crl = 1;
3159 context->setup_data.allow_expired_crl = 1;
3160 context->setup_data.allow_bad_md_hash = 1;
3161 context->setup_data.allow_short_rsa_length = 1;
3162 }
3163#if COAP_SERVER_SUPPORT
3164 if (role == COAP_DTLS_ROLE_SERVER) {
3165 if (context->dtls.ctx) {
3166 /* SERVER DTLS */
3167#if OPENSSL_VERSION_NUMBER < 0x10101000L
3168 if (!setup_pki_server(context->dtls.ctx, setup_data))
3169 return 0;
3170#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3171 /* libcoap is managing TLS connection based on setup_data options */
3172 /* Need to set up logic to differentiate between a PSK or PKI session */
3173 /*
3174 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3175 * which is not in 1.1.0
3176 */
3177#if OPENSSL_VERSION_NUMBER < 0x10101000L
3178 if (SSLeay() >= 0x10101000L) {
3179 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3180 "no certificate checking\n",
3181 OPENSSL_VERSION_NUMBER, SSLeay());
3182 }
3183 SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
3184 SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
3185 tls_server_name_call_back);
3186#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3187 SSL_CTX_set_client_hello_cb(context->dtls.ctx,
3188 tls_client_hello_call_back,
3189 NULL);
3190#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3191 }
3192#if !COAP_DISABLE_TCP
3193 if (context->tls.ctx) {
3194 /* SERVER TLS */
3195#if OPENSSL_VERSION_NUMBER < 0x10101000L
3196 if (!setup_pki_server(context->tls.ctx, setup_data))
3197 return 0;
3198#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3199 /* libcoap is managing TLS connection based on setup_data options */
3200 /* Need to set up logic to differentiate between a PSK or PKI session */
3201 /*
3202 * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
3203 * which is not in 1.1.0
3204 */
3205#if OPENSSL_VERSION_NUMBER < 0x10101000L
3206 if (SSLeay() >= 0x10101000L) {
3207 coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
3208 "no certificate checking\n",
3209 OPENSSL_VERSION_NUMBER, SSLeay());
3210 }
3211 SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
3212 SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
3213 tls_server_name_call_back);
3214#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3215 SSL_CTX_set_client_hello_cb(context->tls.ctx,
3216 tls_client_hello_call_back,
3217 NULL);
3218#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3219 /* TLS Only */
3220 SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
3221 }
3222#endif /* !COAP_DISABLE_TCP */
3223 }
3224#else /* ! COAP_SERVER_SUPPORT */
3225 (void)role;
3226#endif /* ! COAP_SERVER_SUPPORT */
3227
3228 if (!context->dtls.ssl) {
3229 /* This is set up to handle new incoming sessions to a server */
3230 context->dtls.ssl = SSL_new(context->dtls.ctx);
3231 if (!context->dtls.ssl)
3232 return 0;
3233 bio = BIO_new(context->dtls.meth);
3234 if (!bio) {
3235 SSL_free(context->dtls.ssl);
3236 context->dtls.ssl = NULL;
3237 return 0;
3238 }
3239 SSL_set_bio(context->dtls.ssl, bio, bio);
3240 SSL_set_app_data(context->dtls.ssl, NULL);
3241 SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
3242 SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
3243 }
3244 context->psk_pki_enabled |= IS_PKI;
3245 if (setup_data->use_cid) {
3246 coap_log_warn("OpenSSL has no Connection-ID support\n");
3247 }
3248 return 1;
3249}
3250
3251int
3253 const char *ca_file,
3254 const char *ca_dir
3255 ) {
3256 coap_openssl_context_t *context =
3257 ((coap_openssl_context_t *)ctx->dtls_context);
3258 if (context->dtls.ctx) {
3259 if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
3260 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3261 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3262 return 0;
3263 }
3264 }
3265#if !COAP_DISABLE_TCP
3266 if (context->tls.ctx) {
3267 if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
3268 coap_log_warn("Unable to install root CAs (%s : %s)\n",
3269 ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
3270 return 0;
3271 }
3272 }
3273#endif /* !COAP_DISABLE_TCP */
3274 return 1;
3275}
3276
3277int
3279#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3280 coap_openssl_context_t *context =
3281 ((coap_openssl_context_t *)ctx->dtls_context);
3282 if (context->dtls.ctx) {
3283 if (!SSL_CTX_set_default_verify_store(context->dtls.ctx)) {
3284 coap_log_warn("Unable to load trusted root CAs\n");
3285 return 0;
3286 }
3287 }
3288#if !COAP_DISABLE_TCP
3289 if (context->tls.ctx) {
3290 if (!SSL_CTX_set_default_verify_store(context->tls.ctx)) {
3291 coap_log_warn("Unable to load trusted root CAs\n");
3292 return 0;
3293 }
3294 }
3295#endif /* !COAP_DISABLE_TCP */
3296 return 1;
3297#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3298 (void)ctx;
3299 coap_log_warn("coap_context_set_pki_trust_store: (D)TLS environment "
3300 "not supported for OpenSSL < v3.0.0\n");
3301 return 0;
3302#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
3303}
3304
3305int
3307 coap_openssl_context_t *context =
3308 ((coap_openssl_context_t *)ctx->dtls_context);
3309 return context->psk_pki_enabled ? 1 : 0;
3310}
3311
3312
3313void
3314coap_dtls_free_context(void *handle) {
3315 size_t i;
3316 coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
3317
3318 if (context->dtls.ssl)
3319 SSL_free(context->dtls.ssl);
3320 if (context->dtls.ctx)
3321 SSL_CTX_free(context->dtls.ctx);
3322 if (context->dtls.cookie_hmac)
3323 HMAC_CTX_free(context->dtls.cookie_hmac);
3324 if (context->dtls.meth)
3325 BIO_meth_free(context->dtls.meth);
3326 if (context->dtls.bio_addr)
3327 BIO_ADDR_free(context->dtls.bio_addr);
3328#if !COAP_DISABLE_TCP
3329 if (context->tls.ctx)
3330 SSL_CTX_free(context->tls.ctx);
3331 if (context->tls.meth)
3332 BIO_meth_free(context->tls.meth);
3333#endif /* !COAP_DISABLE_TCP */
3334 for (i = 0; i < context->sni_count; i++) {
3335 OPENSSL_free(context->sni_entry_list[i].sni);
3336#if OPENSSL_VERSION_NUMBER < 0x10101000L
3337 SSL_CTX_free(context->sni_entry_list[i].ctx);
3338#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3339 }
3340 if (context->sni_count)
3341 OPENSSL_free(context->sni_entry_list);
3342 for (i = 0; i < context->psk_sni_count; i++) {
3343 OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
3344#if OPENSSL_VERSION_NUMBER < 0x10101000L
3345 SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
3346#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
3347 }
3348 if (context->psk_sni_count)
3349 OPENSSL_free(context->psk_sni_entry_list);
3350 coap_free_type(COAP_STRING, context);
3351}
3352
3353#if COAP_SERVER_SUPPORT
3354void *
3356 BIO *nbio = NULL;
3357 SSL *nssl = NULL, *ssl = NULL;
3358 coap_ssl_data *data;
3359 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3360 int r;
3361 const coap_bin_const_t *psk_hint;
3362
3363 nssl = SSL_new(dtls->ctx);
3364 if (!nssl)
3365 goto error;
3366 nbio = BIO_new(dtls->meth);
3367 if (!nbio)
3368 goto error;
3369 SSL_set_bio(nssl, nbio, nbio);
3370 SSL_set_app_data(nssl, NULL);
3371 SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
3372 SSL_set_mtu(nssl, (long)session->mtu);
3373 ssl = dtls->ssl;
3374 dtls->ssl = nssl;
3375 nssl = NULL;
3376 SSL_set_app_data(ssl, session);
3377
3378 data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3379 data->session = session;
3380
3381 /* hint may get updated if/when handling SNI callback */
3382 psk_hint = coap_get_session_server_psk_hint(session);
3383 if (psk_hint != NULL && psk_hint->length) {
3384 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3385
3386 if (hint) {
3387 memcpy(hint, psk_hint->s, psk_hint->length);
3388 hint[psk_hint->length] = '\000';
3389 SSL_use_psk_identity_hint(ssl, hint);
3390 OPENSSL_free(hint);
3391 } else {
3392 coap_log_warn("hint malloc failure\n");
3393 }
3394 }
3395
3396 r = SSL_accept(ssl);
3397 if (r == -1) {
3398 int err = SSL_get_error(ssl, r);
3399 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3400 r = 0;
3401 }
3402
3403 if (r == 0) {
3404 SSL_free(ssl);
3405 return NULL;
3406 }
3407
3408 return ssl;
3409
3410error:
3411 if (nssl)
3412 SSL_free(nssl);
3413 return NULL;
3414}
3415#endif /* COAP_SERVER_SUPPORT */
3416
3417#if COAP_CLIENT_SUPPORT
3418static int
3419setup_client_ssl_session(coap_session_t *session, SSL *ssl
3420 ) {
3421 coap_openssl_context_t *context =
3422 ((coap_openssl_context_t *)session->context->dtls_context);
3423
3424 if (context->psk_pki_enabled & IS_PSK) {
3425 coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
3426
3427 /* Issue SNI if requested */
3428 if (setup_data->client_sni &&
3429 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3430 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3431 setup_data->client_sni);
3432 }
3433 SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
3434#if COAP_SERVER_SUPPORT
3435 SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
3436#endif /* COAP_SERVER_SUPPORT */
3437 SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
3438 if (setup_data->validate_ih_call_back) {
3439 if (session->proto == COAP_PROTO_DTLS) {
3440 SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
3441 }
3442#if !COAP_DISABLE_TCP
3443 else {
3444 SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
3445 }
3446#endif /* !COAP_DISABLE_TCP */
3447 coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
3448 }
3449 }
3450 if ((context->psk_pki_enabled & IS_PKI) ||
3451 (context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
3452 /*
3453 * If neither PSK or PKI have been set up, use PKI basics.
3454 * This works providing COAP_PKI_KEY_PEM has a value of 0.
3455 */
3456 coap_dtls_pki_t *setup_data = &context->setup_data;
3457
3458 if (!(context->psk_pki_enabled & IS_PKI)) {
3459 /* PKI not defined - set up some defaults */
3460 setup_data->verify_peer_cert = 1;
3461 setup_data->check_common_ca = 0;
3462 setup_data->allow_self_signed = 1;
3463 setup_data->allow_expired_certs = 1;
3464 setup_data->cert_chain_validation = 1;
3465 setup_data->cert_chain_verify_depth = 2;
3466 setup_data->check_cert_revocation = 1;
3467 setup_data->allow_no_crl = 1;
3468 setup_data->allow_expired_crl = 1;
3469 setup_data->is_rpk_not_cert = 0;
3470 setup_data->use_cid = 0;
3471 }
3472 if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
3473 return 0;
3474 /* libcoap is managing (D)TLS connection based on setup_data options */
3475#if !COAP_DISABLE_TCP
3476 if (session->proto == COAP_PROTO_TLS)
3477 SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
3478#endif /* !COAP_DISABLE_TCP */
3479
3480 /* Issue SNI if requested */
3481 if (setup_data->client_sni &&
3482 SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
3483 coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
3484 setup_data->client_sni);
3485 }
3486 /* Certificate Revocation */
3487 if (setup_data->check_cert_revocation) {
3488 X509_VERIFY_PARAM *param;
3489
3490 param = X509_VERIFY_PARAM_new();
3491 X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
3492 SSL_set1_param(ssl, param);
3493 X509_VERIFY_PARAM_free(param);
3494 }
3495
3496 /* Verify Peer */
3497 if (setup_data->verify_peer_cert)
3498 SSL_set_verify(ssl,
3499 SSL_VERIFY_PEER |
3500 SSL_VERIFY_CLIENT_ONCE |
3501 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
3502 tls_verify_call_back);
3503 else
3504 SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
3505
3506 /* Check CA Chain */
3507 if (setup_data->cert_chain_validation)
3508 SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
3509
3510 }
3511#if COAP_DTLS_RETRANSMIT_MS != 1000
3512#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3513 if (session->proto == COAP_PROTO_DTLS) {
3514 DTLS_set_timer_cb(ssl, timer_cb);
3515 }
3516#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
3517#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
3518 return 1;
3519}
3520
3521void *
3523 BIO *bio = NULL;
3524 SSL *ssl = NULL;
3525 coap_ssl_data *data;
3526 int r;
3527 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3528 coap_dtls_context_t *dtls = &context->dtls;
3529
3530 ssl = SSL_new(dtls->ctx);
3531 if (!ssl)
3532 goto error;
3533 bio = BIO_new(dtls->meth);
3534 if (!bio)
3535 goto error;
3536 data = (coap_ssl_data *)BIO_get_data(bio);
3537 data->session = session;
3538 SSL_set_bio(ssl, bio, bio);
3539 SSL_set_app_data(ssl, session);
3540 SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
3541 SSL_set_mtu(ssl, (long)session->mtu);
3542
3543 if (!setup_client_ssl_session(session, ssl))
3544 goto error;
3545
3546 session->dtls_timeout_count = 0;
3547
3548 r = SSL_connect(ssl);
3549 if (r == -1) {
3550 int ret = SSL_get_error(ssl, r);
3551 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3552 r = 0;
3553 }
3554
3555 if (r == 0)
3556 goto error;
3557
3558 session->tls = ssl;
3559 return ssl;
3560
3561error:
3562 if (ssl)
3563 SSL_free(ssl);
3564 return NULL;
3565}
3566
3567void
3569 SSL *ssl = (SSL *)session->tls;
3570 if (ssl)
3571 SSL_set_mtu(ssl, (long)session->mtu);
3572}
3573#endif /* COAP_CLIENT_SUPPORT */
3574
3575void
3577 SSL *ssl = (SSL *)session->tls;
3578 if (ssl) {
3579 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3580 int r = SSL_shutdown(ssl);
3581 if (r == 0)
3582 SSL_shutdown(ssl);
3583 }
3584 SSL_free(ssl);
3585 session->tls = NULL;
3586 if (session->context)
3588 }
3589}
3590
3591ssize_t
3593 const uint8_t *data, size_t data_len) {
3594 int r;
3595 SSL *ssl = (SSL *)session->tls;
3596
3597 if (ssl == NULL) {
3599 return -1;
3600 }
3601
3602 session->dtls_event = -1;
3603 ERR_clear_error();
3604 r = SSL_write(ssl, data, (int)data_len);
3605
3606 if (r <= 0) {
3607 int err = SSL_get_error(ssl, r);
3608 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3609 r = 0;
3610 } else {
3611 if (err == SSL_ERROR_ZERO_RETURN)
3613 else if (err == SSL_ERROR_SSL) {
3614 unsigned long e = ERR_get_error();
3615
3616 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d: %s\n",
3617 coap_session_str(session),
3618 ERR_GET_REASON(e), ERR_reason_error_string(e));
3620 } else {
3621 coap_log_info("***%s: coap_dtls_send: cannot send PDU: %d\n",
3622 coap_session_str(session), err);
3623 }
3624 r = -1;
3625 }
3626 }
3627
3628 if (session->dtls_event >= 0) {
3629 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3630 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3631 coap_handle_event_lkd(session->context, session->dtls_event, session);
3632 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3633 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3635 r = -1;
3636 }
3637 }
3638
3639 if (r > 0) {
3640 if (r == (ssize_t)data_len)
3641 coap_log_debug("* %s: dtls: sent %4d bytes\n",
3642 coap_session_str(session), r);
3643 else
3644 coap_log_debug("* %s: dtls: sent %4d of %4zd bytes\n",
3645 coap_session_str(session), r, data_len);
3646 }
3647 return r;
3648}
3649
3650int
3652 return 0;
3653}
3654
3656coap_dtls_get_context_timeout(void *dtls_context) {
3657 (void)dtls_context;
3658 return 0;
3659}
3660
3663 SSL *ssl = (SSL *)session->tls;
3664 coap_ssl_data *ssl_data;
3665
3666 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3667 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3668 return ssl_data->timeout;
3669}
3670
3671/*
3672 * return 1 timed out
3673 * 0 still timing out
3674 */
3675int
3677 SSL *ssl = (SSL *)session->tls;
3678
3679 assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3680 if ((++session->dtls_timeout_count > session->max_retransmit) ||
3681 (DTLSv1_handle_timeout(ssl) < 0)) {
3682 /* Too many retries */
3684 return 1;
3685 }
3686 return 0;
3687}
3688
3689#if COAP_SERVER_SUPPORT
3690int
3692 const uint8_t *data, size_t data_len) {
3693 coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3694 coap_ssl_data *ssl_data;
3695 int r;
3696
3697 SSL_set_mtu(dtls->ssl, (long)session->mtu);
3698 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(dtls->ssl));
3699 assert(ssl_data != NULL);
3700 if (ssl_data->pdu_len) {
3701 coap_log_err("** %s: Previous data not read %u bytes\n",
3702 coap_session_str(session), ssl_data->pdu_len);
3703 }
3704 ssl_data->session = session;
3705 ssl_data->pdu = data;
3706 ssl_data->pdu_len = (unsigned)data_len;
3707 r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3708 if (r <= 0) {
3709 int err = SSL_get_error(dtls->ssl, r);
3710 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3711 /* Got a ClientHello, sent-out a VerifyRequest */
3712 r = 0;
3713 }
3714 } else {
3715 /* Got a valid answer to a VerifyRequest */
3716 r = 1;
3717 }
3718
3719 /*
3720 * Cannot check if data is left on the stack in error as DTLSv1_listen()
3721 * only does a 'peek' read of the incoming data.
3722 *
3723 */
3724 return r;
3725}
3726#endif /* COAP_SERVER_SUPPORT */
3727
3728int
3729coap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3730 coap_ssl_data *ssl_data;
3731 SSL *ssl = (SSL *)session->tls;
3732 int r;
3733#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3734 int retry = 0;
3735#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3736
3737 assert(ssl != NULL);
3738
3739 int in_init = SSL_in_init(ssl);
3740 uint8_t pdu[COAP_RXBUFFER_SIZE];
3741 ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3742 assert(ssl_data != NULL);
3743
3744 if (ssl_data->pdu_len) {
3745 coap_log_err("** %s: Previous data not read %u bytes\n",
3746 coap_session_str(session), ssl_data->pdu_len);
3747 }
3748 ssl_data->pdu = data;
3749 ssl_data->pdu_len = (unsigned)data_len;
3750
3751 session->dtls_event = -1;
3752#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3753retry:
3754#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3755 ERR_clear_error();
3756 r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3757 if (r > 0) {
3758 coap_log_debug("* %s: dtls: recv %4d bytes\n",
3759 coap_session_str(session), r);
3760 r = coap_handle_dgram(session->context, session, pdu, (size_t)r);
3761 goto finished;
3762 } else {
3763 int err = SSL_get_error(ssl, r);
3764 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3765 if (in_init && SSL_is_init_finished(ssl)) {
3766 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
3767 coap_session_str(session), SSL_get_cipher_name(ssl));
3769 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3770 }
3771 r = 0;
3772 } else {
3773 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
3775 else if (err == SSL_ERROR_SSL) {
3776 unsigned long e = ERR_get_error();
3777
3778#if OPENSSL_VERSION_NUMBER >= 0x30000000L
3779#include <openssl/proverr.h>
3780 if (ERR_GET_REASON(e) == PROV_R_SEARCH_ONLY_SUPPORTED_FOR_DIRECTORIES && !retry) {
3781 /* Loading trust store - first access causes a directory read error */
3782 retry = 1;
3783 goto retry;
3784 }
3785#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
3786 coap_log_info("***%s: coap_dtls_receive: cannot recv PDU: %d: %s\n",
3787 coap_session_str(session),
3788 ERR_GET_REASON(e), ERR_reason_error_string(e));
3790 } else {
3791 coap_log_info("***%s: coap_dtls_receive: cannot send PDU %d\n",
3792 coap_session_str(session), err);
3793 }
3794 r = -1;
3795 }
3796 if (session->dtls_event >= 0) {
3797 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
3798 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3799 coap_handle_event_lkd(session->context, session->dtls_event, session);
3800 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3801 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3803 ssl_data = NULL;
3804 r = -1;
3805 }
3806 }
3807 }
3808
3809finished:
3810 if (ssl_data && ssl_data->pdu_len) {
3811 /* pdu data is held on stack which will not stay there */
3812 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3813 ssl_data->pdu_len = 0;
3814 ssl_data->pdu = NULL;
3815 }
3816 return r;
3817}
3818
3819unsigned int
3821 unsigned int overhead = 37;
3822 const SSL_CIPHER *s_ciph = NULL;
3823 if (session->tls != NULL)
3824 s_ciph = SSL_get_current_cipher(session->tls);
3825 if (s_ciph) {
3826 unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3827
3828 const EVP_CIPHER *e_ciph;
3829 const EVP_MD *e_md;
3830 char cipher[128];
3831
3832 e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3833
3834 switch (EVP_CIPHER_mode(e_ciph)) {
3835 case EVP_CIPH_GCM_MODE:
3836 ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3837 maclen = EVP_GCM_TLS_TAG_LEN;
3838 break;
3839
3840 case EVP_CIPH_CCM_MODE:
3841 ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3842 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3843 if (strstr(cipher, "CCM8"))
3844 maclen = 8;
3845 else
3846 maclen = 16;
3847 break;
3848
3849 case EVP_CIPH_CBC_MODE:
3850 e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3851 blocksize = EVP_CIPHER_block_size(e_ciph);
3852 ivlen = EVP_CIPHER_iv_length(e_ciph);
3853 pad = 1;
3854 maclen = EVP_MD_size(e_md);
3855 break;
3856
3857 case EVP_CIPH_STREAM_CIPHER:
3858 /* Seen with PSK-CHACHA20-POLY1305 */
3859 ivlen = 8;
3860 maclen = 8;
3861 break;
3862
3863 default:
3864 SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3865 coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3866 cipher);
3867 ivlen = 8;
3868 maclen = 16;
3869 break;
3870 }
3871 overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3872 }
3873 return overhead;
3874}
3875
3876#if !COAP_DISABLE_TCP
3877#if COAP_CLIENT_SUPPORT
3878void *
3880 BIO *bio = NULL;
3881 SSL *ssl = NULL;
3882 int r;
3883 coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3884 coap_tls_context_t *tls = &context->tls;
3885
3886 ssl = SSL_new(tls->ctx);
3887 if (!ssl)
3888 goto error;
3889 bio = BIO_new(tls->meth);
3890 if (!bio)
3891 goto error;
3892 BIO_set_data(bio, session);
3893 SSL_set_bio(ssl, bio, bio);
3894 SSL_set_app_data(ssl, session);
3895
3896 if (!setup_client_ssl_session(session, ssl))
3897 return 0;
3898
3899 r = SSL_connect(ssl);
3900 if (r == -1) {
3901 int ret = SSL_get_error(ssl, r);
3902 if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3903 r = 0;
3904 if (ret == SSL_ERROR_WANT_READ)
3905 session->sock.flags |= COAP_SOCKET_WANT_READ;
3906 if (ret == SSL_ERROR_WANT_WRITE) {
3907 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3908#ifdef COAP_EPOLL_SUPPORT
3909 coap_epoll_ctl_mod(&session->sock,
3910 EPOLLOUT |
3911 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3912 EPOLLIN : 0),
3913 __func__);
3914#endif /* COAP_EPOLL_SUPPORT */
3915 }
3916 }
3917
3918 if (r == 0)
3919 goto error;
3920
3921 session->tls = ssl;
3922 if (SSL_is_init_finished(ssl)) {
3924 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3925 }
3926
3927 return ssl;
3928
3929error:
3930 if (ssl)
3931 SSL_free(ssl);
3932 return NULL;
3933}
3934#endif /* COAP_CLIENT_SUPPORT */
3935
3936#if COAP_SERVER_SUPPORT
3937void *
3939 BIO *bio = NULL;
3940 SSL *ssl = NULL;
3941 coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
3942 int r;
3943 const coap_bin_const_t *psk_hint;
3944
3945 ssl = SSL_new(tls->ctx);
3946 if (!ssl)
3947 goto error;
3948 bio = BIO_new(tls->meth);
3949 if (!bio)
3950 goto error;
3951 BIO_set_data(bio, session);
3952 SSL_set_bio(ssl, bio, bio);
3953 SSL_set_app_data(ssl, session);
3954
3955 psk_hint = coap_get_session_server_psk_hint(session);
3956 if (psk_hint != NULL && psk_hint->length) {
3957 char *hint = OPENSSL_malloc(psk_hint->length + 1);
3958
3959 if (hint) {
3960 memcpy(hint, psk_hint->s, psk_hint->length);
3961 hint[psk_hint->length] = '\000';
3962 SSL_use_psk_identity_hint(ssl, hint);
3963 OPENSSL_free(hint);
3964 } else {
3965 coap_log_warn("hint malloc failure\n");
3966 }
3967 }
3968
3969 r = SSL_accept(ssl);
3970 if (r == -1) {
3971 int err = SSL_get_error(ssl, r);
3972 if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3973 r = 0;
3974 if (err == SSL_ERROR_WANT_READ)
3975 session->sock.flags |= COAP_SOCKET_WANT_READ;
3976 if (err == SSL_ERROR_WANT_WRITE) {
3977 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3978#ifdef COAP_EPOLL_SUPPORT
3979 coap_epoll_ctl_mod(&session->sock,
3980 EPOLLOUT |
3981 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3982 EPOLLIN : 0),
3983 __func__);
3984#endif /* COAP_EPOLL_SUPPORT */
3985 }
3986 }
3987
3988 if (r == 0)
3989 goto error;
3990
3991 session->tls = ssl;
3992 if (SSL_is_init_finished(ssl)) {
3994 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3995 }
3996
3997#if COAP_DTLS_RETRANSMIT_MS != 1000
3998#if OPENSSL_VERSION_NUMBER >= 0x10101000L
3999 if (session->proto == COAP_PROTO_DTLS) {
4000 DTLS_set_timer_cb(ssl, timer_cb);
4001 }
4002#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
4003#endif /* COAP_DTLS_RETRANSMIT_MS != 1000 */
4004
4005 return ssl;
4006
4007error:
4008 if (ssl)
4009 SSL_free(ssl);
4010 return NULL;
4011}
4012#endif /* COAP_SERVER_SUPPORT */
4013
4014void
4016 SSL *ssl = (SSL *)session->tls;
4017 if (ssl) {
4018 if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
4019 int r = SSL_shutdown(ssl);
4020 if (r == 0)
4021 SSL_shutdown(ssl);
4022 }
4023 SSL_free(ssl);
4024 session->tls = NULL;
4025 if (session->context)
4027 }
4028}
4029
4030/*
4031 * strm
4032 * return +ve Number of bytes written.
4033 * -1 Error (error in errno).
4034 */
4035ssize_t
4036coap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
4037 SSL *ssl = (SSL *)session->tls;
4038 int r, in_init;
4039
4040 if (ssl == NULL)
4041 return -1;
4042
4043 in_init = !SSL_is_init_finished(ssl);
4044 session->dtls_event = -1;
4045 ERR_clear_error();
4046 r = SSL_write(ssl, data, (int)data_len);
4047
4048 if (r <= 0) {
4049 int err = SSL_get_error(ssl, r);
4050 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4051 if (in_init && SSL_is_init_finished(ssl)) {
4052 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4053 coap_session_str(session), SSL_get_cipher_name(ssl));
4055 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4056 }
4057 if (err == SSL_ERROR_WANT_READ)
4058 session->sock.flags |= COAP_SOCKET_WANT_READ;
4059 else if (err == SSL_ERROR_WANT_WRITE) {
4060 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4061#ifdef COAP_EPOLL_SUPPORT
4062 coap_epoll_ctl_mod(&session->sock,
4063 EPOLLOUT |
4064 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4065 EPOLLIN : 0),
4066 __func__);
4067#endif /* COAP_EPOLL_SUPPORT */
4068 }
4069 r = 0;
4070 } else {
4071 if (err == SSL_ERROR_ZERO_RETURN)
4073 else if (err == SSL_ERROR_SSL) {
4074 unsigned long e = ERR_get_error();
4075
4076 coap_log_info("***%s: coap_tls_write: cannot send PDU: %d: %s\n",
4077 coap_session_str(session),
4078 ERR_GET_REASON(e), ERR_reason_error_string(e));
4080 } else {
4081 coap_log_info("***%s: coap_tls_send: cannot send PDU: %d\n",
4082 coap_session_str(session), err);
4083 }
4084 r = -1;
4085 }
4086 } else if (in_init && SSL_is_init_finished(ssl)) {
4087 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4088 coap_session_str(session), SSL_get_cipher_name(ssl));
4090 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4091 }
4092
4093 if (session->dtls_event >= 0) {
4094 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4095 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4096 coap_handle_event_lkd(session->context, session->dtls_event, session);
4097 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4098 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4100 r = -1;
4101 }
4102 }
4103
4104 if (r >= 0) {
4105 if (r == (ssize_t)data_len)
4106 coap_log_debug("* %s: tls: sent %4d bytes\n",
4107 coap_session_str(session), r);
4108 else
4109 coap_log_debug("* %s: tls: sent %4d of %4zd bytes\n",
4110 coap_session_str(session), r, data_len);
4111 }
4112 return r;
4113}
4114
4115/*
4116 * strm
4117 * return >=0 Number of bytes read.
4118 * -1 Error (error in errno).
4119 */
4120ssize_t
4121coap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
4122 SSL *ssl = (SSL *)session->tls;
4123 int r, in_init;
4124
4125 if (ssl == NULL) {
4126 errno = ENXIO;
4127 return -1;
4128 }
4129
4130 in_init = !SSL_is_init_finished(ssl);
4131 session->dtls_event = -1;
4132 ERR_clear_error();
4133 r = SSL_read(ssl, data, (int)data_len);
4134 if (r <= 0) {
4135 int err = SSL_get_error(ssl, r);
4136 if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
4137 if (in_init && SSL_is_init_finished(ssl)) {
4138 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4139 coap_session_str(session), SSL_get_cipher_name(ssl));
4141 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4142 }
4143 if (err == SSL_ERROR_WANT_READ)
4144 session->sock.flags |= COAP_SOCKET_WANT_READ;
4145 if (err == SSL_ERROR_WANT_WRITE) {
4146 session->sock.flags |= COAP_SOCKET_WANT_WRITE;
4147#ifdef COAP_EPOLL_SUPPORT
4148 coap_epoll_ctl_mod(&session->sock,
4149 EPOLLOUT |
4150 ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
4151 EPOLLIN : 0),
4152 __func__);
4153#endif /* COAP_EPOLL_SUPPORT */
4154 }
4155 r = 0;
4156 } else {
4157 if (err == SSL_ERROR_ZERO_RETURN) /* Got a close notify alert from the remote side */
4159 else if (err == SSL_ERROR_SSL) {
4160 unsigned long e = ERR_get_error();
4161
4162 coap_log_info("***%s: coap_tls_read: cannot recv PDU: %d: %s\n",
4163 coap_session_str(session),
4164 ERR_GET_REASON(e), ERR_reason_error_string(e));
4166 } else {
4167 coap_log_info("***%s: coap_tls_read: cannot read PDU %d\n",
4168 coap_session_str(session), err);
4169 }
4170 r = -1;
4171 }
4172 } else if (in_init && SSL_is_init_finished(ssl)) {
4173 coap_dtls_log(COAP_LOG_INFO, "* %s: Using cipher: %s\n",
4174 coap_session_str(session), SSL_get_cipher_name(ssl));
4176 session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
4177 }
4178
4179 if (session->dtls_event >= 0) {
4180 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
4181 if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
4182 coap_handle_event_lkd(session->context, session->dtls_event, session);
4183 if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
4184 session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
4186 r = -1;
4187 }
4188 }
4189
4190 if (r > 0) {
4191 coap_log_debug("* %s: tls: recv %4d bytes\n",
4192 coap_session_str(session), r);
4193 }
4194 return r;
4195}
4196#endif /* !COAP_DISABLE_TCP */
4197
4198#if COAP_SERVER_SUPPORT
4200coap_digest_setup(void) {
4201 EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
4202
4203 if (digest_ctx) {
4204 EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
4205 }
4206 return digest_ctx;
4207}
4208
4209void
4211 if (digest_ctx)
4212 EVP_MD_CTX_free(digest_ctx);
4213}
4214
4215int
4217 const uint8_t *data,
4218 size_t data_len) {
4219 return EVP_DigestUpdate(digest_ctx, data, data_len);
4220}
4221
4222int
4224 coap_digest_t *digest_buffer) {
4225 unsigned int size = sizeof(coap_digest_t);
4226 int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
4227
4228 coap_digest_free(digest_ctx);
4229 return ret;
4230}
4231#endif /* COAP_SERVER_SUPPORT */
4232
4233#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
4234static void
4235coap_crypto_output_errors(const char *prefix) {
4236#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
4237 (void)prefix;
4238#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4239 unsigned long e;
4240
4241 while ((e = ERR_get_error()))
4242 coap_log_warn("%s: %s%s\n",
4243 prefix,
4244 ERR_reason_error_string(e),
4245 ssl_function_definition(e));
4246#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
4247}
4248#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
4249
4250#if COAP_WS_SUPPORT
4251/*
4252 * The struct hash_algs and the function get_hash_alg() are used to
4253 * determine which hash type to use for creating the required hash object.
4254 */
4255static struct hash_algs {
4256 cose_alg_t alg;
4257 const EVP_MD *(*get_hash)(void);
4258 size_t length; /* in bytes */
4259} hashs[] = {
4260 {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
4261 {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
4262 {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
4263 {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
4264};
4265
4266static const EVP_MD *
4267get_hash_alg(cose_alg_t alg, size_t *length) {
4268 size_t idx;
4269
4270 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
4271 if (hashs[idx].alg == alg) {
4272 *length = hashs[idx].length;
4273 return hashs[idx].get_hash();
4274 }
4275 }
4276 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
4277 return NULL;
4278}
4279
4280int
4282 const coap_bin_const_t *data,
4283 coap_bin_const_t **hash) {
4284 unsigned int length;
4285 const EVP_MD *evp_md;
4286 EVP_MD_CTX *evp_ctx = NULL;
4287 coap_binary_t *dummy = NULL;
4288 size_t hash_length;
4289
4290 if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
4291 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
4292 return 0;
4293 }
4294 evp_ctx = EVP_MD_CTX_new();
4295 if (evp_ctx == NULL)
4296 goto error;
4297 if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
4298 goto error;
4299 ;
4300 if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
4301 goto error;
4302 ;
4303 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4304 if (dummy == NULL)
4305 goto error;
4306 if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
4307 goto error;
4308 dummy->length = length;
4309 if (hash_length < dummy->length)
4310 dummy->length = hash_length;
4311 *hash = (coap_bin_const_t *)(dummy);
4312 EVP_MD_CTX_free(evp_ctx);
4313 return 1;
4314
4315error:
4316 coap_crypto_output_errors("coap_crypto_hash");
4318 if (evp_ctx)
4319 EVP_MD_CTX_free(evp_ctx);
4320 return 0;
4321}
4322#endif /* COAP_WS_SUPPORT */
4323
4324#if COAP_OSCORE_SUPPORT
4325int
4327 return 1;
4328}
4329
4330#include <openssl/evp.h>
4331#include <openssl/hmac.h>
4332
4333/*
4334 * The struct cipher_algs and the function get_cipher_alg() are used to
4335 * determine which cipher type to use for creating the required cipher
4336 * suite object.
4337 */
4338static struct cipher_algs {
4339 cose_alg_t alg;
4340 const EVP_CIPHER *(*get_cipher)(void);
4341} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
4342 {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
4343};
4344
4345static const EVP_CIPHER *
4346get_cipher_alg(cose_alg_t alg) {
4347 size_t idx;
4348
4349 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
4350 if (ciphers[idx].alg == alg)
4351 return ciphers[idx].get_cipher();
4352 }
4353 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
4354 return NULL;
4355}
4356
4357/*
4358 * The struct hmac_algs and the function get_hmac_alg() are used to
4359 * determine which hmac type to use for creating the required hmac
4360 * suite object.
4361 */
4362static struct hmac_algs {
4363 cose_hmac_alg_t hmac_alg;
4364 const EVP_MD *(*get_hmac)(void);
4365} hmacs[] = {
4366 {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
4367 {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
4368 {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
4369};
4370
4371static const EVP_MD *
4372get_hmac_alg(cose_hmac_alg_t hmac_alg) {
4373 size_t idx;
4374
4375 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
4376 if (hmacs[idx].hmac_alg == hmac_alg)
4377 return hmacs[idx].get_hmac();
4378 }
4379 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
4380 return NULL;
4381}
4382
4383int
4385 return get_cipher_alg(alg) != NULL;
4386}
4387
4388int
4390 cose_hmac_alg_t hmac_alg;
4391
4392 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
4393 return 0;
4394 return get_hmac_alg(hmac_alg) != NULL;
4395}
4396
4397#define C(Func) \
4398 if (1 != (Func)) { \
4399 goto error; \
4400 }
4401
4402int
4404 coap_bin_const_t *data,
4405 coap_bin_const_t *aad,
4406 uint8_t *result,
4407 size_t *max_result_len) {
4408 const EVP_CIPHER *cipher;
4409 const coap_crypto_aes_ccm_t *ccm;
4410 int tmp;
4411 int result_len = (int)(*max_result_len & INT_MAX);
4412
4413 if (data == NULL)
4414 return 0;
4415
4416 assert(params != NULL);
4417 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4418 return 0;
4419 }
4420
4421 /* TODO: set evp_md depending on params->alg */
4422 ccm = &params->params.aes;
4423
4424 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
4425
4426 /* EVP_CIPHER_CTX_init(ctx); */
4427 C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4428 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4429 C(EVP_CIPHER_CTX_ctrl(ctx,
4430 EVP_CTRL_AEAD_SET_IVLEN,
4431 (int)(15 - ccm->l),
4432 NULL));
4433 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
4434 C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4435 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4436
4437 C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
4438 if (aad && aad->s && (aad->length > 0)) {
4439 C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
4440 }
4441 C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
4442 /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
4443 tmp = result_len;
4444 C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
4445 result_len += tmp;
4446
4447 /* retrieve the tag */
4448 C(EVP_CIPHER_CTX_ctrl(ctx,
4449 EVP_CTRL_CCM_GET_TAG,
4450 (int)ccm->tag_len,
4451 result + result_len));
4452
4453 *max_result_len = result_len + ccm->tag_len;
4454 EVP_CIPHER_CTX_free(ctx);
4455 return 1;
4456
4457error:
4458 coap_crypto_output_errors("coap_crypto_aead_encrypt");
4459 return 0;
4460}
4461
4462int
4464 coap_bin_const_t *data,
4465 coap_bin_const_t *aad,
4466 uint8_t *result,
4467 size_t *max_result_len) {
4468 const EVP_CIPHER *cipher;
4469 const coap_crypto_aes_ccm_t *ccm;
4470 int tmp;
4471 int len;
4472 const uint8_t *tag;
4473 uint8_t *rwtag;
4474
4475 if (data == NULL)
4476 return 0;
4477
4478 assert(params != NULL);
4479 if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
4480 return 0;
4481 }
4482
4483 ccm = &params->params.aes;
4484
4485 if (data->length < ccm->tag_len) {
4486 return 0;
4487 } else {
4488 tag = data->s + data->length - ccm->tag_len;
4489 data->length -= ccm->tag_len;
4490 /* Kludge to stop compiler warning */
4491 memcpy(&rwtag, &tag, sizeof(rwtag));
4492 }
4493
4494 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
4495
4496 C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
4497 C(EVP_CIPHER_CTX_ctrl(ctx,
4498 EVP_CTRL_AEAD_SET_IVLEN,
4499 (int)(15 - ccm->l),
4500 NULL));
4501 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
4502 C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
4503 /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
4504 C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
4505
4506 C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
4507 if (aad && aad->s && (aad->length > 0)) {
4508 C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
4509 }
4510 tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
4511 EVP_CIPHER_CTX_free(ctx);
4512 if (tmp <= 0) {
4513 *max_result_len = 0;
4514 return 0;
4515 }
4516 *max_result_len = len;
4517 return 1;
4518
4519error:
4520 coap_crypto_output_errors("coap_crypto_aead_decrypt");
4521 return 0;
4522}
4523
4524int
4526 coap_bin_const_t *key,
4527 coap_bin_const_t *data,
4528 coap_bin_const_t **hmac) {
4529 unsigned int result_len;
4530 const EVP_MD *evp_md;
4531 coap_binary_t *dummy = NULL;
4532
4533 assert(key);
4534 assert(data);
4535 assert(hmac);
4536
4537 if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
4538 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
4539 return 0;
4540 }
4541 dummy = coap_new_binary(EVP_MAX_MD_SIZE);
4542 if (dummy == NULL)
4543 return 0;
4544 result_len = (unsigned int)dummy->length;
4545 if (HMAC(evp_md,
4546 key->s,
4547 (int)key->length,
4548 data->s,
4549 (int)data->length,
4550 dummy->s,
4551 &result_len)) {
4552 dummy->length = result_len;
4553 *hmac = (coap_bin_const_t *)dummy;
4554 return 1;
4555 }
4556
4557 coap_crypto_output_errors("coap_crypto_hmac");
4558 return 0;
4559}
4560
4561#endif /* COAP_OSCORE_SUPPORT */
4562
4563#else /* !COAP_WITH_LIBOPENSSL */
4564
4565#ifdef __clang__
4566/* Make compilers happy that do not like empty modules. As this function is
4567 * never used, we ignore -Wunused-function at the end of compiling this file
4568 */
4569#pragma GCC diagnostic ignored "-Wunused-function"
4570#endif
4571static inline void
4572dummy(void) {
4573}
4574
4575#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:229
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:301
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:224
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:243
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:158
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:261
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:124
static coap_log_t dtls_log_level
Definition coap_notls.c:151
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:147
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:212
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:289
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:208
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:238
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:186
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:204
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:181
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:280
static void dummy(void)
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_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:4783
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:2793
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:154
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:219
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:166
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:176
#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:171
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:108
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log_err(...)
Definition coap_debug.h:96
#define coap_log(level,...)
Logging function.
Definition coap_debug.h:284
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_WARN
Definition coap_debug.h:55
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_64
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_SHA_1
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_SHA_512
@ COSE_ALGORITHM_AES_CCM_16_64_256
#define COAP_DEFAULT_MTU
Definition coap_pdu.h:41
@ COAP_PROTO_DTLS
Definition coap_pdu.h:315
@ COAP_PROTO_TLS
Definition coap_pdu.h:317
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
int coap_session_refresh_psk_identity(coap_session_t *session, const coap_bin_const_t *psk_identity)
Refresh the session's current pre-shared identity (PSK).
void coap_session_disconnected_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_CSM
void coap_delete_str_const(coap_str_const_t *s)
Deletes the given const string and releases any memory allocated.
Definition coap_str.c:61
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:77
void coap_delete_binary(coap_binary_t *s)
Deletes the given coap_binary_t object and releases any memory allocated.
Definition coap_str.c:105
coap_str_const_t * coap_new_str_const(const uint8_t *data, size_t size)
Returns a new const string object with at least size+1 bytes storage allocated, and the provided data...
Definition coap_str.c:51
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
Definition coap_notls.c:86
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
#define COAP_UNUSED
Definition libcoap.h: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 is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:330
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