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