libcoap 4.3.0
coap_mbedtls.c
Go to the documentation of this file.
1/*
2* coap_mbedtls.c -- Mbed TLS Datagram Transport Layer Support for libcoap
3*
4* Copyright (C) 2019-2021 Jon Shallow <supjps-libcoap@jpshallow.com>
5* 2019 Jitin George <jitin@espressif.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
13/*
14 * Naming used to prevent confusion between coap sessions, mbedtls sessions etc.
15 * when reading the code.
16 *
17 * c_context A coap_context_t *
18 * c_session A coap_session_t *
19 * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context)
20 * m_env A coap_mbedtls_env_t * (held in c_session->tls)
21 */
22
23#include "coap3/coap_internal.h"
24
25#ifdef HAVE_MBEDTLS
26
27/*
28 * This code can be conditionally compiled to remove some components if
29 * they are not required to make a lighter footprint - all based on how
30 * the mbedtls library has been built. These are not defined within the
31 * libcoap environment.
32 *
33 * MBEDTLS_SSL_SRV_C - defined for server side functionality
34 * MBEDTLS_SSL_CLI_C - defined for client side functionality
35 * MBEDTLS_SSL_PROTO_DTLS - defined for DTLS support
36 * MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED - defined if PSK is to be supported
37 * or MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED - defined if PSK is to be supported
38 *
39 * Note: TLS is not currently supported until additional code is added
40 */
41
42#include <mbedtls/version.h>
43#include <mbedtls/platform.h>
44#include <mbedtls/net_sockets.h>
45#include <mbedtls/ssl.h>
46#include <mbedtls/entropy.h>
47#include <mbedtls/ctr_drbg.h>
48#include <mbedtls/error.h>
49#include <mbedtls/certs.h>
50#include <mbedtls/timing.h>
51#include <mbedtls/ssl_cookie.h>
52#include <mbedtls/oid.h>
53#include <mbedtls/debug.h>
54#include <mbedtls/sha256.h>
55#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
56#include <mbedtls/esp_debug.h>
57#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
58#include <errno.h>
59
60#define mbedtls_malloc(a) malloc(a)
61#define mbedtls_realloc(a,b) realloc(a,b)
62#define mbedtls_strdup(a) strdup(a)
63#define mbedtls_strndup(a,b) strndup(a,b)
64
65#ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
66/* definition changed in later mbedtls code versions */
67#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
68#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
69#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
70#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
71
72#ifdef _WIN32
73#define strcasecmp _stricmp
74#endif
75
76#define IS_PSK (1 << 0)
77#define IS_PKI (1 << 1)
78#define IS_CLIENT (1 << 6)
79#define IS_SERVER (1 << 7)
80
81typedef struct coap_ssl_t {
82 const uint8_t *pdu;
83 unsigned pdu_len;
84 unsigned peekmode;
85} coap_ssl_t;
86
87/*
88 * This structure encapsulates the Mbed TLS session object.
89 * It handles both TLS and DTLS.
90 * c_session->tls points to this.
91 */
92typedef struct coap_mbedtls_env_t {
93 mbedtls_ssl_context ssl;
94 mbedtls_entropy_context entropy;
95 mbedtls_ctr_drbg_context ctr_drbg;
96 mbedtls_ssl_config conf;
97 mbedtls_timing_delay_context timer;
98 mbedtls_x509_crt cacert;
99 mbedtls_x509_crt public_cert;
100 mbedtls_pk_context private_key;
101 mbedtls_ssl_cookie_ctx cookie_ctx;
102 /* If not set, need to do do_mbedtls_handshake */
103 int established;
104 int seen_client_hello;
105 coap_tick_t last_timeout;
106 unsigned int retry_scalar;
107 coap_ssl_t coap_ssl_data;
108} coap_mbedtls_env_t;
109
110typedef struct pki_sni_entry {
111 char *sni;
112 coap_dtls_key_t pki_key;
113 mbedtls_x509_crt cacert;
114 mbedtls_x509_crt public_cert;
115 mbedtls_pk_context private_key;
116} pki_sni_entry;
117
118typedef struct psk_sni_entry {
119 char* sni;
120 coap_dtls_spsk_info_t psk_info;
121} psk_sni_entry;
122
123typedef struct coap_mbedtls_context_t {
124 coap_dtls_pki_t setup_data;
125 size_t pki_sni_count;
126 pki_sni_entry *pki_sni_entry_list;
127 size_t psk_sni_count;
128 psk_sni_entry *psk_sni_entry_list;
129 char *root_ca_file;
130 char *root_ca_path;
131 int psk_pki_enabled;
132} coap_mbedtls_context_t;
133
134typedef enum coap_enc_method_t {
135 COAP_ENC_PSK,
136 COAP_ENC_PKI,
137} coap_enc_method_t;
138
139static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl)
140{
141 ssize_t ret = 0;
142 coap_session_t *c_session = (coap_session_t *)ctx;
143 coap_ssl_t *data;
144
145 if (!c_session->tls) {
146 errno = EAGAIN;
147 return MBEDTLS_ERR_SSL_WANT_READ;
148 }
149 data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data;
150
151 if (out != NULL) {
152 if (data->pdu_len > 0) {
153 if (outl < data->pdu_len) {
154 memcpy(out, data->pdu, outl);
155 ret = outl;
156 data->pdu += outl;
157 data->pdu_len -= outl;
158 }
159 else {
160 memcpy(out, data->pdu, data->pdu_len);
161 ret = data->pdu_len;
162 if (!data->peekmode) {
163 data->pdu_len = 0;
164 data->pdu = NULL;
165 }
166 }
167 }
168 else {
169 ret = MBEDTLS_ERR_SSL_WANT_READ;
170 errno = EAGAIN;
171 }
172 }
173 return ret;
174}
175
176/*
177 * return +ve data amount
178 * 0 no more
179 * -1 error (error in errno)
180 */
181/* callback function given to mbedtls for sending data over socket */
182static int
183coap_dgram_write(void *ctx, const unsigned char *send_buffer,
184 size_t send_buffer_length)
185{
186 ssize_t result = -1;
187 coap_session_t *c_session = (coap_session_t *)ctx;
188
189 if (c_session) {
190 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
191 result = coap_session_send(c_session, send_buffer, send_buffer_length);
192 if (result != (ssize_t)send_buffer_length) {
193 coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zu)\n",
194 result, send_buffer_length);
195 result = 0;
196 }
197 else if (m_env) {
198 coap_tick_t now;
199 coap_ticks(&now);
200 m_env->last_timeout = now;
201 }
202 } else {
203 result = 0;
204 }
205 return result;
206}
207
208#if defined(MBEDTLS_SSL_PROTO_DTLS) && defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && defined(MBEDTLS_SSL_SRV_C)
209/*
210 * Server side PSK callback
211 */
212static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl,
213 const unsigned char *name, size_t name_len )
214{
215 coap_session_t *c_session = (coap_session_t *)p_info;
216 uint8_t buf[128];
217 size_t psk_len;
218 coap_dtls_spsk_t *setup_data;
219 coap_mbedtls_env_t *m_env;
220
221 coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
222 (int)name_len, name);
223
224 if (c_session == NULL || c_session->context == NULL ||
225 c_session->context->get_server_psk == NULL) {
226 return -1;
227 }
228 m_env = (coap_mbedtls_env_t *)c_session->tls;
229 setup_data = &c_session->context->spsk_setup_data;
230
231 if (setup_data->validate_id_call_back) {
232 coap_bin_const_t lidentity;
233 lidentity.length = name_len;
234 lidentity.s = (const uint8_t*)name;
235 const coap_bin_const_t *psk_key =
236 setup_data->validate_id_call_back(&lidentity,
237 c_session,
238 setup_data->id_call_back_arg);
239
240 if (psk_key == NULL)
241 return -1;
242 mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length);
243 coap_session_refresh_psk_key(c_session, psk_key);
244 m_env->seen_client_hello = 1;
245 return 0;
246 }
247
248 psk_len = c_session->context->get_server_psk(c_session,
249 (const uint8_t*)name,
250 name_len,
251 (uint8_t*)buf, sizeof(buf));
252 m_env->seen_client_hello = 1;
253 mbedtls_ssl_set_hs_psk(ssl, buf, psk_len);
254 return 0;
255}
256#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && MBEDTLS_SSL_SRV_C */
257
258static char*
259get_san_or_cn_from_cert(mbedtls_x509_crt *crt)
260{
261 if (crt) {
262 mbedtls_asn1_named_data * cn_data;
263
264 if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
265 mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
266 while (seq && seq->buf.p == NULL) {
267 seq = seq->next;
268 }
269 if (seq) {
270 /* Return the Subject Alt Name */
271 return mbedtls_strndup((const char *)seq->buf.p,
272 seq->buf.len);
273 }
274 }
275
276 cn_data = mbedtls_asn1_find_named_data(&crt->subject,
277 MBEDTLS_OID_AT_CN,
278 MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN));
279 if (cn_data) {
280 /* Return the Common Name */
281 return mbedtls_strndup((const char *)cn_data->val.p,
282 cn_data->val.len);
283 }
284 }
285 return NULL;
286}
287
288static char *
289get_error_string(int ret) {
290 static char buf[128] = {0};
291 mbedtls_strerror(ret, buf, sizeof(buf)-1);
292 return buf;
293}
294
295/*
296 * return 0 All OK
297 * -ve Error Code
298 */
299static int
300cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt,
301 int depth, uint32_t *flags)
302{
303 coap_session_t *c_session = (coap_session_t*)data;
304 coap_mbedtls_context_t *m_context =
305 (coap_mbedtls_context_t *)c_session->context->dtls_context;
306 coap_dtls_pki_t *setup_data = &m_context->setup_data;
307 char *cn = NULL;
308
309 if (*flags == 0)
310 return 0;
311
312 cn = get_san_or_cn_from_cert(crt);
313
314 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
315 if (setup_data->allow_expired_certs) {
316 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
318 " %s: %s: overridden: '%s' depth %d\n",
319 coap_session_str(c_session),
320 "The certificate has expired", cn ? cn : "?", depth);
321 }
322 }
323 if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
324 if (setup_data->allow_expired_certs) {
325 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
327 " %s: %s: overridden: '%s' depth %d\n",
328 coap_session_str(c_session),
329 "The certificate has a future date", cn ? cn : "?", depth);
330 }
331 }
332 if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
333 if (setup_data->allow_bad_md_hash) {
334 *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD;
336 " %s: %s: overridden: '%s' depth %d\n",
337 coap_session_str(c_session),
338 "The certificate has a bad MD hash", cn ? cn : "?", depth);
339 }
340 }
341 if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) {
342 if (setup_data->allow_short_rsa_length) {
343 *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY;
345 " %s: %s: overridden: '%s' depth %d\n",
346 coap_session_str(c_session),
347 "The certificate has a short RSA length", cn ? cn : "?", depth);
348 }
349 }
350 if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
351 uint32_t lflags;
352 int self_signed = !mbedtls_x509_crt_verify(crt, crt, NULL, NULL, &lflags,
353 NULL, NULL);
354 if (self_signed && depth == 0) {
355 if (setup_data->allow_self_signed &&
356 !setup_data->check_common_ca) {
357 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
359 " %s: %s: overridden: '%s' depth %d\n",
360 coap_session_str(c_session),
361 "Self-signed",
362 cn ? cn : "?", depth);
363 }
364 }
365 else {
366 if (!setup_data->verify_peer_cert) {
367 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
369 " %s: %s: overridden: '%s' depth %d\n",
370 coap_session_str(c_session),
371 "The certificate's CA does not match", cn ? cn : "?", depth);
372 }
373 }
374 }
375 if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) {
376 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
377 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
379 " %s: %s: overridden: '%s' depth %d\n",
380 coap_session_str(c_session),
381 "The certificate's CRL has expired", cn ? cn : "?", depth);
382 }
383 else if (!setup_data->check_cert_revocation) {
384 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
385 }
386 }
387 if (*flags & MBEDTLS_X509_BADCRL_FUTURE) {
388 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
389 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
391 " %s: %s: overridden: '%s' depth %d\n",
392 coap_session_str(c_session),
393 "The certificate's CRL has a future date", cn ? cn : "?", depth);
394 }
395 else if (!setup_data->check_cert_revocation) {
396 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
397 }
398 }
399 if (setup_data->cert_chain_validation &&
400 depth > (setup_data->cert_chain_verify_depth + 1)) {
401 *flags |= MBEDTLS_X509_BADCERT_OTHER;
403 " %s: %s: '%s' depth %d\n",
404 coap_session_str(c_session),
405 "The certificate's verify depth is too long",
406 cn ? cn : "?", depth);
407 }
408
409 if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
410 *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
411 }
412 if (setup_data->validate_cn_call_back) {
413 if (!setup_data->validate_cn_call_back(cn,
414 crt->raw.p,
415 crt->raw.len,
416 c_session,
417 depth,
418 *flags == 0,
419 setup_data->cn_call_back_arg)) {
420 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
421 }
422 }
423 if (*flags != 0) {
424 char buf[128];
425 char *tcp;
426 int ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
427
428 if (ret >= 0) {
429 tcp = strchr(buf, '\n');
430 while (tcp) {
431 *tcp = '\000';
433 " %s: %s: issue 0x%x: '%s' depth %d\n",
434 coap_session_str(c_session),
435 buf, *flags, cn ? cn : "?", depth);
436 tcp = strchr(tcp+1, '\n');
437 }
438 }
439 else {
440 coap_log(LOG_ERR, "mbedtls_x509_crt_verify_info returned -0x%x: '%s'\n",
441 -ret, get_error_string(ret));
442 }
443 }
444
445 if (cn)
446 mbedtls_free(cn);
447
448 return 0;
449}
450
451static int
452setup_pki_credentials(mbedtls_x509_crt *cacert,
453 mbedtls_x509_crt *public_cert,
454 mbedtls_pk_context *private_key,
455 coap_mbedtls_env_t *m_env,
456 coap_mbedtls_context_t *m_context,
457 coap_session_t *c_session,
458 coap_dtls_pki_t *setup_data,
459 coap_dtls_role_t role)
460{
461 int ret;
462
463 if (setup_data->is_rpk_not_cert) {
465 "RPK Support not available in Mbed TLS\n");
466 return -1;
467 }
468 switch (setup_data->pki_key.key_type) {
469 case COAP_PKI_KEY_PEM:
470 if (setup_data->pki_key.key.pem.public_cert &&
471 setup_data->pki_key.key.pem.public_cert[0] &&
472 setup_data->pki_key.key.pem.private_key &&
473 setup_data->pki_key.key.pem.private_key[0]) {
474
475 mbedtls_x509_crt_init(public_cert);
476 mbedtls_pk_init(private_key);
477
478 ret = mbedtls_x509_crt_parse_file(public_cert,
479 setup_data->pki_key.key.pem.public_cert);
480 if (ret < 0) {
481 coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x: '%s'\n",
482 -ret, get_error_string(ret));
483 return ret;
484 }
485
486 ret = mbedtls_pk_parse_keyfile(private_key,
487 setup_data->pki_key.key.pem.private_key, NULL);
488 if (ret < 0) {
489 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
490 -ret, get_error_string(ret));
491 return ret;
492 }
493
494 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
495 if (ret < 0) {
496 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
497 -ret, get_error_string(ret));
498 return ret;
499 }
500 }
501 else if (role == COAP_DTLS_ROLE_SERVER) {
503 "***setup_pki: (D)TLS: No Server Certificate + Private "
504 "Key defined\n");
505 return -1;
506 }
507
508 if (setup_data->pki_key.key.pem.ca_file &&
509 setup_data->pki_key.key.pem.ca_file[0]) {
510 mbedtls_x509_crt_init(cacert);
511 ret = mbedtls_x509_crt_parse_file(cacert,
512 setup_data->pki_key.key.pem.ca_file);
513 if (ret < 0) {
514 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
515 -ret, get_error_string(ret));
516 return ret;
517 }
518 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
519 }
520 break;
522 if (setup_data->pki_key.key.pem_buf.public_cert &&
523 setup_data->pki_key.key.pem_buf.public_cert_len &&
524 setup_data->pki_key.key.pem_buf.private_key &&
525 setup_data->pki_key.key.pem_buf.private_key_len) {
526 uint8_t *buffer;
527 size_t length;
528
529 mbedtls_x509_crt_init(public_cert);
530 mbedtls_pk_init(private_key);
531
532 length = setup_data->pki_key.key.pem_buf.public_cert_len;
533 if (setup_data->pki_key.key.pem_buf.public_cert[length-1] != '\000') {
534 /* Need to allocate memory to add in NULL terminator */
535 buffer = mbedtls_malloc(length + 1);
536 if (!buffer) {
537 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
538 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
539 }
540 memcpy(buffer, setup_data->pki_key.key.pem_buf.public_cert, length);
541 buffer[length] = '\000';
542 length++;
543 ret = mbedtls_x509_crt_parse(public_cert, buffer, length);
544 mbedtls_free(buffer);
545 }
546 else {
547 ret = mbedtls_x509_crt_parse(public_cert,
548 setup_data->pki_key.key.pem_buf.public_cert,
549 setup_data->pki_key.key.pem_buf.public_cert_len);
550 }
551 if (ret < 0) {
552 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
553 -ret, get_error_string(ret));
554 return ret;
555 }
556
557 length = setup_data->pki_key.key.pem_buf.private_key_len;
558 if (setup_data->pki_key.key.pem_buf.private_key[length-1] != '\000') {
559 /* Need to allocate memory to add in NULL terminator */
560 buffer = mbedtls_malloc(length + 1);
561 if (!buffer) {
562 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
563 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
564 }
565 memcpy(buffer, setup_data->pki_key.key.pem_buf.private_key, length);
566 buffer[length] = '\000';
567 length++;
568 ret = mbedtls_pk_parse_key(private_key, buffer, length, NULL, 0);
569 mbedtls_free(buffer);
570 }
571 else {
572 ret = mbedtls_pk_parse_key(private_key,
573 setup_data->pki_key.key.pem_buf.private_key,
574 setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0);
575 }
576 if (ret < 0) {
577 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
578 -ret, get_error_string(ret));
579 return ret;
580 }
581
582 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
583 if (ret < 0) {
584 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
585 -ret, get_error_string(ret));
586 return ret;
587 }
588 } else if (role == COAP_DTLS_ROLE_SERVER) {
590 "***setup_pki: (D)TLS: No Server Certificate + Private "
591 "Key defined\n");
592 return -1;
593 }
594
595 if (setup_data->pki_key.key.pem_buf.ca_cert &&
596 setup_data->pki_key.key.pem_buf.ca_cert_len) {
597 uint8_t *buffer;
598 size_t length;
599
600 mbedtls_x509_crt_init(cacert);
601 length = setup_data->pki_key.key.pem_buf.ca_cert_len;
602 if (setup_data->pki_key.key.pem_buf.ca_cert[length-1] != '\000') {
603 /* Need to allocate memory to add in NULL terminator */
604 buffer = mbedtls_malloc(length + 1);
605 if (!buffer) {
606 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
607 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
608 }
609 memcpy(buffer, setup_data->pki_key.key.pem_buf.ca_cert, length);
610 buffer[length] = '\000';
611 length++;
612 ret = mbedtls_x509_crt_parse(cacert, buffer, length);
613 mbedtls_free(buffer);
614 }
615 else {
616 ret = mbedtls_x509_crt_parse(cacert,
617 setup_data->pki_key.key.pem_buf.ca_cert,
618 setup_data->pki_key.key.pem_buf.ca_cert_len);
619 }
620 if (ret < 0) {
621 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
622 -ret, get_error_string(ret));
623 return ret;
624 }
625 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
626 }
627 break;
629 if (setup_data->pki_key.key.asn1.public_cert &&
630 setup_data->pki_key.key.asn1.public_cert_len &&
631 setup_data->pki_key.key.asn1.private_key &&
632 setup_data->pki_key.key.asn1.private_key_len > 0) {
633
634 mbedtls_x509_crt_init(public_cert);
635 mbedtls_pk_init(private_key);
636 ret = mbedtls_x509_crt_parse(public_cert,
637 (const unsigned char *)setup_data->pki_key.key.asn1.public_cert,
638 setup_data->pki_key.key.asn1.public_cert_len);
639 if (ret < 0) {
640 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
641 -ret, get_error_string(ret));
642 return ret;
643 }
644
645 ret = mbedtls_pk_parse_key(private_key,
646 (const unsigned char *)setup_data->pki_key.key.asn1.private_key,
647 setup_data->pki_key.key.asn1.private_key_len, NULL, 0);
648 if (ret < 0) {
649 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
650 -ret, get_error_string(ret));
651 return ret;
652 }
653
654 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
655 if (ret < 0) {
656 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
657 -ret, get_error_string(ret));
658 return ret;
659 }
660 } else if (role == COAP_DTLS_ROLE_SERVER) {
662 "***setup_pki: (D)TLS: No Server Certificate + Private "
663 "Key defined\n");
664 return -1;
665 }
666
667 if (setup_data->pki_key.key.asn1.ca_cert &&
668 setup_data->pki_key.key.asn1.ca_cert_len > 0) {
669 mbedtls_x509_crt_init(cacert);
670 ret = mbedtls_x509_crt_parse(cacert,
671 (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert,
672 setup_data->pki_key.key.asn1.ca_cert_len);
673 if (ret < 0) {
674 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
675 -ret, get_error_string(ret));
676 return ret;
677 }
678 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
679 }
680 break;
681
684 "***setup_pki: (D)TLS: PKCS11 not currently supported\n");
685 return -1;
686
687 default:
689 "***setup_pki: (D)TLS: Unknown key type %d\n",
690 setup_data->pki_key.key_type);
691 return -1;
692 }
693
694 if (m_context->root_ca_file) {
695 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file);
696 if (ret < 0) {
697 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
698 -ret, get_error_string(ret));
699 return ret;
700 }
701 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
702 }
703 if (m_context->root_ca_path) {
704 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path);
705 if (ret < 0) {
706 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
707 -ret, get_error_string(ret));
708 return ret;
709 }
710 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
711 }
712
713 mbedtls_ssl_conf_cert_req_ca_list(&m_env->conf,
714 setup_data->check_common_ca ?
715 MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED :
716 MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED);
717 mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->verify_peer_cert ?
718 MBEDTLS_SSL_VERIFY_REQUIRED :
719 MBEDTLS_SSL_VERIFY_NONE);
720 /*
721 * Verify Peer.
722 * Need to do all checking, even if setup_data->verify_peer_cert is not set
723 */
724 mbedtls_ssl_conf_verify(&m_env->conf,
725 cert_verify_callback_mbedtls, c_session);
726
727 return 0;
728}
729
730#if defined(MBEDTLS_SSL_SRV_C)
731/*
732 * PKI SNI callback.
733 */
734static int
735pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
736 const unsigned char *uname, size_t name_len)
737{
738 unsigned int i;
739 coap_dtls_pki_t sni_setup_data;
740 coap_session_t *c_session = (coap_session_t *)p_info;
741 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
742 coap_mbedtls_context_t *m_context =
743 (coap_mbedtls_context_t *)c_session->context->dtls_context;
744 int ret = 0;
745 char *name;
746
747 name = mbedtls_malloc(name_len+1);
748 if (!name)
749 return -1;
750
751 memcpy(name, uname, name_len);
752 name[name_len] = '\000';
753
754 /* Is this a cached entry? */
755 for (i = 0; i < m_context->pki_sni_count; i++) {
756 if (strcasecmp(name, m_context->pki_sni_entry_list[i].sni) == 0) {
757 break;
758 }
759 }
760 if (i == m_context->pki_sni_count) {
761 /*
762 * New PKI SNI request
763 */
764 coap_dtls_key_t *new_entry;
765 pki_sni_entry *pki_sni_entry_list;
766
767 new_entry =
768 m_context->setup_data.validate_sni_call_back(name,
769 m_context->setup_data.sni_call_back_arg);
770 if (!new_entry) {
771 mbedtls_free(name);
772 return -1;
773 }
774
775 pki_sni_entry_list = mbedtls_realloc(m_context->pki_sni_entry_list,
776 (i+1)*sizeof(pki_sni_entry));
777
778 if (pki_sni_entry_list == NULL) {
779 mbedtls_free(name);
780 return -1;
781 }
782 m_context->pki_sni_entry_list = pki_sni_entry_list;
783 memset(&m_context->pki_sni_entry_list[i], 0,
784 sizeof(m_context->pki_sni_entry_list[i]));
785 m_context->pki_sni_entry_list[i].sni = name;
786 m_context->pki_sni_entry_list[i].pki_key = *new_entry;
787 sni_setup_data = m_context->setup_data;
788 sni_setup_data.pki_key = *new_entry;
789 if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert,
790 &m_context->pki_sni_entry_list[i].public_cert,
791 &m_context->pki_sni_entry_list[i].private_key,
792 m_env,
793 m_context,
794 c_session,
795 &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) {
796 mbedtls_free(name);
797 return -1;
798 }
799 /* name has been absorbed into pki_sni_entry_list[].sni entry */
800 m_context->pki_sni_count++;
801 }
802 else {
803 mbedtls_free(name);
804 }
805
806 mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert,
807 NULL);
808 return mbedtls_ssl_set_hs_own_cert(ssl,
809 &m_context->pki_sni_entry_list[i].public_cert,
810 &m_context->pki_sni_entry_list[i].private_key);
811}
812
813#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
814/*
815 * PSK SNI callback.
816 */
817static int
818psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
819 const unsigned char *uname, size_t name_len)
820{
821 unsigned int i;
822 coap_session_t *c_session = (coap_session_t *)p_info;
823 coap_mbedtls_context_t *m_context =
824 (coap_mbedtls_context_t *)c_session->context->dtls_context;
825 char *name;
826
827 name = mbedtls_malloc(name_len+1);
828 if (!name)
829 return -1;
830
831 memcpy(name, uname, name_len);
832 name[name_len] = '\000';
833
834 /* Is this a cached entry? */
835 for (i = 0; i < m_context->psk_sni_count; i++) {
836 if (strcasecmp(name, m_context->psk_sni_entry_list[i].sni) == 0) {
837 break;
838 }
839 }
840 if (i == m_context->psk_sni_count) {
841 /*
842 * New PSK SNI request
843 */
844 const coap_dtls_spsk_info_t *new_entry;
845 psk_sni_entry *psk_sni_entry_list;
846
847 new_entry =
849 c_session,
851 if (!new_entry) {
852 mbedtls_free(name);
853 return -1;
854 }
855
856 psk_sni_entry_list = mbedtls_realloc(m_context->psk_sni_entry_list,
857 (i+1)*sizeof(psk_sni_entry));
858
859 if (psk_sni_entry_list == NULL) {
860 mbedtls_free(name);
861 return -1;
862 }
863 m_context->psk_sni_entry_list = psk_sni_entry_list;
864 m_context->psk_sni_entry_list[i].sni = name;
865 m_context->psk_sni_entry_list[i].psk_info = *new_entry;
866 /* name has been absorbed into psk_sni_entry_list[].sni entry */
867 m_context->psk_sni_count++;
868 }
869 else {
870 mbedtls_free(name);
871 }
872
874 &m_context->psk_sni_entry_list[i].psk_info.hint);
876 &m_context->psk_sni_entry_list[i].psk_info.key);
877 return mbedtls_ssl_set_hs_psk(ssl,
878 m_context->psk_sni_entry_list[i].psk_info.key.s,
879 m_context->psk_sni_entry_list[i].psk_info.key.length);
880}
881#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
882
883static int setup_server_ssl_session(coap_session_t *c_session,
884 coap_mbedtls_env_t *m_env)
885{
886 coap_mbedtls_context_t *m_context =
887 (coap_mbedtls_context_t *)c_session->context->dtls_context;
888 int ret = 0;
889 m_context->psk_pki_enabled |= IS_SERVER;
890
891 mbedtls_ssl_cookie_init(&m_env->cookie_ctx);
892 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
893 MBEDTLS_SSL_IS_SERVER,
894 c_session->proto == COAP_PROTO_DTLS ?
895 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
896 MBEDTLS_SSL_TRANSPORT_STREAM,
897 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
898 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
899 -ret, get_error_string(ret));
900 goto fail;
901 }
902
903 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
904
905#if defined(MBEDTLS_SSL_PROTO_DTLS)
906 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
908
909 if (m_context->psk_pki_enabled & IS_PSK) {
910#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
911 mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session);
913 mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session);
914 }
915#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
916 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
917#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
918 }
919#endif /* MBEDTLS_SSL_PROTO_DTLS */
920
921 if (m_context->psk_pki_enabled & IS_PKI) {
922 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
923 &m_env->private_key, m_env, m_context,
924 c_session, &m_context->setup_data,
926 if (ret < 0) {
927 coap_log(LOG_ERR, "PKI setup failed\n");
928 return ret;
929 }
930 if (m_context->setup_data.validate_sni_call_back) {
931 mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session);
932 }
933 }
934
935 if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx,
936 mbedtls_ctr_drbg_random,
937 &m_env->ctr_drbg)) != 0) {
938 coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x: '%s'\n",
939 -ret, get_error_string(ret));
940 goto fail;
941 }
942
943#if defined(MBEDTLS_SSL_PROTO_DTLS)
944 mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write,
945 mbedtls_ssl_cookie_check,
946 &m_env->cookie_ctx );
947#if MBEDTLS_VERSION_NUMBER >= 0x02100100
948 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
949#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
950#endif /* MBEDTLS_SSL_PROTO_DTLS */
951fail:
952 return ret;
953}
954#endif /* MBEDTLS_SSL_SRV_C */
955
956static int *psk_ciphers = NULL;
957static int *pki_ciphers = NULL;
958static int processed_ciphers = 0;
959
960static void
961set_ciphersuites(mbedtls_ssl_config *conf, coap_enc_method_t method)
962{
963 if (!processed_ciphers) {
964 const int *list = mbedtls_ssl_list_ciphersuites();
965 const int *base = list;
966 int *psk_list;
967 int *pki_list;
968 int psk_count = 1; /* account for empty terminator */
969 int pki_count = 1;
970
971 while (*list) {
972 const mbedtls_ssl_ciphersuite_t *cur =
973 mbedtls_ssl_ciphersuite_from_id(*list);
974
975 if (cur) {
976 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
977 /* Minimum of TLS1.2 required - skip */
978 }
979 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
980 psk_count++;
981 }
982 else {
983 pki_count++;
984 }
985 }
986 list++;
987 }
988 list = base;
989
990 psk_ciphers = mbedtls_malloc(psk_count * sizeof(psk_ciphers[0]));
991 if (psk_ciphers == NULL) {
992 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", psk_count);
993 return;
994 }
995 pki_ciphers = mbedtls_malloc(pki_count * sizeof(pki_ciphers[0]));
996 if (pki_ciphers == NULL) {
997 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", pki_count);
998 return;
999 }
1000
1001 psk_list = psk_ciphers;
1002 pki_list = pki_ciphers;
1003
1004 while (*list) {
1005 const mbedtls_ssl_ciphersuite_t *cur =
1006 mbedtls_ssl_ciphersuite_from_id(*list);
1007 if (cur) {
1008 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1009 /* Minimum of TLS1.2 required - skip */
1010 }
1011 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
1012 *psk_list = *list;
1013 psk_list++;
1014 }
1015 else {
1016 *pki_list = *list;
1017 pki_list++;
1018 }
1019 }
1020 list++;
1021 }
1022 /* zero terminate */
1023 *psk_list = 0;
1024 *pki_list = 0;
1025 processed_ciphers = 1;
1026 }
1027 mbedtls_ssl_conf_ciphersuites(conf, method == COAP_ENC_PSK ? psk_ciphers : pki_ciphers);
1028}
1029
1030static int setup_client_ssl_session(coap_session_t *c_session,
1031 coap_mbedtls_env_t *m_env)
1032{
1033 int ret;
1034
1035 coap_mbedtls_context_t *m_context =
1036 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1037
1038 m_context->psk_pki_enabled |= IS_CLIENT;
1039
1040 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
1041 MBEDTLS_SSL_IS_CLIENT,
1042 c_session->proto == COAP_PROTO_DTLS ?
1043 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
1044 MBEDTLS_SSL_TRANSPORT_STREAM,
1045 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
1046 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
1047 -ret, get_error_string(ret));
1048 goto fail;
1049 }
1050
1051#if defined(MBEDTLS_SSL_PROTO_DTLS)
1052 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
1054#endif /* MBEDTLS_SSL_PROTO_DTLS */
1055
1056 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
1057 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
1058
1059 if (m_context->psk_pki_enabled & IS_PSK) {
1060#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1061 uint8_t identity[64];
1062 size_t identity_len;
1063 uint8_t psk_key[64];
1064 size_t psk_len;
1065 size_t max_identity_len = sizeof(identity);
1066
1067 coap_log(LOG_INFO, "Setting PSK key\n");
1068 psk_len = c_session->context->get_client_psk(c_session,
1069 NULL,
1070 0,
1071 identity,
1072 &identity_len,
1073 max_identity_len,
1074 psk_key,
1075 sizeof(psk_key));
1076 assert(identity_len <= sizeof(identity));
1077 mbedtls_ssl_conf_psk(&m_env->conf, (const unsigned char *)psk_key,
1078 psk_len, (const unsigned char *)identity,
1079 identity_len);
1080 if (c_session->cpsk_setup_data.client_sni) {
1081 mbedtls_ssl_set_hostname(&m_env->ssl,
1082 c_session->cpsk_setup_data.client_sni);
1083 }
1084 /* Identity Hint currently not supported in Mbed TLS so code removed */
1085
1086 set_ciphersuites(&m_env->conf, COAP_ENC_PSK);
1087#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1088 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
1089#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1090 }
1091 else if ((m_context->psk_pki_enabled & IS_PKI) ||
1092 (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
1093 /*
1094 * If neither PSK or PKI have been set up, use PKI basics.
1095 * This works providing COAP_PKI_KEY_PEM has a value of 0.
1096 */
1097 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
1098 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
1099 &m_env->private_key, m_env, m_context,
1100 c_session, &m_context->setup_data,
1102 if (ret < 0) {
1103 coap_log(LOG_ERR, "PKI setup failed\n");
1104 return ret;
1105 }
1106#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN)
1107 if (c_session->proto == COAP_PROTO_TLS) {
1108 const char *alpn_list[] = { "coap", NULL };
1109
1110 ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list);
1111 if (ret != 0) {
1112 coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret);
1113 }
1114 }
1115#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN */
1116 if (m_context->setup_data.client_sni) {
1117 mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni);
1118 }
1119#if defined(MBEDTLS_SSL_PROTO_DTLS)
1120#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1121 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1122#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1123#endif /* MBEDTLS_SSL_PROTO_DTLS */
1124 set_ciphersuites(&m_env->conf, COAP_ENC_PKI);
1125 }
1126 return 0;
1127
1128fail:
1129 return ret;
1130}
1131
1132static void mbedtls_cleanup(coap_mbedtls_env_t *m_env)
1133{
1134 if (!m_env) {
1135 return;
1136 }
1137
1138 mbedtls_x509_crt_free(&m_env->cacert);
1139 mbedtls_x509_crt_free(&m_env->public_cert);
1140 mbedtls_pk_free(&m_env->private_key);
1141 mbedtls_entropy_free(&m_env->entropy);
1142 mbedtls_ssl_config_free(&m_env->conf);
1143 mbedtls_ctr_drbg_free(&m_env->ctr_drbg);
1144 mbedtls_ssl_free(&m_env->ssl);
1145 mbedtls_ssl_cookie_free(&m_env->cookie_ctx);
1146}
1147
1148static void
1149coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) {
1150 if (m_env) {
1151 mbedtls_cleanup(m_env);
1152 mbedtls_free(m_env);
1153 }
1154}
1155
1156static const char *
1157report_mbedtls_alert(unsigned char alert) {
1158 switch (alert) {
1159 case MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC: return ": Bad Record MAC";
1160 case MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE: return ": Handshake failure";
1161 case MBEDTLS_SSL_ALERT_MSG_NO_CERT: return ": No Certificate provided";
1162 case MBEDTLS_SSL_ALERT_MSG_BAD_CERT: return ": Certificate is bad";
1163 case MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA: return ": CA is unknown";
1164 case MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED: return ": Access was denied";
1165 case MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR: return ": Decrypt error";
1166 default: return "";
1167 }
1168}
1169
1170/*
1171 * return -1 failure
1172 * 0 not completed
1173 * 1 established
1174 */
1175static int do_mbedtls_handshake(coap_session_t *c_session,
1176 coap_mbedtls_env_t *m_env) {
1177 int ret;
1178 int alert;
1179
1180 ret = mbedtls_ssl_handshake(&m_env->ssl);
1181 switch (ret) {
1182 case 0:
1183 m_env->established = 1;
1184 coap_log(LOG_DEBUG, "* %s: Mbed TLS established\n",
1185 coap_session_str(c_session));
1186 ret = 1;
1187 break;
1188 case MBEDTLS_ERR_SSL_WANT_READ:
1189 case MBEDTLS_ERR_SSL_WANT_WRITE:
1190 errno = EAGAIN;
1191 ret = 0;
1192 break;
1193 case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
1194 coap_log(LOG_DEBUG, "hello verification requested\n");
1195 goto reset;
1196 case MBEDTLS_ERR_SSL_INVALID_MAC:
1197 goto fail;
1198 case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
1199 alert = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
1200 goto fail_alert;
1201 case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
1202 alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE;
1203 goto fail_alert;
1204 case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
1205 goto fail;
1206 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1207 if (m_env->ssl.in_msg[1] != MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
1208 coap_log(LOG_WARNING, "***%s: Alert '%d'%s\n",
1209 coap_session_str(c_session), m_env->ssl.in_msg[1],
1210 report_mbedtls_alert(m_env->ssl.in_msg[1]));
1211 /* Fall through */
1212 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1214 ret = -1;
1215 break;
1216 default:
1218 "do_mbedtls_handshake: session establish "
1219 "returned -0x%x: '%s'\n",
1220 -ret, get_error_string(ret));
1221 ret = -1;
1222 break;
1223 }
1224 return ret;
1225
1226fail_alert:
1227 mbedtls_ssl_send_alert_message(&m_env->ssl,
1228 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
1229 alert);
1230fail:
1231 c_session->dtls_event = COAP_EVENT_DTLS_ERROR;
1233 "do_mbedtls_handshake: session establish "
1234 "returned '%s'\n",
1235 get_error_string(ret));
1236reset:
1237 mbedtls_ssl_session_reset(&m_env->ssl);
1238 return -1;
1239}
1240
1241static void
1242mbedtls_debug_out(void *ctx COAP_UNUSED, int level,
1243 const char *file, int line, const char *str) {
1244 int log_level;
1245 /*
1246 * 0 No debug
1247 * 1 Error
1248 * 2 State change
1249 * 3 Informational
1250 * 4 Verbose
1251 */
1252 switch (level) {
1253 case 4:
1254 case 3:
1255 case 2:
1256 log_level = COAP_LOG_CIPHERS;
1257 break;
1258 case 1:
1259 log_level = LOG_ERR;
1260 break;
1261 case 0:
1262 default:
1263 log_level = 0;
1264 break;
1265 }
1266 coap_log(log_level, "%s:%04d: %s", file, line, str);
1267}
1268
1269static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session,
1270 coap_dtls_role_t role)
1271{
1272 int ret = 0;
1273 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1274
1275 if (m_env)
1276 return m_env;
1277
1278 m_env = (coap_mbedtls_env_t *)mbedtls_malloc(sizeof(coap_mbedtls_env_t));
1279 if (!m_env) {
1280 return NULL;
1281 }
1282 memset(m_env, 0, sizeof(coap_mbedtls_env_t));
1283
1284 mbedtls_ssl_init(&m_env->ssl);
1285 mbedtls_ctr_drbg_init(&m_env->ctr_drbg);
1286 mbedtls_ssl_config_init(&m_env->conf);
1287 mbedtls_entropy_init(&m_env->entropy);
1288
1289#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
1290 mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL);
1291#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
1292 if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg,
1293 mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) {
1294 coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n",
1295 -ret, get_error_string(ret));
1296 goto fail;
1297 }
1298
1299 if (role == COAP_DTLS_ROLE_CLIENT) {
1300 if (setup_client_ssl_session(c_session, m_env) != 0) {
1301 goto fail;
1302 }
1303#if defined(MBEDTLS_SSL_SRV_C)
1304 } else if (role == COAP_DTLS_ROLE_SERVER) {
1305 if (setup_server_ssl_session(c_session, m_env) != 0) {
1306 goto fail;
1307 }
1308#endif /* MBEDTLS_SSL_SRV_C */
1309 } else {
1310 goto fail;
1311 }
1312
1313 mbedtls_ssl_conf_min_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
1314 MBEDTLS_SSL_MINOR_VERSION_3);
1315
1316 if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) {
1317 goto fail;
1318 }
1319 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write,
1320 coap_dgram_read, NULL);
1321 mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer,
1322 mbedtls_timing_set_delay,
1323 mbedtls_timing_get_delay);
1324
1325 mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout);
1326 return m_env;
1327
1328fail:
1329 if (m_env) {
1330 mbedtls_free(m_env);
1331 }
1332 return NULL;
1333}
1334
1335int coap_dtls_is_supported(void) {
1336#if defined(MBEDTLS_SSL_PROTO_DTLS)
1337 return 1;
1338#else /* !MBEDTLS_SSL_PROTO_DTLS */
1340 "libcoap not compiled for DTLS with Mbed TLS"
1341 " - update Mbed TLS to include DTLS\n");
1342 return 0;
1343#endif /* !MBEDTLS_SSL_PROTO_DTLS */
1344}
1345
1346int coap_tls_is_supported(void)
1347{
1348 return 0;
1349}
1350
1351void *coap_dtls_new_context(coap_context_t *c_context)
1352{
1353 coap_mbedtls_context_t *m_context;
1354 (void)c_context;
1355
1356 m_context = (coap_mbedtls_context_t *)mbedtls_malloc(sizeof(coap_mbedtls_context_t));
1357 if (m_context) {
1358 memset(m_context, 0, sizeof(coap_mbedtls_context_t));
1359 }
1360 return m_context;
1361}
1362
1363/*
1364 * return 0 failed
1365 * 1 passed
1366 */
1367int
1369 coap_dtls_spsk_t *setup_data
1370) {
1371 coap_mbedtls_context_t *m_context =
1372 ((coap_mbedtls_context_t *)c_context->dtls_context);
1373
1374#if !defined(MBEDTLS_SSL_SRV_C)
1375 coap_log(LOG_EMERG, "coap_context_set_spsk:"
1376 " libcoap not compiled for Server Mode for Mbed TLS"
1377 " - update Mbed TLS to include Server Mode\n");
1378 return 0;
1379#endif /* !MBEDTLS_SSL_SRV_C */
1380 if (!m_context || !setup_data)
1381 return 0;
1382
1383 m_context->psk_pki_enabled |= IS_PSK;
1384 return 1;
1385}
1386
1387/*
1388 * return 0 failed
1389 * 1 passed
1390 */
1391int
1393 coap_dtls_cpsk_t *setup_data
1394) {
1395#if !defined(MBEDTLS_SSL_CLI_C)
1396 coap_log(LOG_EMERG, "coap_context_set_spsk:"
1397 " libcoap not compiled for Client Mode for Mbed TLS"
1398 " - update Mbed TLS to include Client Mode\n");
1399 return 0;
1400#endif /* !MBEDTLS_SSL_CLI_C */
1401 coap_mbedtls_context_t *m_context =
1402 ((coap_mbedtls_context_t *)c_context->dtls_context);
1403
1404 if (!m_context || !setup_data)
1405 return 0;
1406
1407 if (setup_data->validate_ih_call_back) {
1409 "CoAP Client with Mbed TLS does not support Identity Hint selection\n");
1410 }
1411 m_context->psk_pki_enabled |= IS_PSK;
1412 return 1;
1413}
1414
1416 const coap_dtls_pki_t *setup_data,
1417 const coap_dtls_role_t role COAP_UNUSED)
1418{
1419 coap_mbedtls_context_t *m_context =
1420 ((coap_mbedtls_context_t *)c_context->dtls_context);
1421
1422 m_context->setup_data = *setup_data;
1423 if (!m_context->setup_data.verify_peer_cert) {
1424 /* Needs to be clear so that no CA DNs are transmitted */
1425 m_context->setup_data.check_common_ca = 0;
1426 /* Allow all of these but warn if issue */
1427 m_context->setup_data.allow_self_signed = 1;
1428 m_context->setup_data.allow_expired_certs = 1;
1429 m_context->setup_data.cert_chain_validation = 1;
1430 m_context->setup_data.cert_chain_verify_depth = 10;
1431 m_context->setup_data.check_cert_revocation = 1;
1432 m_context->setup_data.allow_no_crl = 1;
1433 m_context->setup_data.allow_expired_crl = 1;
1434 m_context->setup_data.allow_bad_md_hash = 1;
1435 m_context->setup_data.allow_short_rsa_length = 1;
1436 }
1437 m_context->psk_pki_enabled |= IS_PKI;
1438 return 1;
1439}
1440
1442 const char *ca_file,
1443 const char *ca_path)
1444{
1445 coap_mbedtls_context_t *m_context =
1446 ((coap_mbedtls_context_t *)c_context->dtls_context);
1447
1448 if (!m_context) {
1450 "coap_context_set_pki_root_cas: (D)TLS environment "
1451 "not set up\n");
1452 return 0;
1453 }
1454
1455 if (ca_file == NULL && ca_path == NULL) {
1457 "coap_context_set_pki_root_cas: ca_file and/or ca_path "
1458 "not defined\n");
1459 return 0;
1460 }
1461 if (m_context->root_ca_file) {
1462 mbedtls_free(m_context->root_ca_file);
1463 m_context->root_ca_file = NULL;
1464 }
1465
1466 if (ca_file) {
1467 m_context->root_ca_file = mbedtls_strdup(ca_file);
1468 }
1469
1470 if (m_context->root_ca_path) {
1471 mbedtls_free(m_context->root_ca_path);
1472 m_context->root_ca_path = NULL;
1473 }
1474
1475 if (ca_path) {
1476 m_context->root_ca_path = mbedtls_strdup(ca_path);
1477 }
1478 return 1;
1479}
1480
1482{
1483 coap_mbedtls_context_t *m_context =
1484 ((coap_mbedtls_context_t *)c_context->dtls_context);
1485 return m_context->psk_pki_enabled ? 1 : 0;
1486}
1487
1488void coap_dtls_free_context(void *dtls_context)
1489{
1490 coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context;
1491 unsigned int i;
1492
1493 for (i = 0; i < m_context->pki_sni_count; i++) {
1494 mbedtls_free(m_context->pki_sni_entry_list[i].sni);
1495
1496 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert);
1497
1498 mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key);
1499
1500 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert);
1501 }
1502 if (m_context->pki_sni_entry_list)
1503 mbedtls_free(m_context->pki_sni_entry_list);
1504
1505 for (i = 0; i < m_context->psk_sni_count; i++) {
1506 mbedtls_free(m_context->psk_sni_entry_list[i].sni);
1507 }
1508 if (m_context->psk_sni_entry_list)
1509 mbedtls_free(m_context->psk_sni_entry_list);
1510
1511 if (m_context->root_ca_path)
1512 mbedtls_free(m_context->root_ca_path);
1513 if (m_context->root_ca_file)
1514 mbedtls_free(m_context->root_ca_file);
1515
1516 mbedtls_free(m_context);
1517}
1518
1520{
1521#if !defined(MBEDTLS_SSL_CLI_C)
1522 (void)c_session;
1523 coap_log(LOG_EMERG, "coap_dtls_new_client_session:"
1524 " libcoap not compiled for Client Mode for Mbed TLS"
1525 " - update Mbed TLS to include Client Mode\n");
1526 return NULL;
1527#else /* MBEDTLS_SSL_CLI_C */
1528 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
1530 int ret;
1531
1532 if (m_env) {
1533 coap_tick_t now;
1534 coap_ticks(&now);
1535 m_env->last_timeout = now;
1536 ret = do_mbedtls_handshake(c_session, m_env);
1537 if (ret == -1) {
1538 coap_dtls_free_mbedtls_env(m_env);
1539 return NULL;
1540 }
1541 }
1542 return m_env;
1543#endif /* MBEDTLS_SSL_CLI_C */
1544}
1545
1547{
1548 coap_mbedtls_env_t *m_env =
1549 (coap_mbedtls_env_t *)c_session->tls;
1550 if (m_env) {
1551#if defined(MBEDTLS_SSL_PROTO_DTLS)
1552#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1553 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1554#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1555#endif /* MBEDTLS_SSL_PROTO_DTLS */
1556 }
1557 return m_env;
1558}
1559
1561{
1562 if (c_session && c_session->context && c_session->tls) {
1563 coap_dtls_free_mbedtls_env(c_session->tls);
1564 c_session->tls = NULL;
1565 coap_handle_event(c_session->context, COAP_EVENT_DTLS_CLOSED, c_session);
1566 }
1567 return;
1568}
1569
1571{
1572#if defined(MBEDTLS_SSL_PROTO_DTLS)
1573 coap_mbedtls_env_t *m_env =
1574 (coap_mbedtls_env_t *)c_session->tls;
1575 if (m_env) {
1576#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1577 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1578#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1579 }
1580#endif /* MBEDTLS_SSL_PROTO_DTLS */
1581}
1582
1583int coap_dtls_send(coap_session_t *c_session,
1584 const uint8_t *data,
1585 size_t data_len)
1586{
1587 int ret;
1588 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1589
1590 assert(m_env != NULL);
1591
1592 if (!m_env) {
1593 return -1;
1594 }
1595 c_session->dtls_event = -1;
1596 if (m_env->established) {
1597 ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len);
1598 if (ret <= 0) {
1599 switch (ret) {
1600 case MBEDTLS_ERR_SSL_WANT_READ:
1601 case MBEDTLS_ERR_SSL_WANT_WRITE:
1602 ret = 0;
1603 break;
1604 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1606 ret = -1;
1607 break;
1608 default:
1610 "coap_dtls_send: "
1611 "returned -0x%x: '%s'\n",
1612 -ret, get_error_string(ret));
1613 ret = -1;
1614 break;
1615 }
1616 if (ret == -1) {
1617 coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1618 }
1619 }
1620 } else {
1621 ret = do_mbedtls_handshake(c_session, m_env);
1622 if (ret == 1) {
1623 /* Just connected, so send the data */
1624 return coap_dtls_send(c_session, data, data_len);
1625 }
1626 ret = -1;
1627 }
1628
1629 if (c_session->dtls_event >= 0) {
1630 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
1631 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
1632 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
1633 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1634 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1636 ret = -1;
1637 }
1638 }
1639 return ret;
1640}
1641
1643{
1644 return 0;
1645}
1646
1648{
1649 return 0;
1650}
1651
1653{
1654 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1655 int ret = mbedtls_timing_get_delay(&m_env->timer);
1656 unsigned int scalar = 1 << m_env->retry_scalar;
1657
1658 assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1659 switch (ret) {
1660 case 0:
1661 /* int_ms has not timed out */
1662 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1663 /* Need to indicate remaining timeout time */
1664 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1665 }
1666 m_env->last_timeout = now;
1667 /* This may cause a minor extra delay */
1668 return now + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1669 case 1:
1670 /* int_ms has timed out, but not fin_ms */
1671 /*
1672 * Need to make sure that we do not do this too frequently
1673 */
1674 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1675 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1676 }
1677
1678 /* Reset for the next time */
1679 m_env->last_timeout = now;
1680 return now;
1681 case 2:
1682 /* fin_ms has timed out - timed out - one final try */
1683 return now;
1684 default:
1685 break;
1686 }
1687
1688 return 0;
1689}
1690
1692{
1693 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1694
1695 assert(m_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1696 m_env->retry_scalar++;
1697 if ((++c_session->dtls_timeout_count > c_session->max_retransmit) ||
1698 (do_mbedtls_handshake(c_session, m_env) < 0)) {
1699 /* Too many retries */
1701 }
1702 return;
1703}
1704
1705/*
1706 * return +ve data amount
1707 * 0 no more
1708 * -1 error
1709 */
1710int coap_dtls_receive(coap_session_t *c_session,
1711 const uint8_t *data,
1712 size_t data_len)
1713{
1714 int ret = 1;
1715
1716 c_session->dtls_event = -1;
1717 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1718 coap_ssl_t *ssl_data;
1719
1720 assert(m_env != NULL);
1721
1722 ssl_data = &m_env->coap_ssl_data;
1723 if (ssl_data->pdu_len) {
1724 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
1725 coap_session_str(c_session), ssl_data->pdu_len);
1726 }
1727 ssl_data->pdu = data;
1728 ssl_data->pdu_len = (unsigned)data_len;
1729
1730 if (m_env->established) {
1731#if COAP_CONSTRAINED_STACK
1732 static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER;
1733 static uint8_t pdu[COAP_RXBUFFER_SIZE];
1734#else /* ! COAP_CONSTRAINED_STACK */
1735 uint8_t pdu[COAP_RXBUFFER_SIZE];
1736#endif /* ! COAP_CONSTRAINED_STACK */
1737
1738#if COAP_CONSTRAINED_STACK
1739 coap_mutex_lock(&b_static_mutex);
1740#endif /* COAP_CONSTRAINED_STACK */
1741
1742 if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) {
1744 c_session);
1745 coap_session_connected(c_session);
1746 }
1747
1748 ret = mbedtls_ssl_read(&m_env->ssl, pdu, sizeof(pdu));
1749 if (ret > 0) {
1750 ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret);
1751#if COAP_CONSTRAINED_STACK
1752 coap_mutex_unlock(&b_static_mutex);
1753#endif /* COAP_CONSTRAINED_STACK */
1754 goto finish;
1755 }
1756 switch (ret) {
1757 case 0:
1758 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1759 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1761 break;
1762 case MBEDTLS_ERR_SSL_WANT_READ:
1763 break;
1764 default:
1766 "coap_dtls_receive: "
1767 "returned -0x%x: '%s' (length %zd)\n",
1768 -ret, get_error_string(ret), data_len);
1769 break;
1770 }
1771#if COAP_CONSTRAINED_STACK
1772 coap_mutex_unlock(&b_static_mutex);
1773#endif /* COAP_CONSTRAINED_STACK */
1774 ret = -1;
1775 }
1776 else {
1777 ret = do_mbedtls_handshake(c_session, m_env);
1778 if (ret == 1) {
1779 /* Just connected, so send the data */
1780 coap_session_connected(c_session);
1781 } else {
1782 if (ssl_data->pdu_len) {
1783 /* Do the handshake again incase of internal timeout */
1784 ret = do_mbedtls_handshake(c_session, m_env);
1785 if (ret == 1) {
1786 /* Just connected, so send the data */
1787 coap_session_connected(c_session);
1788 } else {
1789 ret = -1;
1790 }
1791 }
1792 ret = -1;
1793 }
1794 }
1795 if (c_session->dtls_event >= 0) {
1796 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
1797 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
1798 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
1799 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1800 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1802 ssl_data = NULL;
1803 ret = -1;
1804 }
1805 }
1806finish:
1807 if (ssl_data && ssl_data->pdu_len) {
1808 /* pdu data is held on stack which will not stay there */
1809 coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
1810 ssl_data->pdu_len = 0;
1811 ssl_data->pdu = NULL;
1812 }
1813 return ret;
1814}
1815
1816/*
1817 * return -1 failure
1818 * 0 not completed
1819 * 1 client hello seen
1820 */
1821int coap_dtls_hello(coap_session_t *c_session,
1822 const uint8_t *data,
1823 size_t data_len)
1824{
1825#if !defined(MBEDTLS_SSL_PROTO_DTLS) || !defined(MBEDTLS_SSL_SRV_C)
1826 (void)c_session;
1827 (void)data;
1828 (void)data_len;
1829 coap_log(LOG_EMERG, "coap_dtls_hello:"
1830 " libcoap not compiled for DTLS or Server Mode for Mbed TLS"
1831 " - update Mbed TLS to include DTLS and Server Mode\n");
1832 return -1;
1833#else /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
1834 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1835 coap_ssl_t *ssl_data;
1836 int ret;
1837
1838 if (!m_env) {
1839 m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER);
1840 if (m_env) {
1841 c_session->tls = m_env;
1842 }
1843 else {
1844 /* error should have already been reported */
1845 return -1;
1846 }
1847 }
1848
1849 if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl,
1850 (unsigned char *)&c_session->addr_info.remote,
1851 sizeof(c_session->addr_info.remote))) != 0) {
1853 "mbedtls_ssl_set_client_transport_id() returned -0x%x: '%s'\n",
1854 -ret, get_error_string(ret));
1855 return -1;
1856 }
1857
1858 ssl_data = &m_env->coap_ssl_data;
1859 if (ssl_data->pdu_len) {
1860 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
1861 coap_session_str(c_session), ssl_data->pdu_len);
1862 }
1863 ssl_data->pdu = data;
1864 ssl_data->pdu_len = (unsigned)data_len;
1865
1866 ret = do_mbedtls_handshake(c_session, m_env);
1867 if (ret == 0 || m_env->seen_client_hello) {
1868 /* The test for seen_client_hello gives the ability to setup a new
1869 c_session to continue the do_mbedtls_handshake past the client hello
1870 and safely allow updating of the m_env and separately
1871 letting a new session cleanly start up.
1872 */
1873 m_env->seen_client_hello = 0;
1874 ret = 1;
1875 }
1876 else {
1877 ret = 0;
1878 }
1879
1880 if (ssl_data->pdu_len) {
1881 /* pdu data is held on stack which will not stay there */
1882 coap_log(LOG_DEBUG, "coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
1883 ssl_data->pdu_len = 0;
1884 ssl_data->pdu = NULL;
1885 }
1886 return ret;
1887#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
1888}
1889
1890unsigned int coap_dtls_get_overhead(coap_session_t *c_session)
1891{
1892 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1893 int expansion = mbedtls_ssl_get_record_expansion(&m_env->ssl);
1894
1895 if (expansion == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
1896 return 13 + 8 + 8;
1897 }
1898 return expansion;
1899}
1900
1901#if !COAP_DISABLE_TCP
1903 int *connected COAP_UNUSED)
1904{
1905 return NULL;
1906}
1907
1909 int *connected COAP_UNUSED)
1910{
1911 return NULL;
1912}
1913
1915{
1916}
1917
1918ssize_t coap_tls_write(coap_session_t *c_session COAP_UNUSED,
1919 const uint8_t *data COAP_UNUSED,
1920 size_t data_len COAP_UNUSED
1921 )
1922{
1923 return 0;
1924}
1925
1926ssize_t coap_tls_read(coap_session_t *c_session COAP_UNUSED,
1927 uint8_t *data COAP_UNUSED,
1928 size_t data_len COAP_UNUSED
1929 )
1930{
1931 return 0;
1932}
1933#endif /* !COAP_DISABLE_TCP */
1934
1935void coap_dtls_startup(void)
1936{
1937}
1938
1939void coap_dtls_shutdown(void) {
1940}
1941
1942void *
1943coap_dtls_get_tls(const coap_session_t *c_session,
1944 coap_tls_library_t *tls_lib) {
1945 if (tls_lib)
1946 *tls_lib = COAP_TLS_LIBRARY_MBEDTLS;
1947 if (c_session && c_session->tls) {
1948 coap_mbedtls_env_t *m_env;
1949
1950 /* To get around const issue */
1951 memcpy(&m_env, &c_session->tls, sizeof(m_env));
1952
1953 return (void *)&m_env->ssl;
1954 }
1955 return NULL;
1956}
1957
1958static int keep_log_level = 0;
1959
1960void coap_dtls_set_log_level(int level)
1961{
1962#if !defined(ESPIDF_VERSION)
1963 int use_level;
1964 /*
1965 * Mbed TLS debug levels filter
1966 * 0 No debug
1967 * 1 Error
1968 * 2 State change
1969 * 3 Informational
1970 * 4 Verbose
1971 */
1972
1973 if (level <= LOG_ERR) {
1974 use_level = 1;
1975 }
1976 else {
1977 use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0;
1978 }
1979 mbedtls_debug_set_threshold(use_level);
1980#endif /* !ESPIDF_VERSION) */
1981 keep_log_level = level;
1982}
1983
1985{
1986 return keep_log_level;
1987}
1988
1990{
1991 static coap_tls_version_t version;
1992 version.version = mbedtls_version_get_number();
1993 version.built_version = MBEDTLS_VERSION_NUMBER;
1995 return &version;
1996}
1997
1999coap_digest_setup(void) {
2000 mbedtls_sha256_context *digest_ctx = mbedtls_malloc(sizeof(mbedtls_sha256_context));
2001
2002 if (digest_ctx) {
2003 mbedtls_sha256_init(digest_ctx);
2004 mbedtls_sha256_starts_ret(digest_ctx, 0);
2005 }
2006 return digest_ctx;
2007}
2008
2009void
2011 mbedtls_sha256_free(digest_ctx);
2012 mbedtls_free(digest_ctx);
2013}
2014
2015int
2017 const uint8_t *data,
2018 size_t data_len) {
2019 int ret = mbedtls_sha256_update_ret(digest_ctx, data, data_len);
2020
2021 return ret == 0;
2022}
2023
2024int
2026 coap_digest_t *digest_buffer) {
2027 int ret = mbedtls_sha256_finish_ret(digest_ctx, (uint8_t*)digest_buffer);
2028
2029 coap_digest_free(digest_ctx);
2030 return ret == 0;
2031}
2032
2033#else /* !HAVE_MBEDTLS */
2034
2035#ifdef __clang__
2036/* Make compilers happy that do not like empty modules. As this function is
2037 * never used, we ignore -Wunused-function at the end of compiling this file
2038 */
2039#pragma GCC diagnostic ignored "-Wunused-function"
2040#endif
2041static inline void dummy(void) {
2042}
2043
2044#endif /* HAVE_MBEDTLS */
Pulls together all the internal only header files.
#define COAP_RXBUFFER_SIZE
Definition: coap_io.h:24
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:68
static void dummy(void)
int coap_dtls_context_set_spsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_spsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:58
void coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:140
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:35
void * coap_tls_new_client_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:163
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition: coap_notls.c:136
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:120
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:181
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition: coap_notls.c:131
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:144
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition: coap_notls.c:76
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:159
int coap_dtls_hello(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition: coap_notls.c:152
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition: coap_notls.c:65
void * coap_dtls_new_client_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:109
int coap_dtls_context_set_cpsk(coap_context_t *ctx COAP_UNUSED, coap_dtls_cpsk_t *setup_data COAP_UNUSED)
Definition: coap_notls.c:51
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:174
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:116
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:43
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition: coap_notls.c:102
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:113
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition: coap_notls.c:97
void * coap_dtls_new_server_session(coap_session_t *session COAP_UNUSED)
Definition: coap_notls.c:105
void * coap_tls_new_server_session(coap_session_t *session COAP_UNUSED, int *connected COAP_UNUSED)
Definition: coap_notls.c:167
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition: coap_notls.c:171
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
Definition: coap_notls.c:205
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.
Definition: coap_notls.c:222
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.
Definition: coap_notls.c:210
void coap_digest_ctx_t
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
Definition: coap_notls.c:194
void coap_ticks(coap_tick_t *t)
Sets t to the internal time with COAP_TICKS_PER_SECOND resolution.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition: coap_time.h:122
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:1898
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:3163
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition: coap_notls.c:72
#define COAP_DTLS_RETRANSMIT_MS
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition: coap_notls.c:127
void coap_dtls_shutdown(void)
Close down the underlying (D)TLS Library layer.
Definition: coap_notls.c:83
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
#define COAP_DTLS_RETRANSMIT_TOTAL_MS
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:27
coap_dtls_role_t
Definition: coap_dtls.h:31
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition: coap_notls.c:22
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition: coap_notls.c:17
coap_tls_library_t
Definition: coap_dtls.h:52
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition: coap_dtls.h:33
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition: coap_dtls.h:32
@ COAP_PKI_KEY_PKCS11
The PKI key type is PKCS11 (DER)
Definition: coap_dtls.h:152
@ COAP_PKI_KEY_PEM_BUF
The PKI key type is PEM buffer.
Definition: coap_dtls.h:151
@ COAP_PKI_KEY_PEM
The PKI key type is PEM file.
Definition: coap_dtls.h:149
@ COAP_PKI_KEY_ASN1
The PKI key type is ASN.1 (DER) buffer.
Definition: coap_dtls.h:150
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition: coap_dtls.h:57
#define COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:35
#define COAP_EVENT_DTLS_CLOSED
(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
Definition: coap_event.h:32
#define COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:33
void coap_dtls_set_log_level(int level)
Sets the (D)TLS logging level to the specified level.
Definition: coap_notls.c:87
int coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition: coap_notls.c:92
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log(level,...)
Logging function.
Definition: coap_debug.h:152
@ LOG_ERR
Error.
Definition: coap_debug.h:55
@ LOG_INFO
Information.
Definition: coap_debug.h:58
@ LOG_WARNING
Warning.
Definition: coap_debug.h:56
@ LOG_DEBUG
Debug.
Definition: coap_debug.h:59
@ COAP_LOG_CIPHERS
CipherInfo.
Definition: coap_debug.h:60
@ LOG_EMERG
Emergency.
Definition: coap_debug.h:52
@ COAP_PROTO_DTLS
Definition: pdu.h:283
@ COAP_PROTO_TLS
Definition: pdu.h:285
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
Definition: coap_session.c:996
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:277
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:399
void coap_session_disconnected(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
Definition: coap_session.c:456
@ COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:55
#define COAP_UNUSED
Definition: libcoap.h:55
coap_address_t remote
remote address and port
Definition: coap_io.h:51
CoAP binary data definition with const data.
Definition: str.h:58
size_t length
length of binary data
Definition: str.h:59
const uint8_t * s
read-only binary data
Definition: str.h:60
The CoAP stack's global state is stored in a coap_context_t object.
size_t(* get_server_psk)(const coap_session_t *session, const uint8_t *identity, size_t identity_len, uint8_t *psk, size_t max_psk_len)
size_t(* get_client_psk)(const coap_session_t *session, const uint8_t *hint, size_t hint_len, uint8_t *identity, size_t *identity_len, size_t max_identity_len, uint8_t *psk, size_t max_psk_len)
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:338
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition: coap_dtls.h:362
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition: coap_dtls.h:358
The structure that holds the PKI key information.
Definition: coap_dtls.h:212
coap_pki_key_pem_t pem
for PEM file keys
Definition: coap_dtls.h:215
union coap_dtls_key_t::@2 key
coap_pki_key_pem_buf_t pem_buf
for PEM memory keys
Definition: coap_dtls.h:216
coap_pki_key_t key_type
key format type
Definition: coap_dtls.h:213
coap_pki_key_asn1_t asn1
for ASN.1 (DER) memory keys
Definition: coap_dtls.h:217
The structure used for defining the PKI setup data to be used.
Definition: coap_dtls.h:244
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition: coap_dtls.h:249
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition: coap_dtls.h:262
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:250
coap_dtls_key_t pki_key
PKI key definition.
Definition: coap_dtls.h:301
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition: coap_dtls.h:374
The structure used for defining the Server PSK setup data to be used.
Definition: coap_dtls.h:425
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition: coap_dtls.h:452
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition: coap_dtls.h:444
void * id_call_back_arg
Passed in to the Identity callback function.
Definition: coap_dtls.h:445
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition: coap_dtls.h:453
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:190
size_t public_cert_len
ASN1 Public Cert length.
Definition: coap_dtls.h:192
size_t private_key_len
ASN1 Private Key length.
Definition: coap_dtls.h:193
const uint8_t * ca_cert
ASN1 (DER) Common CA Cert.
Definition: coap_dtls.h:188
size_t ca_cert_len
ASN1 CA Cert length.
Definition: coap_dtls.h:191
const uint8_t * public_cert
ASN1 (DER) Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:189
size_t ca_cert_len
PEM buffer CA Cert length.
Definition: coap_dtls.h:179
const uint8_t * ca_cert
PEM buffer Common CA Cert.
Definition: coap_dtls.h:174
size_t private_key_len
PEM buffer Private Key length.
Definition: coap_dtls.h:181
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:176
size_t public_cert_len
PEM buffer Public Cert length.
Definition: coap_dtls.h:180
const uint8_t * public_cert
PEM buffer Public Cert, or Public Key if RPK.
Definition: coap_dtls.h:175
const char * ca_file
File location of Common CA in PEM format.
Definition: coap_dtls.h:159
const char * public_cert
File location of Public Cert.
Definition: coap_dtls.h:160
const char * private_key
File location of Private Key in PEM format.
Definition: coap_dtls.h:161
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
unsigned int max_retransmit
maximum re-transmit count (default 4)
coap_session_state_t state
current state of relationaship with peer
coap_addr_tuple_t addr_info
key: remote/local address info
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
int dtls_event
Tracking any (D)TLS events on this sesison.
void * tls
security parameters
coap_context_t * context
session's context
The structure used for returning the underlying (D)TLS library information.
Definition: coap_dtls.h:64
uint64_t built_version
(D)TLS Built against Library Version
Definition: coap_dtls.h:67
coap_tls_library_t type
Library type.
Definition: coap_dtls.h:66
uint64_t version
(D)TLS runtime Library Version
Definition: coap_dtls.h:65