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