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