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