libcoap 4.3.2rc2

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