libcoap 4.3.1rc1
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-2022 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
18/*
19 * Naming used to prevent confusion between coap sessions, mbedtls sessions etc.
20 * when reading the code.
21 *
22 * c_context A coap_context_t *
23 * c_session A coap_session_t *
24 * m_context A coap_mbedtls_context_t * (held in c_context->dtls_context)
25 * m_env A coap_mbedtls_env_t * (held in c_session->tls)
26 */
27
28#include "coap3/coap_internal.h"
29
30#ifdef HAVE_MBEDTLS
31
32/*
33 * This code can be conditionally compiled to remove some components if
34 * they are not required to make a lighter footprint - all based on how
35 * the mbedtls library has been built. These are not defined within the
36 * libcoap environment.
37 *
38 * MBEDTLS_SSL_SRV_C - defined for server side functionality
39 * MBEDTLS_SSL_CLI_C - defined for client side functionality
40 * MBEDTLS_SSL_PROTO_DTLS - defined for DTLS support
41 * MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED - defined if PSK is to be supported
42 * or MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED - defined if PSK is to be supported
43 *
44 */
45
46#include <mbedtls/version.h>
47
48/* Keep forward-compatibility with Mbed TLS 3.x */
49#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
50#define MBEDTLS_2_X_COMPAT
51#else /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */
52/* Macro wrapper for struct's private members */
53#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS
54#define MBEDTLS_ALLOW_PRIVATE_ACCESS
55#endif /* MBEDTLS_ALLOW_PRIVATE_ACCESS */
56#endif /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */
57
58#include <mbedtls/platform.h>
59#include <mbedtls/net_sockets.h>
60#include <mbedtls/ssl.h>
61#include <mbedtls/entropy.h>
62#include <mbedtls/ctr_drbg.h>
63#include <mbedtls/error.h>
64#include <mbedtls/timing.h>
65#include <mbedtls/ssl_cookie.h>
66#include <mbedtls/oid.h>
67#include <mbedtls/debug.h>
68#include <mbedtls/sha256.h>
69#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
70#include <mbedtls/esp_debug.h>
71#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
72#include <errno.h>
73
74#define mbedtls_malloc(a) malloc(a)
75#define mbedtls_realloc(a,b) realloc(a,b)
76#define mbedtls_strdup(a) strdup(a)
77#define mbedtls_strndup(a,b) strndup(a,b)
78
79#ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
80/* definition changed in later mbedtls code versions */
81#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
82#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
83#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
84#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
85
86#if ! COAP_SERVER_SUPPORT
87#undef MBEDTLS_SSL_SRV_C
88#endif /* ! COAP_SERVER_SUPPORT */
89#if ! COAP_CLIENT_SUPPORT
90#undef MBEDTLS_SSL_CLI_C
91#endif /* ! COAP_CLIENT_SUPPORT */
92
93#ifdef _WIN32
94#define strcasecmp _stricmp
95#endif
96
97#define IS_PSK (1 << 0)
98#define IS_PKI (1 << 1)
99#define IS_CLIENT (1 << 6)
100#define IS_SERVER (1 << 7)
101
102typedef struct coap_ssl_t {
103 const uint8_t *pdu;
104 unsigned pdu_len;
105 unsigned peekmode;
106} coap_ssl_t;
107
108/*
109 * This structure encapsulates the Mbed TLS session object.
110 * It handles both TLS and DTLS.
111 * c_session->tls points to this.
112 */
113typedef struct coap_mbedtls_env_t {
114 mbedtls_ssl_context ssl;
115 mbedtls_entropy_context entropy;
116 mbedtls_ctr_drbg_context ctr_drbg;
117 mbedtls_ssl_config conf;
118 mbedtls_timing_delay_context timer;
119 mbedtls_x509_crt cacert;
120 mbedtls_x509_crt public_cert;
121 mbedtls_pk_context private_key;
122 mbedtls_ssl_cookie_ctx cookie_ctx;
123 /* If not set, need to do do_mbedtls_handshake */
124 int established;
125 int sent_alert;
126 int seen_client_hello;
127 coap_tick_t last_timeout;
128 unsigned int retry_scalar;
129 coap_ssl_t coap_ssl_data;
130} coap_mbedtls_env_t;
131
132typedef struct pki_sni_entry {
133 char *sni;
134 coap_dtls_key_t pki_key;
135 mbedtls_x509_crt cacert;
136 mbedtls_x509_crt public_cert;
137 mbedtls_pk_context private_key;
138} pki_sni_entry;
139
140typedef struct psk_sni_entry {
141 char* sni;
142 coap_dtls_spsk_info_t psk_info;
143} psk_sni_entry;
144
145typedef struct coap_mbedtls_context_t {
146 coap_dtls_pki_t setup_data;
147 size_t pki_sni_count;
148 pki_sni_entry *pki_sni_entry_list;
149 size_t psk_sni_count;
150 psk_sni_entry *psk_sni_entry_list;
151 char *root_ca_file;
152 char *root_ca_path;
153 int psk_pki_enabled;
154} coap_mbedtls_context_t;
155
156typedef enum coap_enc_method_t {
157 COAP_ENC_PSK,
158 COAP_ENC_PKI,
159} coap_enc_method_t;
160
161#ifndef MBEDTLS_2_X_COMPAT
162/*
163 * mbedtls_ callback functions expect 0 on success, -ve on failure.
164 */
165static int coap_rng(void *ctx COAP_UNUSED, unsigned char *buf, size_t len)
166{
167 return coap_prng(buf, len) ? 0 : MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
168}
169#endif /* MBEDTLS_2_X_COMPAT */
170
171static int coap_dgram_read(void *ctx, unsigned char *out, size_t outl)
172{
173 ssize_t ret = 0;
174 coap_session_t *c_session = (coap_session_t *)ctx;
175 coap_ssl_t *data;
176
177 if (!c_session->tls) {
178 errno = EAGAIN;
179 return MBEDTLS_ERR_SSL_WANT_READ;
180 }
181 data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data;
182
183 if (out != NULL) {
184 if (data->pdu_len > 0) {
185 if (outl < data->pdu_len) {
186 memcpy(out, data->pdu, outl);
187 ret = outl;
188 data->pdu += outl;
189 data->pdu_len -= outl;
190 }
191 else {
192 memcpy(out, data->pdu, data->pdu_len);
193 ret = data->pdu_len;
194 if (!data->peekmode) {
195 data->pdu_len = 0;
196 data->pdu = NULL;
197 }
198 }
199 }
200 else {
201 ret = MBEDTLS_ERR_SSL_WANT_READ;
202 errno = EAGAIN;
203 }
204 }
205 return ret;
206}
207
208/*
209 * return +ve data amount
210 * 0 no more
211 * -ve Mbed TLS error
212 */
213/* callback function given to mbedtls for sending data over socket */
214static int
215coap_dgram_write(void *ctx, const unsigned char *send_buffer,
216 size_t send_buffer_length)
217{
218 ssize_t result = -1;
219 coap_session_t *c_session = (coap_session_t *)ctx;
220
221 if (c_session) {
222 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
223 result = coap_session_send(c_session, send_buffer, send_buffer_length);
224 if (result != (ssize_t)send_buffer_length) {
225 coap_log(LOG_WARNING, "coap_network_send failed (%zd != %zu)\n",
226 result, send_buffer_length);
227 result = 0;
228 }
229 else if (m_env) {
230 coap_tick_t now;
231 coap_ticks(&now);
232 m_env->last_timeout = now;
233 }
234 } else {
235 result = 0;
236 }
237 return result;
238}
239
240#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && defined(MBEDTLS_SSL_SRV_C)
241/*
242 * Server side PSK callback
243 */
244static int psk_server_callback(void *p_info, mbedtls_ssl_context *ssl,
245 const unsigned char *identity, size_t identity_len )
246{
247 coap_session_t *c_session = (coap_session_t *)p_info;
248 coap_dtls_spsk_t *setup_data;
249 coap_mbedtls_env_t *m_env;
250 coap_bin_const_t lidentity;
251 const coap_bin_const_t *psk_key;
252
253 if (c_session == NULL)
254 return -1;
255
256 /* Track the Identity being used */
257 lidentity.s = identity ? (const uint8_t*)identity : (const uint8_t*)"";
258 lidentity.length = identity ? identity_len : 0;
259 coap_session_refresh_psk_identity(c_session, &lidentity);
260
261 coap_log(LOG_DEBUG, "got psk_identity: '%.*s'\n",
262 (int)lidentity.length, (const char *)lidentity.s);
263
264 m_env = (coap_mbedtls_env_t *)c_session->tls;
265 setup_data = &c_session->context->spsk_setup_data;
266
267 if (setup_data->validate_id_call_back) {
268 psk_key = setup_data->validate_id_call_back(&lidentity,
269 c_session,
270 setup_data->id_call_back_arg);
271
272 coap_session_refresh_psk_key(c_session, psk_key);
273 }
274 else {
275 psk_key = coap_get_session_server_psk_key(c_session);
276 }
277
278 if (psk_key == NULL)
279 return -1;
280 mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length);
281 m_env->seen_client_hello = 1;
282 return 0;
283}
284#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && MBEDTLS_SSL_SRV_C */
285
286static char*
287get_san_or_cn_from_cert(mbedtls_x509_crt *crt)
288{
289 if (crt) {
290 const mbedtls_asn1_named_data * cn_data;
291
292 if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
293 mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
294 while (seq && seq->buf.p == NULL) {
295 seq = seq->next;
296 }
297 if (seq) {
298 /* Return the Subject Alt Name */
299 return mbedtls_strndup((const char *)seq->buf.p,
300 seq->buf.len);
301 }
302 }
303
304 cn_data = mbedtls_asn1_find_named_data(&crt->subject,
305 MBEDTLS_OID_AT_CN,
306 MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN));
307 if (cn_data) {
308 /* Return the Common Name */
309 return mbedtls_strndup((const char *)cn_data->val.p,
310 cn_data->val.len);
311 }
312 }
313 return NULL;
314}
315
316static char *
317get_error_string(int ret) {
318 static char buf[128] = {0};
319 mbedtls_strerror(ret, buf, sizeof(buf)-1);
320 return buf;
321}
322
323static int
324self_signed_cert_verify_callback_mbedtls(void *data,
325 mbedtls_x509_crt *crt COAP_UNUSED,
326 int depth COAP_UNUSED,
327 uint32_t *flags)
328{
329 const coap_session_t *c_session = (coap_session_t*)data;
330 const coap_mbedtls_context_t *m_context =
331 (coap_mbedtls_context_t *)c_session->context->dtls_context;
332 const coap_dtls_pki_t *setup_data = &m_context->setup_data;
333
334 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
335 if (setup_data->allow_expired_certs) {
336 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
337 }
338 }
339 return 0;
340}
341
342/*
343 * return 0 All OK
344 * -ve Error Code
345 */
346static int
347cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt,
348 int depth, uint32_t *flags)
349{
350 coap_session_t *c_session = (coap_session_t*)data;
351 coap_mbedtls_context_t *m_context =
352 (coap_mbedtls_context_t *)c_session->context->dtls_context;
353 coap_dtls_pki_t *setup_data = &m_context->setup_data;
354 char *cn = NULL;
355
356 if (*flags == 0)
357 return 0;
358
359 cn = get_san_or_cn_from_cert(crt);
360
361 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
362 if (setup_data->allow_expired_certs) {
363 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
365 " %s: %s: overridden: '%s' depth %d\n",
366 coap_session_str(c_session),
367 "The certificate has expired", cn ? cn : "?", depth);
368 }
369 }
370 if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
371 if (setup_data->allow_expired_certs) {
372 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
374 " %s: %s: overridden: '%s' depth %d\n",
375 coap_session_str(c_session),
376 "The certificate has a future date", cn ? cn : "?", depth);
377 }
378 }
379 if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
380 if (setup_data->allow_bad_md_hash) {
381 *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD;
383 " %s: %s: overridden: '%s' depth %d\n",
384 coap_session_str(c_session),
385 "The certificate has a bad MD hash", cn ? cn : "?", depth);
386 }
387 }
388 if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) {
389 if (setup_data->allow_short_rsa_length) {
390 *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY;
392 " %s: %s: overridden: '%s' depth %d\n",
393 coap_session_str(c_session),
394 "The certificate has a short RSA length", cn ? cn : "?", depth);
395 }
396 }
397 if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
398 uint32_t lflags;
399 int self_signed = !mbedtls_x509_crt_verify(crt, crt, NULL, NULL, &lflags,
400 self_signed_cert_verify_callback_mbedtls,
401 data);
402 if (self_signed && depth == 0) {
403 if (setup_data->allow_self_signed &&
404 !setup_data->check_common_ca) {
405 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
407 " %s: %s: overridden: '%s' depth %d\n",
408 coap_session_str(c_session),
409 "Self-signed",
410 cn ? cn : "?", depth);
411 }
412 }
413 else {
414 if (!setup_data->verify_peer_cert) {
415 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
417 " %s: %s: overridden: '%s' depth %d\n",
418 coap_session_str(c_session),
419 "The certificate's CA does not match", cn ? cn : "?", depth);
420 }
421 }
422 }
423 if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) {
424 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
425 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
427 " %s: %s: overridden: '%s' depth %d\n",
428 coap_session_str(c_session),
429 "The certificate's CRL has expired", cn ? cn : "?", depth);
430 }
431 else if (!setup_data->check_cert_revocation) {
432 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
433 }
434 }
435 if (*flags & MBEDTLS_X509_BADCRL_FUTURE) {
436 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
437 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
439 " %s: %s: overridden: '%s' depth %d\n",
440 coap_session_str(c_session),
441 "The certificate's CRL has a future date", cn ? cn : "?", depth);
442 }
443 else if (!setup_data->check_cert_revocation) {
444 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
445 }
446 }
447 if (setup_data->cert_chain_validation &&
448 depth > (setup_data->cert_chain_verify_depth + 1)) {
449 *flags |= MBEDTLS_X509_BADCERT_OTHER;
451 " %s: %s: '%s' depth %d\n",
452 coap_session_str(c_session),
453 "The certificate's verify depth is too long",
454 cn ? cn : "?", depth);
455 }
456
457 if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
458 *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
459 }
460 if (setup_data->validate_cn_call_back) {
461 if (!setup_data->validate_cn_call_back(cn,
462 crt->raw.p,
463 crt->raw.len,
464 c_session,
465 depth,
466 *flags == 0,
467 setup_data->cn_call_back_arg)) {
468 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
469 }
470 }
471 if (*flags != 0) {
472 char buf[128];
473 char *tcp;
474 int ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
475
476 if (ret >= 0) {
477 tcp = strchr(buf, '\n');
478 while (tcp) {
479 *tcp = '\000';
481 " %s: %s: issue 0x%x: '%s' depth %d\n",
482 coap_session_str(c_session),
483 buf, *flags, cn ? cn : "?", depth);
484 tcp = strchr(tcp+1, '\n');
485 }
486 }
487 else {
488 coap_log(LOG_ERR, "mbedtls_x509_crt_verify_info returned -0x%x: '%s'\n",
489 -ret, get_error_string(ret));
490 }
491 }
492
493 if (cn)
494 mbedtls_free(cn);
495
496 return 0;
497}
498
499static int
500setup_pki_credentials(mbedtls_x509_crt *cacert,
501 mbedtls_x509_crt *public_cert,
502 mbedtls_pk_context *private_key,
503 coap_mbedtls_env_t *m_env,
504 coap_mbedtls_context_t *m_context,
505 coap_session_t *c_session,
506 coap_dtls_pki_t *setup_data,
507 coap_dtls_role_t role)
508{
509 int ret;
510
511 if (setup_data->is_rpk_not_cert) {
513 "RPK Support not available in Mbed TLS\n");
514 return -1;
515 }
516 switch (setup_data->pki_key.key_type) {
517 case COAP_PKI_KEY_PEM:
518 if (setup_data->pki_key.key.pem.public_cert &&
519 setup_data->pki_key.key.pem.public_cert[0] &&
520 setup_data->pki_key.key.pem.private_key &&
521 setup_data->pki_key.key.pem.private_key[0]) {
522
523 mbedtls_x509_crt_init(public_cert);
524 mbedtls_pk_init(private_key);
525
526 ret = mbedtls_x509_crt_parse_file(public_cert,
527 setup_data->pki_key.key.pem.public_cert);
528 if (ret < 0) {
529 coap_log(LOG_ERR, "mbedtls_x509_crt_parse_file returned -0x%x: '%s'\n",
530 -ret, get_error_string(ret));
531 return ret;
532 }
533
534#ifdef MBEDTLS_2_X_COMPAT
535 ret = mbedtls_pk_parse_keyfile(private_key,
536 setup_data->pki_key.key.pem.private_key, NULL);
537#else
538 ret = mbedtls_pk_parse_keyfile(private_key,
539 setup_data->pki_key.key.pem.private_key,
540 NULL, coap_rng, (void *)&m_env->ctr_drbg);
541#endif /* MBEDTLS_2_X_COMPAT */
542 if (ret < 0) {
543 coap_log(LOG_ERR, "mbedtls_pk_parse_keyfile returned -0x%x: '%s'\n",
544 -ret, get_error_string(ret));
545 return ret;
546 }
547
548 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
549 if (ret < 0) {
550 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
551 -ret, get_error_string(ret));
552 return ret;
553 }
554 }
555 else if (role == COAP_DTLS_ROLE_SERVER) {
557 "***setup_pki: (D)TLS: No Server Certificate + Private "
558 "Key defined\n");
559 return -1;
560 }
561
562 if (setup_data->pki_key.key.pem.ca_file &&
563 setup_data->pki_key.key.pem.ca_file[0]) {
564 mbedtls_x509_crt_init(cacert);
565 ret = mbedtls_x509_crt_parse_file(cacert,
566 setup_data->pki_key.key.pem.ca_file);
567 if (ret < 0) {
568 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
569 -ret, get_error_string(ret));
570 return ret;
571 }
572 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
573 }
574 break;
576 if (setup_data->pki_key.key.pem_buf.public_cert &&
577 setup_data->pki_key.key.pem_buf.public_cert_len &&
578 setup_data->pki_key.key.pem_buf.private_key &&
579 setup_data->pki_key.key.pem_buf.private_key_len) {
580 uint8_t *buffer;
581 size_t length;
582
583 mbedtls_x509_crt_init(public_cert);
584 mbedtls_pk_init(private_key);
585
586 length = setup_data->pki_key.key.pem_buf.public_cert_len;
587 if (setup_data->pki_key.key.pem_buf.public_cert[length-1] != '\000') {
588 /* Need to allocate memory to add in NULL terminator */
589 buffer = mbedtls_malloc(length + 1);
590 if (!buffer) {
591 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
592 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
593 }
594 memcpy(buffer, setup_data->pki_key.key.pem_buf.public_cert, length);
595 buffer[length] = '\000';
596 length++;
597 ret = mbedtls_x509_crt_parse(public_cert, buffer, length);
598 mbedtls_free(buffer);
599 }
600 else {
601 ret = mbedtls_x509_crt_parse(public_cert,
602 setup_data->pki_key.key.pem_buf.public_cert,
603 setup_data->pki_key.key.pem_buf.public_cert_len);
604 }
605 if (ret < 0) {
606 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
607 -ret, get_error_string(ret));
608 return ret;
609 }
610
611 length = setup_data->pki_key.key.pem_buf.private_key_len;
612 if (setup_data->pki_key.key.pem_buf.private_key[length-1] != '\000') {
613 /* Need to allocate memory to add in NULL terminator */
614 buffer = mbedtls_malloc(length + 1);
615 if (!buffer) {
616 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
617 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
618 }
619 memcpy(buffer, setup_data->pki_key.key.pem_buf.private_key, length);
620 buffer[length] = '\000';
621 length++;
622#ifdef MBEDTLS_2_X_COMPAT
623 ret = mbedtls_pk_parse_key(private_key, buffer, length, NULL, 0);
624#else
625 ret = mbedtls_pk_parse_key(private_key, buffer, length,
626 NULL, 0, coap_rng, (void *)&m_env->ctr_drbg);
627#endif /* MBEDTLS_2_X_COMPAT */
628 mbedtls_free(buffer);
629 }
630 else {
631#ifdef MBEDTLS_2_X_COMPAT
632 ret = mbedtls_pk_parse_key(private_key,
633 setup_data->pki_key.key.pem_buf.private_key,
634 setup_data->pki_key.key.pem_buf.private_key_len, NULL, 0);
635#else
636 ret = mbedtls_pk_parse_key(private_key,
637 setup_data->pki_key.key.pem_buf.private_key,
639 NULL, 0, coap_rng, (void *)&m_env->ctr_drbg);
640#endif /* MBEDTLS_2_X_COMPAT */
641 }
642 if (ret < 0) {
643 coap_log(LOG_ERR, "mbedtls_pk_parse_key returned -0x%x: '%s'\n",
644 -ret, get_error_string(ret));
645 return ret;
646 }
647
648 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
649 if (ret < 0) {
650 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
651 -ret, get_error_string(ret));
652 return ret;
653 }
654 } else if (role == COAP_DTLS_ROLE_SERVER) {
656 "***setup_pki: (D)TLS: No Server Certificate + Private "
657 "Key defined\n");
658 return -1;
659 }
660
661 if (setup_data->pki_key.key.pem_buf.ca_cert &&
662 setup_data->pki_key.key.pem_buf.ca_cert_len) {
663 uint8_t *buffer;
664 size_t length;
665
666 mbedtls_x509_crt_init(cacert);
667 length = setup_data->pki_key.key.pem_buf.ca_cert_len;
668 if (setup_data->pki_key.key.pem_buf.ca_cert[length-1] != '\000') {
669 /* Need to allocate memory to add in NULL terminator */
670 buffer = mbedtls_malloc(length + 1);
671 if (!buffer) {
672 coap_log(LOG_ERR, "mbedtls_malloc failed\n");
673 return MBEDTLS_ERR_SSL_ALLOC_FAILED;
674 }
675 memcpy(buffer, setup_data->pki_key.key.pem_buf.ca_cert, length);
676 buffer[length] = '\000';
677 length++;
678 ret = mbedtls_x509_crt_parse(cacert, buffer, length);
679 mbedtls_free(buffer);
680 }
681 else {
682 ret = mbedtls_x509_crt_parse(cacert,
683 setup_data->pki_key.key.pem_buf.ca_cert,
684 setup_data->pki_key.key.pem_buf.ca_cert_len);
685 }
686 if (ret < 0) {
687 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
688 -ret, get_error_string(ret));
689 return ret;
690 }
691 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
692 }
693 break;
695 if (setup_data->pki_key.key.asn1.public_cert &&
696 setup_data->pki_key.key.asn1.public_cert_len &&
697 setup_data->pki_key.key.asn1.private_key &&
698 setup_data->pki_key.key.asn1.private_key_len > 0) {
699
700 mbedtls_x509_crt_init(public_cert);
701 mbedtls_pk_init(private_key);
702 ret = mbedtls_x509_crt_parse(public_cert,
703 (const unsigned char *)setup_data->pki_key.key.asn1.public_cert,
704 setup_data->pki_key.key.asn1.public_cert_len);
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
711#ifdef MBEDTLS_2_X_COMPAT
712 ret = mbedtls_pk_parse_key(private_key,
713 (const unsigned char *)setup_data->pki_key.key.asn1.private_key,
714 setup_data->pki_key.key.asn1.private_key_len, NULL, 0);
715#else
716 ret = mbedtls_pk_parse_key(private_key,
717 (const unsigned char *)setup_data->pki_key.key.asn1.private_key,
718 setup_data->pki_key.key.asn1.private_key_len, NULL, 0, coap_rng,
719 (void *)&m_env->ctr_drbg);
720#endif /* MBEDTLS_2_X_COMPAT */
721 if (ret < 0) {
722 coap_log(LOG_ERR, "mbedtls_pk_parse_key returned -0x%x: '%s'\n",
723 -ret, get_error_string(ret));
724 return ret;
725 }
726
727 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
728 if (ret < 0) {
729 coap_log(LOG_ERR, "mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
730 -ret, get_error_string(ret));
731 return ret;
732 }
733 } else if (role == COAP_DTLS_ROLE_SERVER) {
735 "***setup_pki: (D)TLS: No Server Certificate + Private "
736 "Key defined\n");
737 return -1;
738 }
739
740 if (setup_data->pki_key.key.asn1.ca_cert &&
741 setup_data->pki_key.key.asn1.ca_cert_len > 0) {
742 mbedtls_x509_crt_init(cacert);
743 ret = mbedtls_x509_crt_parse(cacert,
744 (const unsigned char *)setup_data->pki_key.key.asn1.ca_cert,
745 setup_data->pki_key.key.asn1.ca_cert_len);
746 if (ret < 0) {
747 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
748 -ret, get_error_string(ret));
749 return ret;
750 }
751 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
752 }
753 break;
754
757 "***setup_pki: (D)TLS: PKCS11 not currently supported\n");
758 return -1;
759
760 default:
762 "***setup_pki: (D)TLS: Unknown key type %d\n",
763 setup_data->pki_key.key_type);
764 return -1;
765 }
766
767 if (m_context->root_ca_file) {
768 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file);
769 if (ret < 0) {
770 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
771 -ret, get_error_string(ret));
772 return ret;
773 }
774 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
775 }
776 if (m_context->root_ca_path) {
777 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_path);
778 if (ret < 0) {
779 coap_log(LOG_ERR, "mbedtls_x509_crt_parse returned -0x%x: '%s'\n",
780 -ret, get_error_string(ret));
781 return ret;
782 }
783 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
784 }
785
786#if defined(MBEDTLS_SSL_SRV_C)
787 mbedtls_ssl_conf_cert_req_ca_list(&m_env->conf,
788 setup_data->check_common_ca ?
789 MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED :
790 MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED);
791#endif
792 mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->verify_peer_cert ?
793 MBEDTLS_SSL_VERIFY_REQUIRED :
794 MBEDTLS_SSL_VERIFY_NONE);
795 /*
796 * Verify Peer.
797 * Need to do all checking, even if setup_data->verify_peer_cert is not set
798 */
799 mbedtls_ssl_conf_verify(&m_env->conf,
800 cert_verify_callback_mbedtls, c_session);
801
802 return 0;
803}
804
805#if defined(MBEDTLS_SSL_SRV_C)
806/*
807 * PKI SNI callback.
808 */
809static int
810pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
811 const unsigned char *uname, size_t name_len)
812{
813 unsigned int i;
814 coap_dtls_pki_t sni_setup_data;
815 coap_session_t *c_session = (coap_session_t *)p_info;
816 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
817 coap_mbedtls_context_t *m_context =
818 (coap_mbedtls_context_t *)c_session->context->dtls_context;
819 int ret = 0;
820 char *name;
821
822 name = mbedtls_malloc(name_len+1);
823 if (!name)
824 return -1;
825
826 memcpy(name, uname, name_len);
827 name[name_len] = '\000';
828
829 /* Is this a cached entry? */
830 for (i = 0; i < m_context->pki_sni_count; i++) {
831 if (strcasecmp(name, m_context->pki_sni_entry_list[i].sni) == 0) {
832 break;
833 }
834 }
835 if (i == m_context->pki_sni_count) {
836 /*
837 * New PKI SNI request
838 */
839 coap_dtls_key_t *new_entry;
840 pki_sni_entry *pki_sni_entry_list;
841
842 new_entry =
843 m_context->setup_data.validate_sni_call_back(name,
844 m_context->setup_data.sni_call_back_arg);
845 if (!new_entry) {
846 mbedtls_free(name);
847 return -1;
848 }
849
850 pki_sni_entry_list = mbedtls_realloc(m_context->pki_sni_entry_list,
851 (i+1)*sizeof(pki_sni_entry));
852
853 if (pki_sni_entry_list == NULL) {
854 mbedtls_free(name);
855 return -1;
856 }
857 m_context->pki_sni_entry_list = pki_sni_entry_list;
858 memset(&m_context->pki_sni_entry_list[i], 0,
859 sizeof(m_context->pki_sni_entry_list[i]));
860 m_context->pki_sni_entry_list[i].sni = name;
861 m_context->pki_sni_entry_list[i].pki_key = *new_entry;
862 sni_setup_data = m_context->setup_data;
863 sni_setup_data.pki_key = *new_entry;
864 if ((ret = setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert,
865 &m_context->pki_sni_entry_list[i].public_cert,
866 &m_context->pki_sni_entry_list[i].private_key,
867 m_env,
868 m_context,
869 c_session,
870 &sni_setup_data, COAP_DTLS_ROLE_SERVER)) < 0) {
871 mbedtls_free(name);
872 return -1;
873 }
874 /* name has been absorbed into pki_sni_entry_list[].sni entry */
875 m_context->pki_sni_count++;
876 }
877 else {
878 mbedtls_free(name);
879 }
880
881 mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert,
882 NULL);
883 return mbedtls_ssl_set_hs_own_cert(ssl,
884 &m_context->pki_sni_entry_list[i].public_cert,
885 &m_context->pki_sni_entry_list[i].private_key);
886}
887
888#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
889/*
890 * PSK SNI callback.
891 */
892static int
893psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
894 const unsigned char *uname, size_t name_len)
895{
896 unsigned int i;
897 coap_session_t *c_session = (coap_session_t *)p_info;
898 coap_mbedtls_context_t *m_context =
899 (coap_mbedtls_context_t *)c_session->context->dtls_context;
900 char *name;
901
902 name = mbedtls_malloc(name_len+1);
903 if (!name)
904 return -1;
905
906 memcpy(name, uname, name_len);
907 name[name_len] = '\000';
908
909 /* Is this a cached entry? */
910 for (i = 0; i < m_context->psk_sni_count; i++) {
911 if (strcasecmp(name, m_context->psk_sni_entry_list[i].sni) == 0) {
912 break;
913 }
914 }
915 if (i == m_context->psk_sni_count) {
916 /*
917 * New PSK SNI request
918 */
919 const coap_dtls_spsk_info_t *new_entry;
920 psk_sni_entry *psk_sni_entry_list;
921
922 new_entry =
924 c_session,
926 if (!new_entry) {
927 mbedtls_free(name);
928 return -1;
929 }
930
931 psk_sni_entry_list = mbedtls_realloc(m_context->psk_sni_entry_list,
932 (i+1)*sizeof(psk_sni_entry));
933
934 if (psk_sni_entry_list == NULL) {
935 mbedtls_free(name);
936 return -1;
937 }
938 m_context->psk_sni_entry_list = psk_sni_entry_list;
939 m_context->psk_sni_entry_list[i].sni = name;
940 m_context->psk_sni_entry_list[i].psk_info = *new_entry;
941 /* name has been absorbed into psk_sni_entry_list[].sni entry */
942 m_context->psk_sni_count++;
943 }
944 else {
945 mbedtls_free(name);
946 }
947
949 &m_context->psk_sni_entry_list[i].psk_info.hint);
951 &m_context->psk_sni_entry_list[i].psk_info.key);
952 return mbedtls_ssl_set_hs_psk(ssl,
953 m_context->psk_sni_entry_list[i].psk_info.key.s,
954 m_context->psk_sni_entry_list[i].psk_info.key.length);
955}
956#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
957
958static int setup_server_ssl_session(coap_session_t *c_session,
959 coap_mbedtls_env_t *m_env)
960{
961 coap_mbedtls_context_t *m_context =
962 (coap_mbedtls_context_t *)c_session->context->dtls_context;
963 int ret = 0;
964 m_context->psk_pki_enabled |= IS_SERVER;
965
966 mbedtls_ssl_cookie_init(&m_env->cookie_ctx);
967 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
968 MBEDTLS_SSL_IS_SERVER,
969 c_session->proto == COAP_PROTO_DTLS ?
970 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
971 MBEDTLS_SSL_TRANSPORT_STREAM,
972 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
973 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
974 -ret, get_error_string(ret));
975 goto fail;
976 }
977
978 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
979
980#if defined(MBEDTLS_SSL_PROTO_DTLS)
981 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
982 COAP_DTLS_RETRANSMIT_TOTAL_MS);
983#endif /* MBEDTLS_SSL_PROTO_DTLS */
984
985 if (m_context->psk_pki_enabled & IS_PSK) {
986#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
987 mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session);
989 mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session);
990 }
991#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
992 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
993#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
994 }
995
996 if (m_context->psk_pki_enabled & IS_PKI) {
997 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
998 &m_env->private_key, m_env, m_context,
999 c_session, &m_context->setup_data,
1001 if (ret < 0) {
1002 coap_log(LOG_ERR, "PKI setup failed\n");
1003 return ret;
1004 }
1005 if (m_context->setup_data.validate_sni_call_back) {
1006 mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session);
1007 }
1008 }
1009
1010 if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx,
1011 mbedtls_ctr_drbg_random,
1012 &m_env->ctr_drbg)) != 0) {
1013 coap_log(LOG_ERR, "mbedtls_ssl_cookie_setup: returned -0x%x: '%s'\n",
1014 -ret, get_error_string(ret));
1015 goto fail;
1016 }
1017
1018#if defined(MBEDTLS_SSL_PROTO_DTLS)
1019 mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write,
1020 mbedtls_ssl_cookie_check,
1021 &m_env->cookie_ctx );
1022#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1023 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1024#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1025#endif /* MBEDTLS_SSL_PROTO_DTLS */
1026fail:
1027 return ret;
1028}
1029#endif /* MBEDTLS_SSL_SRV_C */
1030
1031#if COAP_CLIENT_SUPPORT
1032static int *psk_ciphers = NULL;
1033static int *pki_ciphers = NULL;
1034static int processed_ciphers = 0;
1035
1036static void
1037set_ciphersuites(mbedtls_ssl_config *conf, coap_enc_method_t method)
1038{
1039 if (!processed_ciphers) {
1040 const int *list = mbedtls_ssl_list_ciphersuites();
1041 const int *base = list;
1042 int *psk_list;
1043 int *pki_list;
1044 int psk_count = 1; /* account for empty terminator */
1045 int pki_count = 1;
1046
1047 while (*list) {
1048 const mbedtls_ssl_ciphersuite_t *cur =
1049 mbedtls_ssl_ciphersuite_from_id(*list);
1050
1051 if (cur) {
1052 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1053 /* Minimum of TLS1.2 required - skip */
1054 }
1055#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1056 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
1057 psk_count++;
1058 }
1059#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1060 else {
1061 pki_count++;
1062 }
1063 }
1064 list++;
1065 }
1066 list = base;
1067
1068 psk_ciphers = mbedtls_malloc(psk_count * sizeof(psk_ciphers[0]));
1069 if (psk_ciphers == NULL) {
1070 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", psk_count);
1071 return;
1072 }
1073 pki_ciphers = mbedtls_malloc(pki_count * sizeof(pki_ciphers[0]));
1074 if (pki_ciphers == NULL) {
1075 coap_log(LOG_ERR, "set_ciphers: mbedtls_malloc with count %d failed\n", pki_count);
1076 mbedtls_free(psk_ciphers);
1077 psk_ciphers = NULL;
1078 return;
1079 }
1080
1081 psk_list = psk_ciphers;
1082 pki_list = pki_ciphers;
1083
1084 while (*list) {
1085 const mbedtls_ssl_ciphersuite_t *cur =
1086 mbedtls_ssl_ciphersuite_from_id(*list);
1087 if (cur) {
1088 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1089 /* Minimum of TLS1.2 required - skip */
1090 }
1091#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1092 else if (mbedtls_ssl_ciphersuite_uses_psk(cur)) {
1093 *psk_list = *list;
1094 psk_list++;
1095 }
1096#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1097 else {
1098 *pki_list = *list;
1099 pki_list++;
1100 }
1101 }
1102 list++;
1103 }
1104 /* zero terminate */
1105 *psk_list = 0;
1106 *pki_list = 0;
1107 processed_ciphers = 1;
1108 }
1109 mbedtls_ssl_conf_ciphersuites(conf, method == COAP_ENC_PSK ? psk_ciphers : pki_ciphers);
1110}
1111
1112static int setup_client_ssl_session(coap_session_t *c_session,
1113 coap_mbedtls_env_t *m_env)
1114{
1115 int ret;
1116
1117 coap_mbedtls_context_t *m_context =
1118 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1119
1120 m_context->psk_pki_enabled |= IS_CLIENT;
1121
1122 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
1123 MBEDTLS_SSL_IS_CLIENT,
1124 c_session->proto == COAP_PROTO_DTLS ?
1125 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
1126 MBEDTLS_SSL_TRANSPORT_STREAM,
1127 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
1128 coap_log(LOG_ERR, "mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
1129 -ret, get_error_string(ret));
1130 goto fail;
1131 }
1132
1133#if defined(MBEDTLS_SSL_PROTO_DTLS)
1134 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
1135 COAP_DTLS_RETRANSMIT_TOTAL_MS);
1136#endif /* MBEDTLS_SSL_PROTO_DTLS */
1137
1138 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
1139 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
1140
1141 if (m_context->psk_pki_enabled & IS_PSK) {
1142#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1143 const coap_bin_const_t *psk_key;
1144 const coap_bin_const_t *psk_identity;
1145
1146 coap_log(LOG_INFO, "Setting PSK key\n");
1147
1148 psk_key = coap_get_session_client_psk_key(c_session);
1149 psk_identity = coap_get_session_client_psk_identity(c_session);
1150 if (psk_key == NULL || psk_identity == NULL) {
1151 ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
1152 goto fail;
1153 }
1154
1155 if ((ret = mbedtls_ssl_conf_psk(&m_env->conf, psk_key->s,
1156 psk_key->length, psk_identity->s,
1157 psk_identity->length)) != 0) {
1158 coap_log(LOG_ERR, "mbedtls_ssl_conf_psk returned -0x%x: '%s'\n",
1159 -ret, get_error_string(ret));
1160 goto fail;
1161 }
1162 if (c_session->cpsk_setup_data.client_sni) {
1163 if ((ret = mbedtls_ssl_set_hostname(&m_env->ssl,
1164 c_session->cpsk_setup_data.client_sni)) != 0) {
1165 coap_log(LOG_ERR, "mbedtls_ssl_set_hostname returned -0x%x: '%s'\n",
1166 -ret, get_error_string(ret));
1167 goto fail;
1168 }
1169 }
1170 /* Identity Hint currently not supported in Mbed TLS so code removed */
1171
1172 set_ciphersuites(&m_env->conf, COAP_ENC_PSK);
1173#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1174 coap_log(LOG_WARNING, "PSK not enabled in Mbed TLS library\n");
1175#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1176 }
1177 else if ((m_context->psk_pki_enabled & IS_PKI) ||
1178 (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
1179 /*
1180 * If neither PSK or PKI have been set up, use PKI basics.
1181 * This works providing COAP_PKI_KEY_PEM has a value of 0.
1182 */
1183 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
1184 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
1185 &m_env->private_key, m_env, m_context,
1186 c_session, &m_context->setup_data,
1188 if (ret < 0) {
1189 coap_log(LOG_ERR, "PKI setup failed\n");
1190 return ret;
1191 }
1192#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN)
1193 if (c_session->proto == COAP_PROTO_TLS) {
1194 static const char *alpn_list[] = { "coap", NULL };
1195
1196 ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list);
1197 if (ret != 0) {
1198 coap_log(LOG_ERR, "ALPN setup failed %d)\n", ret);
1199 }
1200 }
1201#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN */
1202 if (m_context->setup_data.client_sni) {
1203 mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni);
1204 }
1205#if defined(MBEDTLS_SSL_PROTO_DTLS)
1206#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1207 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1208#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1209#endif /* MBEDTLS_SSL_PROTO_DTLS */
1210 set_ciphersuites(&m_env->conf, COAP_ENC_PKI);
1211 }
1212 return 0;
1213
1214fail:
1215 return ret;
1216}
1217#endif /* COAP_CLIENT_SUPPORT */
1218
1219static void mbedtls_cleanup(coap_mbedtls_env_t *m_env)
1220{
1221 if (!m_env) {
1222 return;
1223 }
1224
1225 mbedtls_x509_crt_free(&m_env->cacert);
1226 mbedtls_x509_crt_free(&m_env->public_cert);
1227 mbedtls_pk_free(&m_env->private_key);
1228 mbedtls_entropy_free(&m_env->entropy);
1229 mbedtls_ssl_config_free(&m_env->conf);
1230 mbedtls_ctr_drbg_free(&m_env->ctr_drbg);
1231 mbedtls_ssl_free(&m_env->ssl);
1232 mbedtls_ssl_cookie_free(&m_env->cookie_ctx);
1233}
1234
1235static void
1236coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) {
1237 if (m_env) {
1238 if (!m_env->sent_alert)
1239 mbedtls_ssl_close_notify(&m_env->ssl);
1240 mbedtls_cleanup(m_env);
1241 mbedtls_free(m_env);
1242 }
1243}
1244
1245static const char *
1246report_mbedtls_alert(unsigned char alert) {
1247 switch (alert) {
1248 case MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC: return ": Bad Record MAC";
1249 case MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE: return ": Handshake failure";
1250 case MBEDTLS_SSL_ALERT_MSG_NO_CERT: return ": No Certificate provided";
1251 case MBEDTLS_SSL_ALERT_MSG_BAD_CERT: return ": Certificate is bad";
1252 case MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA: return ": CA is unknown";
1253 case MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED: return ": Access was denied";
1254 case MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR: return ": Decrypt error";
1255 default: return "";
1256 }
1257}
1258
1259/*
1260 * return -1 failure
1261 * 0 not completed
1262 * 1 established
1263 */
1264static int do_mbedtls_handshake(coap_session_t *c_session,
1265 coap_mbedtls_env_t *m_env) {
1266 int ret;
1267 int alert;
1268
1269 ret = mbedtls_ssl_handshake(&m_env->ssl);
1270 switch (ret) {
1271 case 0:
1272 m_env->established = 1;
1273 coap_log(LOG_DEBUG, "* %s: Mbed TLS established\n",
1274 coap_session_str(c_session));
1275 ret = 1;
1276 break;
1277 case MBEDTLS_ERR_SSL_WANT_READ:
1278 case MBEDTLS_ERR_SSL_WANT_WRITE:
1279 errno = EAGAIN;
1280 ret = 0;
1281 break;
1282 case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
1283 coap_log(LOG_DEBUG, "hello verification requested\n");
1284 goto reset;
1285 case MBEDTLS_ERR_SSL_INVALID_MAC:
1286 goto fail;
1287 case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
1288 alert = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
1289 goto fail_alert;
1290#ifdef MBEDTLS_2_X_COMPAT
1291 case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
1292 case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO:
1293 alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE;
1294 goto fail_alert;
1295#endif /* MBEDTLS_2_X_COMPAT */
1296 case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
1297 goto fail;
1298 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1299 if (m_env->ssl.in_msg[1] != MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
1300 coap_log(LOG_WARNING, "***%s: Alert '%d'%s\n",
1301 coap_session_str(c_session), m_env->ssl.in_msg[1],
1302 report_mbedtls_alert(m_env->ssl.in_msg[1]));
1303 /* Fall through */
1304 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1305 case MBEDTLS_ERR_SSL_CONN_EOF:
1306 case MBEDTLS_ERR_NET_CONN_RESET:
1308 ret = -1;
1309 break;
1310 default:
1312 "do_mbedtls_handshake: session establish "
1313 "returned -0x%x: '%s'\n",
1314 -ret, get_error_string(ret));
1315 ret = -1;
1316 break;
1317 }
1318 return ret;
1319
1320fail_alert:
1321 mbedtls_ssl_send_alert_message(&m_env->ssl,
1322 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
1323 alert);
1324 m_env->sent_alert = 1;
1325fail:
1326 c_session->dtls_event = COAP_EVENT_DTLS_ERROR;
1328 "do_mbedtls_handshake: session establish "
1329 "returned '%s'\n",
1330 get_error_string(ret));
1331reset:
1332 mbedtls_ssl_session_reset(&m_env->ssl);
1333 return -1;
1334}
1335
1336static void
1337mbedtls_debug_out(void *ctx COAP_UNUSED, int level,
1338 const char *file, int line, const char *str) {
1339 int log_level;
1340 /*
1341 * 0 No debug
1342 * 1 Error
1343 * 2 State change
1344 * 3 Informational
1345 * 4 Verbose
1346 */
1347 switch (level) {
1348 case 4:
1349 case 3:
1350 case 2:
1351 log_level = COAP_LOG_CIPHERS;
1352 break;
1353 case 1:
1354 log_level = LOG_ERR;
1355 break;
1356 case 0:
1357 default:
1358 log_level = 0;
1359 break;
1360 }
1361 coap_log(log_level, "%s:%04d: %s", file, line, str);
1362}
1363
1364#if !COAP_DISABLE_TCP
1365/*
1366 * return +ve data amount
1367 * 0 no more
1368 * -ve Mbed TLS error
1369 */
1370static int
1371coap_sock_read(void *ctx, unsigned char *out, size_t outl) {
1372 ssize_t ret = MBEDTLS_ERR_SSL_CONN_EOF;
1373 coap_session_t *c_session = (coap_session_t *)ctx;
1374
1375 if (out != NULL) {
1376#ifdef _WIN32
1377 ret = recv(c_session->sock.fd, (char *)out, (int)outl, 0);
1378#else
1379 ret = recv(c_session->sock.fd, out, outl, 0);
1380#endif
1381 if (ret > 0) {
1382 coap_log(LOG_DEBUG, "* %s: received %zd bytes\n",
1383 coap_session_str(c_session), ret);
1384 } else if (ret < 0 && errno != EAGAIN) {
1385 coap_log(LOG_DEBUG, "* %s: failed to receive any bytes (%s)\n",
1387 }
1388
1389 if (ret == 0) {
1390 /* graceful shutdown */
1391 c_session->sock.flags &= ~COAP_SOCKET_CAN_READ;
1392 ret = MBEDTLS_ERR_SSL_CONN_EOF;
1393 }
1394 else if (ret == COAP_SOCKET_ERROR) {
1395#ifdef _WIN32
1396 int lasterror = WSAGetLastError();
1397
1398 if (lasterror == WSAEWOULDBLOCK) {
1399 ret = MBEDTLS_ERR_SSL_WANT_READ;
1400 }
1401 else if (lasterror == WSAECONNRESET) {
1402 ret = MBEDTLS_ERR_NET_CONN_RESET;
1403 }
1404#else
1405 if (errno == EAGAIN) {
1406 ret = MBEDTLS_ERR_SSL_WANT_READ;
1407 }
1408 else if (errno == EPIPE || errno == ECONNRESET) {
1409 ret = MBEDTLS_ERR_NET_CONN_RESET;
1410 }
1411#endif
1412 else {
1413 ret = MBEDTLS_ERR_NET_RECV_FAILED;
1414 }
1415 c_session->sock.flags &= ~COAP_SOCKET_CAN_READ;
1416 }
1417 else if (ret < (ssize_t)outl) {
1418 c_session->sock.flags &= ~COAP_SOCKET_CAN_READ;
1419 }
1420 }
1421 return (int)ret;
1422}
1423
1424/*
1425 * return +ve data amount
1426 * 0 no more
1427 * -ve Mbed TLS error
1428 */
1429static int
1430coap_sock_write(void *context, const unsigned char *in, size_t inl) {
1431 int ret = 0;
1432 coap_session_t *c_session = (coap_session_t *)context;
1433
1434 ret = (int)coap_socket_write(&c_session->sock, in, inl);
1435 if (ret > 0) {
1436 coap_log(LOG_DEBUG, "* %s: sent %d bytes\n",
1437 coap_session_str(c_session), ret);
1438 } else if (ret < 0) {
1439 if ((c_session->state == COAP_SESSION_STATE_CSM ||
1440 c_session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1441 (errno == EPIPE || errno == ECONNRESET)) {
1442 /*
1443 * Need to handle a TCP timing window where an agent continues with
1444 * the sending of the next handshake or a CSM.
1445 * However, the peer does not like a certificate and so sends a
1446 * fatal alert and closes the TCP session.
1447 * The sending of the next handshake or CSM may get terminated because
1448 * of the closed TCP session, but there is still an outstanding alert
1449 * to be read in and reported on.
1450 * In this case, pretend that sending the info was fine so that the
1451 * alert can be read (which effectively is what happens with DTLS).
1452 */
1453 ret = inl;
1454 }
1455 else {
1456#ifdef _WIN32
1457 int lasterror = WSAGetLastError();
1458
1459 if (lasterror == WSAEWOULDBLOCK) {
1460 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1461 }
1462 else if (lasterror == WSAECONNRESET) {
1463 ret = MBEDTLS_ERR_NET_CONN_RESET;
1464 }
1465#else
1466 if (errno == EAGAIN || errno == EINTR) {
1467 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1468 }
1469 else if (errno == EPIPE || errno == ECONNRESET) {
1470 ret = MBEDTLS_ERR_NET_CONN_RESET;
1471 }
1472#endif
1473 else {
1474 ret = MBEDTLS_ERR_NET_SEND_FAILED;
1475 }
1476 coap_log(LOG_DEBUG, "* %s: failed to send %zd bytes (%s) state %d\n",
1477 coap_session_str(c_session), inl, coap_socket_strerror(),
1478 c_session->state);
1479 }
1480 }
1481 if (ret == 0) {
1482 errno = EAGAIN;
1483 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1484 }
1485 return ret;
1486}
1487#endif /* !COAP_DISABLE_TCP */
1488
1489static coap_mbedtls_env_t *coap_dtls_new_mbedtls_env(coap_session_t *c_session,
1490 coap_dtls_role_t role,
1491 coap_proto_t proto)
1492{
1493 int ret = 0;
1494 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1495
1496 if (m_env)
1497 return m_env;
1498
1499 m_env = (coap_mbedtls_env_t *)mbedtls_malloc(sizeof(coap_mbedtls_env_t));
1500 if (!m_env) {
1501 return NULL;
1502 }
1503 memset(m_env, 0, sizeof(coap_mbedtls_env_t));
1504
1505 mbedtls_ssl_init(&m_env->ssl);
1506 mbedtls_ctr_drbg_init(&m_env->ctr_drbg);
1507 mbedtls_ssl_config_init(&m_env->conf);
1508 mbedtls_entropy_init(&m_env->entropy);
1509
1510#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
1511 mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL);
1512#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
1513 if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg,
1514 mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) {
1515 coap_log(LOG_ERR, "mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n",
1516 -ret, get_error_string(ret));
1517 goto fail;
1518 }
1519
1520 if (role == COAP_DTLS_ROLE_CLIENT) {
1521#if COAP_CLIENT_SUPPORT
1522 if (setup_client_ssl_session(c_session, m_env) != 0) {
1523 goto fail;
1524 }
1525#else /* !COAP_CLIENT_SUPPORT */
1526 goto fail;
1527#endif /* !COAP_CLIENT_SUPPORT */
1528 } else if (role == COAP_DTLS_ROLE_SERVER) {
1529#if defined(MBEDTLS_SSL_SRV_C)
1530 if (setup_server_ssl_session(c_session, m_env) != 0) {
1531 goto fail;
1532 }
1533#else /* ! MBEDTLS_SSL_SRV_C */
1534 goto fail;
1535#endif /* ! MBEDTLS_SSL_SRV_C */
1536 } else {
1537 goto fail;
1538 }
1539
1540 mbedtls_ssl_conf_min_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
1541 MBEDTLS_SSL_MINOR_VERSION_3);
1542
1543 if ((ret = mbedtls_ssl_setup(&m_env->ssl, &m_env->conf)) != 0) {
1544 goto fail;
1545 }
1546 if (proto == COAP_PROTO_DTLS) {
1547 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write,
1548 coap_dgram_read, NULL);
1549 }
1550#if !COAP_DISABLE_TCP
1551 else {
1552 assert(proto == COAP_PROTO_TLS);
1553 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_sock_write,
1554 coap_sock_read, NULL);
1555 }
1556#endif /* ! COAP_DISABLE_TCP */
1557 mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer,
1558 mbedtls_timing_set_delay,
1559 mbedtls_timing_get_delay);
1560
1561 mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout);
1562 return m_env;
1563
1564fail:
1565 if (m_env) {
1566 mbedtls_free(m_env);
1567 }
1568 return NULL;
1569}
1570
1571int coap_dtls_is_supported(void) {
1572#if defined(MBEDTLS_SSL_PROTO_DTLS)
1573 return 1;
1574#else /* !MBEDTLS_SSL_PROTO_DTLS */
1575 static int reported = 0;
1576 if (!reported) {
1577 reported = 1;
1579 "libcoap not compiled for DTLS with Mbed TLS"
1580 " - update Mbed TLS to include DTLS\n");
1581 }
1582 return 0;
1583#endif /* !MBEDTLS_SSL_PROTO_DTLS */
1584}
1585
1586int coap_tls_is_supported(void)
1587{
1588#if !COAP_DISABLE_TCP
1589 return 1;
1590#else /* COAP_DISABLE_TCP */
1591 return 0;
1592#endif /* COAP_DISABLE_TCP */
1593}
1594
1595void *coap_dtls_new_context(coap_context_t *c_context)
1596{
1597 coap_mbedtls_context_t *m_context;
1598 (void)c_context;
1599
1600 m_context = (coap_mbedtls_context_t *)mbedtls_malloc(sizeof(coap_mbedtls_context_t));
1601 if (m_context) {
1602 memset(m_context, 0, sizeof(coap_mbedtls_context_t));
1603 }
1604 return m_context;
1605}
1606
1607#if COAP_SERVER_SUPPORT
1608/*
1609 * return 0 failed
1610 * 1 passed
1611 */
1612int
1614 coap_dtls_spsk_t *setup_data
1615) {
1616 coap_mbedtls_context_t *m_context =
1617 ((coap_mbedtls_context_t *)c_context->dtls_context);
1618
1619#if !defined(MBEDTLS_SSL_SRV_C)
1620 coap_log(LOG_EMERG, "coap_context_set_spsk:"
1621 " libcoap not compiled for Server Mode for Mbed TLS"
1622 " - update Mbed TLS to include Server Mode\n");
1623 return 0;
1624#endif /* !MBEDTLS_SSL_SRV_C */
1625 if (!m_context || !setup_data)
1626 return 0;
1627
1628 m_context->psk_pki_enabled |= IS_PSK;
1629 return 1;
1630}
1631#endif /* COAP_SERVER_SUPPORT */
1632
1633#if COAP_CLIENT_SUPPORT
1634/*
1635 * return 0 failed
1636 * 1 passed
1637 */
1638int
1640 coap_dtls_cpsk_t *setup_data
1641) {
1642#if !defined(MBEDTLS_SSL_CLI_C)
1643 coap_log(LOG_EMERG, "coap_context_set_cpsk:"
1644 " libcoap not compiled for Client Mode for Mbed TLS"
1645 " - update Mbed TLS to include Client Mode\n");
1646 return 0;
1647#else /* MBEDTLS_SSL_CLI_C */
1648 coap_mbedtls_context_t *m_context =
1649 ((coap_mbedtls_context_t *)c_context->dtls_context);
1650
1651 if (!m_context || !setup_data)
1652 return 0;
1653
1654 if (setup_data->validate_ih_call_back) {
1656 "CoAP Client with Mbed TLS does not support Identity Hint selection\n");
1657 }
1658 m_context->psk_pki_enabled |= IS_PSK;
1659 return 1;
1660#endif /* MBEDTLS_SSL_CLI_C */
1661}
1662#endif /* COAP_CLIENT_SUPPORT */
1663
1665 const coap_dtls_pki_t *setup_data,
1666 const coap_dtls_role_t role COAP_UNUSED)
1667{
1668 coap_mbedtls_context_t *m_context =
1669 ((coap_mbedtls_context_t *)c_context->dtls_context);
1670
1671 m_context->setup_data = *setup_data;
1672 if (!m_context->setup_data.verify_peer_cert) {
1673 /* Needs to be clear so that no CA DNs are transmitted */
1674 m_context->setup_data.check_common_ca = 0;
1675 /* Allow all of these but warn if issue */
1676 m_context->setup_data.allow_self_signed = 1;
1677 m_context->setup_data.allow_expired_certs = 1;
1678 m_context->setup_data.cert_chain_validation = 1;
1679 m_context->setup_data.cert_chain_verify_depth = 10;
1680 m_context->setup_data.check_cert_revocation = 1;
1681 m_context->setup_data.allow_no_crl = 1;
1682 m_context->setup_data.allow_expired_crl = 1;
1683 m_context->setup_data.allow_bad_md_hash = 1;
1684 m_context->setup_data.allow_short_rsa_length = 1;
1685 }
1686 m_context->psk_pki_enabled |= IS_PKI;
1687 return 1;
1688}
1689
1691 const char *ca_file,
1692 const char *ca_path)
1693{
1694 coap_mbedtls_context_t *m_context =
1695 ((coap_mbedtls_context_t *)c_context->dtls_context);
1696
1697 if (!m_context) {
1699 "coap_context_set_pki_root_cas: (D)TLS environment "
1700 "not set up\n");
1701 return 0;
1702 }
1703
1704 if (ca_file == NULL && ca_path == NULL) {
1706 "coap_context_set_pki_root_cas: ca_file and/or ca_path "
1707 "not defined\n");
1708 return 0;
1709 }
1710 if (m_context->root_ca_file) {
1711 mbedtls_free(m_context->root_ca_file);
1712 m_context->root_ca_file = NULL;
1713 }
1714
1715 if (ca_file) {
1716 m_context->root_ca_file = mbedtls_strdup(ca_file);
1717 }
1718
1719 if (m_context->root_ca_path) {
1720 mbedtls_free(m_context->root_ca_path);
1721 m_context->root_ca_path = NULL;
1722 }
1723
1724 if (ca_path) {
1725 m_context->root_ca_path = mbedtls_strdup(ca_path);
1726 }
1727 return 1;
1728}
1729
1731{
1732 coap_mbedtls_context_t *m_context =
1733 ((coap_mbedtls_context_t *)c_context->dtls_context);
1734 return m_context->psk_pki_enabled ? 1 : 0;
1735}
1736
1737void coap_dtls_free_context(void *dtls_context)
1738{
1739 coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context;
1740 unsigned int i;
1741
1742 for (i = 0; i < m_context->pki_sni_count; i++) {
1743 mbedtls_free(m_context->pki_sni_entry_list[i].sni);
1744
1745 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert);
1746
1747 mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key);
1748
1749 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert);
1750 }
1751 if (m_context->pki_sni_entry_list)
1752 mbedtls_free(m_context->pki_sni_entry_list);
1753
1754 for (i = 0; i < m_context->psk_sni_count; i++) {
1755 mbedtls_free(m_context->psk_sni_entry_list[i].sni);
1756 }
1757 if (m_context->psk_sni_entry_list)
1758 mbedtls_free(m_context->psk_sni_entry_list);
1759
1760 if (m_context->root_ca_path)
1761 mbedtls_free(m_context->root_ca_path);
1762 if (m_context->root_ca_file)
1763 mbedtls_free(m_context->root_ca_file);
1764
1765 mbedtls_free(m_context);
1766}
1767
1768#if COAP_CLIENT_SUPPORT
1770{
1771#if !defined(MBEDTLS_SSL_CLI_C)
1772 (void)c_session;
1773 coap_log(LOG_EMERG, "coap_dtls_new_client_session:"
1774 " libcoap not compiled for Client Mode for Mbed TLS"
1775 " - update Mbed TLS to include Client Mode\n");
1776 return NULL;
1777#else /* MBEDTLS_SSL_CLI_C */
1778 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
1781 int ret;
1782
1783 if (m_env) {
1784 coap_tick_t now;
1785 coap_ticks(&now);
1786 m_env->last_timeout = now;
1787 ret = do_mbedtls_handshake(c_session, m_env);
1788 if (ret == -1) {
1789 coap_dtls_free_mbedtls_env(m_env);
1790 return NULL;
1791 }
1792 }
1793 return m_env;
1794#endif /* MBEDTLS_SSL_CLI_C */
1795}
1796#endif /* COAP_CLIENT_SUPPORT */
1797
1798#if COAP_SERVER_SUPPORT
1800{
1801#if !defined(MBEDTLS_SSL_SRV_C)
1802 (void)c_session;
1803 coap_log(LOG_EMERG, "coap_dtls_new_server_session:"
1804 " libcoap not compiled for Server Mode for Mbed TLS"
1805 " - update Mbed TLS to include Server Mode\n");
1806 return NULL;
1807#else /* MBEDTLS_SSL_SRV_C */
1808 coap_mbedtls_env_t *m_env =
1809 (coap_mbedtls_env_t *)c_session->tls;
1810 if (m_env) {
1811#if defined(MBEDTLS_SSL_PROTO_DTLS)
1812#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1813 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1814#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1815#endif /* MBEDTLS_SSL_PROTO_DTLS */
1816 }
1817 return m_env;
1818#endif /* MBEDTLS_SSL_SRV_C */
1819}
1820#endif /* COAP_SERVER_SUPPORT */
1821
1823{
1824 if (c_session && c_session->context && c_session->tls) {
1825 coap_dtls_free_mbedtls_env(c_session->tls);
1826 c_session->tls = NULL;
1827 coap_handle_event(c_session->context, COAP_EVENT_DTLS_CLOSED, c_session);
1828 }
1829 return;
1830}
1831
1833{
1834#if defined(MBEDTLS_SSL_PROTO_DTLS)
1835 coap_mbedtls_env_t *m_env =
1836 (coap_mbedtls_env_t *)c_session->tls;
1837 if (m_env) {
1838#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1839 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1840#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1841 }
1842#else /* ! MBEDTLS_SSL_PROTO_DTLS */
1843 (void)c_session;
1844#endif /* MBEDTLS_SSL_PROTO_DTLS */
1845}
1846
1847int coap_dtls_send(coap_session_t *c_session,
1848 const uint8_t *data,
1849 size_t data_len)
1850{
1851 int ret;
1852 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1853
1854 assert(m_env != NULL);
1855
1856 if (!m_env) {
1857 return -1;
1858 }
1859 c_session->dtls_event = -1;
1860 if (m_env->established) {
1861 ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len);
1862 if (ret <= 0) {
1863 switch (ret) {
1864 case MBEDTLS_ERR_SSL_WANT_READ:
1865 case MBEDTLS_ERR_SSL_WANT_WRITE:
1866 ret = 0;
1867 break;
1868 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1870 ret = -1;
1871 break;
1872 default:
1874 "coap_dtls_send: "
1875 "returned -0x%x: '%s'\n",
1876 -ret, get_error_string(ret));
1877 ret = -1;
1878 break;
1879 }
1880 if (ret == -1) {
1881 coap_log(LOG_WARNING, "coap_dtls_send: cannot send PDU\n");
1882 }
1883 }
1884 } else {
1885 ret = do_mbedtls_handshake(c_session, m_env);
1886 if (ret == 1) {
1887 /* Just connected, so send the data */
1888 return coap_dtls_send(c_session, data, data_len);
1889 }
1890 ret = -1;
1891 }
1892
1893 if (c_session->dtls_event >= 0) {
1894 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
1895 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
1896 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
1897 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
1898 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
1900 ret = -1;
1901 }
1902 }
1903 return ret;
1904}
1905
1907{
1908 return 0;
1909}
1910
1912{
1913 return 0;
1914}
1915
1917{
1918 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1919 int ret = mbedtls_timing_get_delay(&m_env->timer);
1920 unsigned int scalar = 1 << m_env->retry_scalar;
1921
1922 assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1923 switch (ret) {
1924 case 0:
1925 /* int_ms has not timed out */
1926 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1927 /* Need to indicate remaining timeout time */
1928 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1929 }
1930 m_env->last_timeout = now;
1931 /* This may cause a minor extra delay */
1932 return now + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1933 case 1:
1934 /* int_ms has timed out, but not fin_ms */
1935 /*
1936 * Need to make sure that we do not do this too frequently
1937 */
1938 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
1939 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
1940 }
1941
1942 /* Reset for the next time */
1943 m_env->last_timeout = now;
1944 return now;
1945 case 2:
1946 /* fin_ms has timed out - timed out - one final try */
1947 return now;
1948 default:
1949 break;
1950 }
1951
1952 return 0;
1953}
1954
1955/*
1956 * return 1 timed out
1957 * 0 still timing out
1958 */
1959int
1961{
1962 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1963
1964 assert(m_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE);
1965 m_env->retry_scalar++;
1966 if ((++c_session->dtls_timeout_count > c_session->max_retransmit) ||
1967 (do_mbedtls_handshake(c_session, m_env) < 0)) {
1968 /* Too many retries */
1970 return 1;
1971 }
1972 return 0;
1973}
1974
1975/*
1976 * return +ve data amount
1977 * 0 no more
1978 * -1 error
1979 */
1980int coap_dtls_receive(coap_session_t *c_session,
1981 const uint8_t *data,
1982 size_t data_len)
1983{
1984 int ret = 1;
1985
1986 c_session->dtls_event = -1;
1987 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1988 coap_ssl_t *ssl_data;
1989
1990 assert(m_env != NULL);
1991
1992 ssl_data = &m_env->coap_ssl_data;
1993 if (ssl_data->pdu_len) {
1994 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
1995 coap_session_str(c_session), ssl_data->pdu_len);
1996 }
1997 ssl_data->pdu = data;
1998 ssl_data->pdu_len = (unsigned)data_len;
1999
2000 if (m_env->established) {
2001#if COAP_CONSTRAINED_STACK
2002 static coap_mutex_t b_static_mutex = COAP_MUTEX_INITIALIZER;
2003 static uint8_t pdu[COAP_RXBUFFER_SIZE];
2004#else /* ! COAP_CONSTRAINED_STACK */
2005 uint8_t pdu[COAP_RXBUFFER_SIZE];
2006#endif /* ! COAP_CONSTRAINED_STACK */
2007
2008#if COAP_CONSTRAINED_STACK
2009 coap_mutex_lock(&b_static_mutex);
2010#endif /* COAP_CONSTRAINED_STACK */
2011
2012 if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) {
2014 c_session);
2015 coap_session_connected(c_session);
2016 }
2017
2018 ret = mbedtls_ssl_read(&m_env->ssl, pdu, sizeof(pdu));
2019 if (ret > 0) {
2020 ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret);
2021#if COAP_CONSTRAINED_STACK
2022 coap_mutex_unlock(&b_static_mutex);
2023#endif /* COAP_CONSTRAINED_STACK */
2024 goto finish;
2025 }
2026 switch (ret) {
2027 case 0:
2028 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
2029 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2031 break;
2032 case MBEDTLS_ERR_SSL_WANT_READ:
2033 break;
2034 default:
2036 "coap_dtls_receive: "
2037 "returned -0x%x: '%s' (length %zd)\n",
2038 -ret, get_error_string(ret), data_len);
2039 break;
2040 }
2041#if COAP_CONSTRAINED_STACK
2042 coap_mutex_unlock(&b_static_mutex);
2043#endif /* COAP_CONSTRAINED_STACK */
2044 ret = -1;
2045 }
2046 else {
2047 ret = do_mbedtls_handshake(c_session, m_env);
2048 if (ret == 1) {
2049 /* Just connected, so send the data */
2050 coap_session_connected(c_session);
2051 } else {
2052 if (ssl_data->pdu_len) {
2053 /* Do the handshake again incase of internal timeout */
2054 ret = do_mbedtls_handshake(c_session, m_env);
2055 if (ret == 1) {
2056 /* Just connected, so send the data */
2057 coap_session_connected(c_session);
2058 } else {
2059 ret = -1;
2060 }
2061 }
2062 ret = -1;
2063 }
2064 }
2065 if (c_session->dtls_event >= 0) {
2066 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
2067 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2068 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
2069 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2070 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2072 ssl_data = NULL;
2073 ret = -1;
2074 }
2075 }
2076finish:
2077 if (ssl_data && ssl_data->pdu_len) {
2078 /* pdu data is held on stack which will not stay there */
2079 coap_log(LOG_DEBUG, "coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
2080 ssl_data->pdu_len = 0;
2081 ssl_data->pdu = NULL;
2082 }
2083 return ret;
2084}
2085
2086#if COAP_SERVER_SUPPORT
2087/*
2088 * return -1 failure
2089 * 0 not completed
2090 * 1 client hello seen
2091 */
2092int coap_dtls_hello(coap_session_t *c_session,
2093 const uint8_t *data,
2094 size_t data_len)
2095{
2096#if !defined(MBEDTLS_SSL_PROTO_DTLS) || !defined(MBEDTLS_SSL_SRV_C)
2097 (void)c_session;
2098 (void)data;
2099 (void)data_len;
2100 coap_log(LOG_EMERG, "coap_dtls_hello:"
2101 " libcoap not compiled for DTLS or Server Mode for Mbed TLS"
2102 " - update Mbed TLS to include DTLS and Server Mode\n");
2103 return -1;
2104#else /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
2105 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2106 coap_ssl_t *ssl_data;
2107 int ret;
2108
2109 if (!m_env) {
2110 m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER,
2112 if (m_env) {
2113 c_session->tls = m_env;
2114 }
2115 else {
2116 /* error should have already been reported */
2117 return -1;
2118 }
2119 }
2120
2121 if((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl,
2122 (unsigned char *)&c_session->addr_info.remote,
2123 sizeof(c_session->addr_info.remote))) != 0) {
2125 "mbedtls_ssl_set_client_transport_id() returned -0x%x: '%s'\n",
2126 -ret, get_error_string(ret));
2127 return -1;
2128 }
2129
2130 ssl_data = &m_env->coap_ssl_data;
2131 if (ssl_data->pdu_len) {
2132 coap_log(LOG_ERR, "** %s: Previous data not read %u bytes\n",
2133 coap_session_str(c_session), ssl_data->pdu_len);
2134 }
2135 ssl_data->pdu = data;
2136 ssl_data->pdu_len = (unsigned)data_len;
2137
2138 ret = do_mbedtls_handshake(c_session, m_env);
2139 if (ret == 0 || m_env->seen_client_hello) {
2140 /* The test for seen_client_hello gives the ability to setup a new
2141 c_session to continue the do_mbedtls_handshake past the client hello
2142 and safely allow updating of the m_env and separately
2143 letting a new session cleanly start up.
2144 */
2145 m_env->seen_client_hello = 0;
2146 ret = 1;
2147 }
2148 else {
2149 ret = 0;
2150 }
2151
2152 if (ssl_data->pdu_len) {
2153 /* pdu data is held on stack which will not stay there */
2154 coap_log(LOG_DEBUG, "coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
2155 ssl_data->pdu_len = 0;
2156 ssl_data->pdu = NULL;
2157 }
2158 return ret;
2159#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
2160}
2161#endif /* COAP_SERVER_SUPPORT */
2162
2163unsigned int coap_dtls_get_overhead(coap_session_t *c_session)
2164{
2165 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2166 int expansion = mbedtls_ssl_get_record_expansion(&m_env->ssl);
2167
2168 if (expansion == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
2169 return 13 + 8 + 8;
2170 }
2171 return expansion;
2172}
2173
2174#if !COAP_DISABLE_TCP
2175#if COAP_CLIENT_SUPPORT
2177 int *connected)
2178{
2179#if !defined(MBEDTLS_SSL_CLI_C)
2180 (void)c_session;
2181 *connected = 0;
2182 coap_log(LOG_EMERG, "coap_tls_new_client_session:"
2183 " libcoap not compiled for Client Mode for Mbed TLS"
2184 " - update Mbed TLS to include Client Mode\n");
2185 return NULL;
2186#else /* MBEDTLS_SSL_CLI_C */
2187 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
2190 int ret;
2191 coap_tick_t now;
2192 coap_ticks(&now);
2193
2194 *connected = 0;
2195 if (!m_env)
2196 return NULL;
2197
2198 m_env->last_timeout = now;
2199 c_session->tls = m_env;
2200 ret = do_mbedtls_handshake(c_session, m_env);
2201 if (ret == 1) {
2202 *connected = 1;
2203 coap_handle_event(c_session->context, COAP_EVENT_DTLS_CONNECTED, c_session);
2204 coap_session_send_csm(c_session);
2205 }
2206 return m_env;
2207#endif /* MBEDTLS_SSL_CLI_C */
2208}
2209#endif /* COAP_CLIENT_SUPPORT */
2210
2211#if COAP_SERVER_SUPPORT
2213 int *connected COAP_UNUSED)
2214{
2215#if !defined(MBEDTLS_SSL_SRV_C)
2216 (void)c_session;
2217 coap_log(LOG_EMERG, "coap_tls_new_server_session:"
2218 " libcoap not compiled for Server Mode for Mbed TLS"
2219 " - update Mbed TLS to include Server Mode\n");
2220 return NULL;
2221#else /* MBEDTLS_SSL_SRV_C */
2222 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
2225 int ret;
2226
2227 c_session->tls = m_env;
2228 ret = do_mbedtls_handshake(c_session, m_env);
2229 if (ret == 1) {
2230 *connected = 1;
2231 }
2232 return m_env;
2233#endif /* MBEDTLS_SSL_SRV_C */
2234}
2235#endif /* COAP_SERVER_SUPPORT */
2236
2238{
2239 coap_dtls_free_session(c_session);
2240 return;
2241}
2242
2243/*
2244 * return +ve data amount
2245 * 0 no more
2246 * -1 error (error in errno)
2247 */
2248ssize_t coap_tls_write(coap_session_t *c_session,
2249 const uint8_t *data,
2250 size_t data_len
2251 )
2252{
2253 int ret;
2254 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2255
2256 assert(m_env != NULL);
2257
2258 if (!m_env) {
2259 return -1;
2260 }
2261 c_session->dtls_event = -1;
2262 if (m_env->established) {
2263 ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char*) data, data_len);
2264 if (ret <= 0) {
2265 switch (ret) {
2266 case MBEDTLS_ERR_SSL_WANT_READ:
2267 case MBEDTLS_ERR_SSL_WANT_WRITE:
2268 ret = 0;
2269 break;
2270 case MBEDTLS_ERR_NET_CONN_RESET:
2271 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2273 ret = -1;
2274 break;
2275 default:
2277 "coap_tls_write: "
2278 "returned -0x%x: '%s'\n",
2279 -ret, get_error_string(ret));
2280 ret = -1;
2281 break;
2282 }
2283 if (ret == -1) {
2284 coap_log(LOG_WARNING, "coap_tls_write: cannot send PDU\n");
2285 }
2286 }
2287 } else {
2288 ret = do_mbedtls_handshake(c_session, m_env);
2289 if (ret == 1) {
2291 c_session);
2292 coap_session_send_csm(c_session);
2293 }
2294 else {
2295 ret = -1;
2296 }
2297 }
2298
2299 if (c_session->dtls_event >= 0) {
2300 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
2301 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2302 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
2303 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2304 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2306 ret = -1;
2307 }
2308 }
2309 return ret;
2310}
2311
2312/*
2313 * return +ve data amount
2314 * 0 no more
2315 * -1 error (error in errno)
2316 */
2317ssize_t coap_tls_read(coap_session_t *c_session,
2318 uint8_t *data,
2319 size_t data_len
2320 )
2321{
2322 int ret = -1;
2323
2324 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2325
2326 if (!m_env)
2327 return -1;
2328
2329 c_session->dtls_event = -1;
2330
2331 if (!m_env->established && !m_env->sent_alert) {
2332 ret = do_mbedtls_handshake(c_session, m_env);
2333 if (ret == 1) {
2335 c_session);
2336 coap_session_send_csm(c_session);
2337 }
2338 }
2339
2340 if (c_session->state != COAP_SESSION_STATE_NONE && m_env->established) {
2341 ret = mbedtls_ssl_read(&m_env->ssl, data, data_len);
2342 if (ret <= 0) {
2343 switch (ret) {
2344 case 0:
2345 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
2347 ret = -1;
2348 break;
2349 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2350 /* Stop the sending of an alert on closedown */
2351 m_env->sent_alert = 1;
2353 ret = -1;
2354 break;
2355 case MBEDTLS_ERR_SSL_WANT_READ:
2356 errno = EAGAIN;
2357 ret = 0;
2358 break;
2359 default:
2361 "coap_tls_read: "
2362 "returned -0x%x: '%s' (length %zd)\n",
2363 -ret, get_error_string(ret), data_len);
2364 ret = -1;
2365 break;
2366 }
2367 }
2368 }
2369
2370 if (c_session->dtls_event >= 0) {
2371 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
2372 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2373 coap_handle_event(c_session->context, c_session->dtls_event, c_session);
2374 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2375 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2377 ret = -1;
2378 }
2379 }
2380 return ret;
2381}
2382#endif /* !COAP_DISABLE_TCP */
2383
2384void coap_dtls_startup(void)
2385{
2386}
2387
2388void coap_dtls_shutdown(void) {
2389#if COAP_CLIENT_SUPPORT
2390 mbedtls_free(psk_ciphers);
2391 mbedtls_free(pki_ciphers);
2392 psk_ciphers = NULL;
2393 pki_ciphers = NULL;
2394 processed_ciphers = 0;
2395#endif /* COAP_CLIENT_SUPPORT */
2396}
2397
2398void *
2399coap_dtls_get_tls(const coap_session_t *c_session,
2400 coap_tls_library_t *tls_lib) {
2401 if (tls_lib)
2402 *tls_lib = COAP_TLS_LIBRARY_MBEDTLS;
2403 if (c_session && c_session->tls) {
2404 coap_mbedtls_env_t *m_env;
2405
2406 /* To get around const issue */
2407 memcpy(&m_env, &c_session->tls, sizeof(m_env));
2408
2409 return (void *)&m_env->ssl;
2410 }
2411 return NULL;
2412}
2413
2414static int keep_log_level = 0;
2415
2416void coap_dtls_set_log_level(int level)
2417{
2418#if !defined(ESPIDF_VERSION)
2419 int use_level;
2420 /*
2421 * Mbed TLS debug levels filter
2422 * 0 No debug
2423 * 1 Error
2424 * 2 State change
2425 * 3 Informational
2426 * 4 Verbose
2427 */
2428
2429 if (level <= LOG_ERR) {
2430 use_level = 1;
2431 }
2432 else {
2433 use_level = (level >= LOG_DEBUG) ? level - LOG_DEBUG + 2 : 0;
2434 }
2435 mbedtls_debug_set_threshold(use_level);
2436#endif /* !ESPIDF_VERSION) */
2437 keep_log_level = level;
2438}
2439
2441{
2442 return keep_log_level;
2443}
2444
2446{
2447 static coap_tls_version_t version;
2448 version.version = mbedtls_version_get_number();
2449 version.built_version = MBEDTLS_VERSION_NUMBER;
2451 return &version;
2452}
2453
2454#if COAP_SERVER_SUPPORT
2456coap_digest_setup(void) {
2457 mbedtls_sha256_context *digest_ctx = mbedtls_malloc(sizeof(mbedtls_sha256_context));
2458
2459 if (digest_ctx) {
2460 mbedtls_sha256_init(digest_ctx);
2461#ifdef MBEDTLS_2_X_COMPAT
2462 if (mbedtls_sha256_starts_ret(digest_ctx, 0) != 0) {
2463#else
2464 if (mbedtls_sha256_starts(digest_ctx, 0) != 0) {
2465#endif /* MBEDTLS_2_X_COMPAT */
2466 return NULL;
2467 }
2468 }
2469 return digest_ctx;
2470}
2471
2472void
2474 mbedtls_sha256_free(digest_ctx);
2475 mbedtls_free(digest_ctx);
2476}
2477
2478int
2480 const uint8_t *data,
2481 size_t data_len) {
2482#ifdef MBEDTLS_2_X_COMPAT
2483 int ret = mbedtls_sha256_update_ret(digest_ctx, data, data_len);
2484#else
2485 int ret = mbedtls_sha256_update(digest_ctx, data, data_len);
2486#endif /* MBEDTLS_2_X_COMPAT */
2487
2488 return ret == 0;
2489}
2490
2491int
2493 coap_digest_t *digest_buffer) {
2494#ifdef MBEDTLS_2_X_COMPAT
2495 int ret = mbedtls_sha256_finish_ret(digest_ctx, (uint8_t*)digest_buffer);
2496#else
2497 int ret = mbedtls_sha256_finish(digest_ctx, (uint8_t*)digest_buffer);
2498#endif /* MBEDTLS_2_X_COMPAT */
2499
2500 coap_digest_free(digest_ctx);
2501 return ret == 0;
2502}
2503#endif /* COAP_SERVER_SUPPORT */
2504
2505#else /* !HAVE_MBEDTLS */
2506
2507#ifdef __clang__
2508/* Make compilers happy that do not like empty modules. As this function is
2509 * never used, we ignore -Wunused-function at the end of compiling this file
2510 */
2511#pragma GCC diagnostic ignored "-Wunused-function"
2512#endif
2513static inline void dummy(void) {
2514}
2515
2516#endif /* HAVE_MBEDTLS */
Pulls together all the internal only header files.
const char * coap_socket_strerror(void)
Definition: coap_io.c:1594
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
#define COAP_SOCKET_ERROR
Definition: coap_io.h:49
@ COAP_NACK_TLS_FAILED
Definition: coap_io.h:73
static void dummy(void)
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
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
void coap_digest_free(coap_digest_ctx_t *digest_ctx)
Free off coap_digest_ctx_t.
int coap_digest_final(coap_digest_ctx_t *digest_ctx, coap_digest_t *digest_buffer)
Finalize the coap_digest information into the provided digest_buffer.
int coap_digest_update(coap_digest_ctx_t *digest_ctx, const uint8_t *data, size_t data_len)
Update the coap_digest information with the next chunk of data.
void coap_digest_ctx_t
coap_digest_ctx_t * coap_digest_setup(void)
Initialize a coap_digest.
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: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:2035
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:3356
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.
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
const coap_bin_const_t * coap_get_session_server_psk_key(const coap_session_t *coap_session)
Get the current server's PSK key.
coap_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_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition: coap_dtls.h:69
@ COAP_EVENT_DTLS_CLOSED
(D)TLS events for COAP_PROTO_DTLS and COAP_PROTO_TLS
Definition: coap_event.h:38
@ COAP_EVENT_DTLS_CONNECTED
Definition: coap_event.h:39
@ COAP_EVENT_DTLS_ERROR
Definition: coap_event.h:41
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_EMERG
Definition: coap_debug.h:60
#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
coap_proto_t
CoAP protocol types.
Definition: pdu.h:292
@ 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:473
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:395
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:528
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:587
@ COAP_SESSION_STATE_HANDSHAKE
Definition: coap_session.h:56
@ COAP_SESSION_STATE_CSM
Definition: coap_session.h:57
@ COAP_SESSION_STATE_NONE
Definition: coap_session.h:54
#define COAP_UNUSED
Definition: libcoap.h:60
coap_address_t remote
remote address and port
Definition: coap_io.h: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 used for defining the Client PSK setup data to be used.
Definition: coap_dtls.h:350
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
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 verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition: coap_dtls.h:261
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
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
const uint8_t * private_key
ASN1 (DER) Private Key.
Definition: coap_dtls.h:202
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
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_socket_t sock
socket object for the session, if any
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 (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
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