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