libcoap 4.3.5-develop-4fa3dfa
Loading...
Searching...
No Matches
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-2025 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/*
29 * Notes
30 *
31 * Version 3.2.0 or later is needed to provide Connection ID support (RFC9146).
32 *
33 */
34
36
37#ifdef COAP_WITH_LIBMBEDTLS
38
39/*
40 * This code can be conditionally compiled to remove some components if
41 * they are not required to make a lighter footprint - all based on how
42 * the mbedtls library has been built. These are not defined within the
43 * libcoap environment.
44 *
45 * MBEDTLS_SSL_SRV_C - defined for server side functionality
46 * MBEDTLS_SSL_CLI_C - defined for client side functionality
47 * MBEDTLS_SSL_PROTO_DTLS - defined for DTLS support
48 * MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED - defined if PSK is to be supported
49 * or MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED - defined if PSK is to be supported
50 *
51 */
52
53#include <mbedtls/version.h>
54
55/* Keep forward-compatibility with Mbed TLS 3.x */
56#if (MBEDTLS_VERSION_NUMBER < 0x03000000)
57#define MBEDTLS_2_X_COMPAT
58#else /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */
59/* Macro wrapper for struct's private members */
60#ifndef MBEDTLS_ALLOW_PRIVATE_ACCESS
61#define MBEDTLS_ALLOW_PRIVATE_ACCESS
62#endif /* MBEDTLS_ALLOW_PRIVATE_ACCESS */
63#endif /* !(MBEDTLS_VERSION_NUMBER < 0x03000000) */
64
65#include <mbedtls/platform.h>
66#include <mbedtls/net_sockets.h>
67#include <mbedtls/ssl.h>
68#include <mbedtls/entropy.h>
69#include <mbedtls/ctr_drbg.h>
70#include <mbedtls/error.h>
71#include <mbedtls/timing.h>
72#include <mbedtls/ssl_cookie.h>
73#include <mbedtls/oid.h>
74#include <mbedtls/debug.h>
75#include <mbedtls/sha256.h>
76#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
77#include <mbedtls/esp_debug.h>
78#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
79#if defined(MBEDTLS_PSA_CRYPTO_C)
80#include <psa/crypto.h>
81#endif /* MBEDTLS_PSA_CRYPTO_C */
82
83#define mbedtls_malloc(a) malloc(a)
84#define mbedtls_realloc(a,b) realloc(a,b)
85#define mbedtls_strdup(a) strdup(a)
86#define mbedtls_strndup(a,b) strndup(a,b)
87#undef mbedtls_free
88#define mbedtls_free(a) free(a)
89
90#ifndef MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
91/* definition changed in later mbedtls code versions */
92#ifdef MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED
93#define MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED
94#endif /* MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED */
95#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
96
97#if ! COAP_SERVER_SUPPORT
98#undef MBEDTLS_SSL_SRV_C
99#endif /* ! COAP_SERVER_SUPPORT */
100#if ! COAP_CLIENT_SUPPORT
101#undef MBEDTLS_SSL_CLI_C
102#endif /* ! COAP_CLIENT_SUPPORT */
103
104#ifdef _WIN32
105#define strcasecmp _stricmp
106#endif
107
108#define IS_PSK (1 << 0)
109#define IS_PKI (1 << 1)
110#define IS_CLIENT (1 << 6)
111#define IS_SERVER (1 << 7)
112
113typedef struct coap_ssl_t {
114 const uint8_t *pdu;
115 unsigned pdu_len;
116 unsigned peekmode;
117} coap_ssl_t;
118
119/*
120 * This structure encapsulates the Mbed TLS session object.
121 * It handles both TLS and DTLS.
122 * c_session->tls points to this.
123 */
124typedef struct coap_mbedtls_env_t {
125 mbedtls_ssl_context ssl;
126 mbedtls_entropy_context entropy;
127 mbedtls_ctr_drbg_context ctr_drbg;
128 mbedtls_ssl_config conf;
129 mbedtls_timing_delay_context timer;
130 mbedtls_x509_crt cacert;
131 mbedtls_x509_crt public_cert;
132 mbedtls_pk_context private_key;
133 mbedtls_ssl_cookie_ctx cookie_ctx;
134 /* If not set, need to do do_mbedtls_handshake */
135 int established;
136 int sent_alert;
137 int seen_client_hello;
138 int ec_jpake;
139 coap_tick_t last_timeout;
140 unsigned int retry_scalar;
141 coap_ssl_t coap_ssl_data;
142 uint32_t server_hello_cnt;
143} coap_mbedtls_env_t;
144
145typedef struct pki_sni_entry {
146 char *sni;
147 coap_dtls_key_t pki_key;
148 mbedtls_x509_crt cacert;
149 mbedtls_x509_crt public_cert;
150 mbedtls_pk_context private_key;
151} pki_sni_entry;
152
153typedef struct psk_sni_entry {
154 char *sni;
155 coap_dtls_spsk_info_t psk_info;
156} psk_sni_entry;
157
158typedef struct coap_mbedtls_context_t {
159 coap_dtls_pki_t setup_data;
160 size_t pki_sni_count;
161 pki_sni_entry *pki_sni_entry_list;
162 size_t psk_sni_count;
163 psk_sni_entry *psk_sni_entry_list;
164 char *root_ca_file;
165 char *root_ca_path;
166 int trust_store_defined;
167 int psk_pki_enabled;
168} coap_mbedtls_context_t;
169
170typedef enum coap_enc_method_t {
171 COAP_ENC_PSK,
172 COAP_ENC_PKI,
173 COAP_ENC_ECJPAKE,
174} coap_enc_method_t;
175
176#ifdef __ZEPHYR__
177
178typedef struct {
179 uint32_t start_time;
180 uint32_t int_time;
181 uint32_t fin_time;
182} zephyr_timing_delay_context;
183
184static void
185zephyr_timing_set_delay(void *data, uint32_t int_ms, uint32_t fin_ms) {
186 zephyr_timing_delay_context *ctx = (zephyr_timing_delay_context *)data;
187
188 if (ctx == NULL) {
189 return;
190 }
191
192 ctx->start_time = k_uptime_get_32();
193
194 if (fin_ms != 0) {
195 ctx->int_time = ctx->start_time + int_ms;
196 ctx->fin_time = ctx->start_time + fin_ms;
197 } else {
198 ctx->int_time = 0;
199 ctx->fin_time = 0;
200 }
201}
202
203static int
204zephyr_timing_get_delay(void *data) {
205 zephyr_timing_delay_context *ctx = (zephyr_timing_delay_context *)data;
206 uint32_t now;
207
208 if (ctx == NULL || ctx->fin_time == 0) {
209 return -1;
210 }
211
212 now = k_uptime_get_32();
213
214 if (now >= ctx->fin_time) {
215 return 2;
216 }
217
218 if (now >= ctx->int_time) {
219 return 1;
220 }
221
222 return 0;
223}
224
225#endif /* __ZEPHYR__ */
226
227#ifndef MBEDTLS_2_X_COMPAT
228/*
229 * mbedtls_ callback functions expect 0 on success, -ve on failure.
230 */
231static int
232coap_rng(void *ctx COAP_UNUSED, unsigned char *buf, size_t len) {
233 return coap_prng_lkd(buf, len) ? 0 : MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
234}
235#endif /* MBEDTLS_2_X_COMPAT */
236
237static int
238coap_dgram_read(void *ctx, unsigned char *out, size_t outl) {
239 ssize_t ret = 0;
240 coap_session_t *c_session = (coap_session_t *)ctx;
241 coap_ssl_t *data;
242
243 if (!c_session->tls) {
244 errno = EAGAIN;
245 return MBEDTLS_ERR_SSL_WANT_READ;
246 }
247 data = &((coap_mbedtls_env_t *)c_session->tls)->coap_ssl_data;
248
249 if (out != NULL) {
250 if (data->pdu_len > 0) {
251 if (outl < data->pdu_len) {
252 memcpy(out, data->pdu, outl);
253 ret = outl;
254 data->pdu += outl;
255 data->pdu_len -= outl;
256 } else {
257 memcpy(out, data->pdu, data->pdu_len);
258 ret = data->pdu_len;
259 if (!data->peekmode) {
260 data->pdu_len = 0;
261 data->pdu = NULL;
262 }
263 }
264 } else {
265 ret = MBEDTLS_ERR_SSL_WANT_READ;
266 errno = EAGAIN;
267 }
268 }
269 return ret;
270}
271
272/*
273 * return +ve data amount
274 * 0 no more
275 * -ve Mbed TLS error
276 */
277/* callback function given to mbedtls for sending data over socket */
278static int
279coap_dgram_write(void *ctx, const unsigned char *send_buffer,
280 size_t send_buffer_length) {
281 ssize_t result = -1;
282 coap_session_t *c_session = (coap_session_t *)ctx;
283
284 if (c_session) {
285 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
286
287 if (!coap_netif_available(c_session)
289 && c_session->endpoint == NULL
290#endif /* COAP_SERVER_SUPPORT */
291 ) {
292 /* socket was closed on client due to error */
293 errno = ECONNRESET;
294 return -1;
295 }
296 result = (int)c_session->sock.lfunc[COAP_LAYER_TLS].l_write(c_session,
297 send_buffer, send_buffer_length);
298 if (result != (ssize_t)send_buffer_length) {
299 int keep_errno = errno;
300
301 coap_log_warn("coap_netif_dgrm_write failed (%zd != %zu)\n",
302 result, send_buffer_length);
303 errno = keep_errno;
304 if (result < 0) {
305 if (errno == ENOTCONN || errno == ECONNREFUSED)
307 return -1;
308 } else {
309 result = 0;
310 }
311 } else if (m_env) {
312 coap_tick_t now;
313 coap_ticks(&now);
314 m_env->last_timeout = now;
315 }
316 } else {
317 result = 0;
318 }
319 return result;
320}
321
322#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && defined(MBEDTLS_SSL_SRV_C)
323/*
324 * Server side PSK callback
325 */
326static int
327psk_server_callback(void *p_info, mbedtls_ssl_context *ssl,
328 const unsigned char *identity, size_t identity_len) {
329 coap_session_t *c_session = (coap_session_t *)p_info;
330 coap_dtls_spsk_t *setup_data;
331 coap_mbedtls_env_t *m_env;
332 coap_bin_const_t lidentity;
333 const coap_bin_const_t *psk_key;
334
335 if (c_session == NULL)
336 return -1;
337
338 /* Track the Identity being used */
339 lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
340 lidentity.length = identity ? identity_len : 0;
341 coap_session_refresh_psk_identity(c_session, &lidentity);
342
343 coap_log_debug("got psk_identity: '%.*s'\n",
344 (int)lidentity.length, (const char *)lidentity.s);
345
346 m_env = (coap_mbedtls_env_t *)c_session->tls;
347 setup_data = &c_session->context->spsk_setup_data;
348
349 if (setup_data->validate_id_call_back) {
350 psk_key = setup_data->validate_id_call_back(&lidentity,
351 c_session,
352 setup_data->id_call_back_arg);
353
354 coap_session_refresh_psk_key(c_session, psk_key);
355 } else {
356 psk_key = coap_get_session_server_psk_key(c_session);
357 }
358
359 if (psk_key == NULL)
360 return -1;
361 mbedtls_ssl_set_hs_psk(ssl, psk_key->s, psk_key->length);
362 m_env->seen_client_hello = 1;
363 return 0;
364}
365#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && MBEDTLS_SSL_SRV_C */
366
367static char *
368get_san_or_cn_from_cert(mbedtls_x509_crt *crt) {
369 if (crt) {
370 const mbedtls_asn1_named_data *cn_data;
371
372 if (crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME) {
373 mbedtls_asn1_sequence *seq = &crt->subject_alt_names;
374 while (seq && seq->buf.p == NULL) {
375 seq = seq->next;
376 }
377 if (seq) {
378 /* Return the Subject Alt Name */
379 return mbedtls_strndup((const char *)seq->buf.p,
380 seq->buf.len);
381 }
382 }
383
384 cn_data = mbedtls_asn1_find_named_data(&crt->subject,
385 MBEDTLS_OID_AT_CN,
386 MBEDTLS_OID_SIZE(MBEDTLS_OID_AT_CN));
387 if (cn_data) {
388 /* Return the Common Name */
389 return mbedtls_strndup((const char *)cn_data->val.p,
390 cn_data->val.len);
391 }
392 }
393 return NULL;
394}
395
396#if COAP_MAX_LOGGING_LEVEL > 0
397static char *
398get_error_string(int ret) {
399 static char buf[128] = {0};
400 mbedtls_strerror(ret, buf, sizeof(buf)-1);
401 return buf;
402}
403#endif /* COAP_MAX_LOGGING_LEVEL */
404
405static int
406self_signed_cert_verify_callback_mbedtls(void *data,
407 mbedtls_x509_crt *crt COAP_UNUSED,
408 int depth COAP_UNUSED,
409 uint32_t *flags) {
410 const coap_session_t *c_session = (coap_session_t *)data;
411 const coap_mbedtls_context_t *m_context =
412 (coap_mbedtls_context_t *)c_session->context->dtls_context;
413 const coap_dtls_pki_t *setup_data = &m_context->setup_data;
414
415 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
416 if (setup_data->allow_expired_certs) {
417 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
418 }
419 }
420 return 0;
421}
422
423/*
424 * return 0 All OK
425 * -ve Error Code
426 */
427static int
428cert_verify_callback_mbedtls(void *data, mbedtls_x509_crt *crt,
429 int depth, uint32_t *flags) {
430 coap_session_t *c_session = (coap_session_t *)data;
431 coap_mbedtls_context_t *m_context =
432 (coap_mbedtls_context_t *)c_session->context->dtls_context;
433 coap_dtls_pki_t *setup_data = &m_context->setup_data;
434 char *cn = NULL;
435
436 if (*flags == 0)
437 return 0;
438
439 cn = get_san_or_cn_from_cert(crt);
440
441 if (*flags & MBEDTLS_X509_BADCERT_EXPIRED) {
442 if (setup_data->allow_expired_certs) {
443 *flags &= ~MBEDTLS_X509_BADCERT_EXPIRED;
444 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
445 coap_session_str(c_session),
446 "The certificate has expired", cn ? cn : "?", depth);
447 }
448 }
449 if (*flags & MBEDTLS_X509_BADCERT_FUTURE) {
450 if (setup_data->allow_expired_certs) {
451 *flags &= ~MBEDTLS_X509_BADCERT_FUTURE;
452 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
453 coap_session_str(c_session),
454 "The certificate has a future date", cn ? cn : "?", depth);
455 }
456 }
457 if (*flags & MBEDTLS_X509_BADCERT_BAD_MD) {
458 if (setup_data->allow_bad_md_hash) {
459 *flags &= ~MBEDTLS_X509_BADCERT_BAD_MD;
460 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
461 coap_session_str(c_session),
462 "The certificate has a bad MD hash", cn ? cn : "?", depth);
463 }
464 }
465 if (*flags & MBEDTLS_X509_BADCERT_BAD_KEY) {
466 if (setup_data->allow_short_rsa_length) {
467 *flags &= ~MBEDTLS_X509_BADCERT_BAD_KEY;
468 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
469 coap_session_str(c_session),
470 "The certificate has a short RSA length", cn ? cn : "?", depth);
471 }
472 }
473 if (*flags & MBEDTLS_X509_BADCERT_NOT_TRUSTED) {
474 uint32_t lflags;
475 int self_signed = !mbedtls_x509_crt_verify(crt, crt, NULL, NULL, &lflags,
476 self_signed_cert_verify_callback_mbedtls,
477 data);
478 if (self_signed && depth == 0) {
479 if (setup_data->allow_self_signed &&
480 !setup_data->check_common_ca) {
481 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
482 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
483 coap_session_str(c_session),
484 "Self-signed",
485 cn ? cn : "?", depth);
486 }
487 } else if (self_signed) {
488 if (!setup_data->verify_peer_cert) {
489 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
490 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
491 coap_session_str(c_session),
492 "Self-signed", cn ? cn : "?", depth);
493 }
494 } else {
495 if (!setup_data->verify_peer_cert) {
496 *flags &= ~MBEDTLS_X509_BADCERT_NOT_TRUSTED;
497 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
498 coap_session_str(c_session),
499 "The certificate's CA is not trusted", cn ? cn : "?", depth);
500 }
501 }
502 }
503 if (*flags & MBEDTLS_X509_BADCRL_EXPIRED) {
504 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
505 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
506 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
507 coap_session_str(c_session),
508 "The certificate's CRL has expired", cn ? cn : "?", depth);
509 } else if (!setup_data->check_cert_revocation) {
510 *flags &= ~MBEDTLS_X509_BADCRL_EXPIRED;
511 }
512 }
513 if (*flags & MBEDTLS_X509_BADCRL_FUTURE) {
514 if (setup_data->check_cert_revocation && setup_data->allow_expired_crl) {
515 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
516 coap_log_info(" %s: %s: overridden: '%s' depth %d\n",
517 coap_session_str(c_session),
518 "The certificate's CRL has a future date", cn ? cn : "?", depth);
519 } else if (!setup_data->check_cert_revocation) {
520 *flags &= ~MBEDTLS_X509_BADCRL_FUTURE;
521 }
522 }
523 if (setup_data->cert_chain_validation &&
524 depth > (setup_data->cert_chain_verify_depth + 1)) {
525 *flags |= MBEDTLS_X509_BADCERT_OTHER;
526 coap_log_warn(" %s: %s: '%s' depth %d\n",
527 coap_session_str(c_session),
528 "The certificate's verify depth is too long",
529 cn ? cn : "?", depth);
530 }
531
532 if (*flags & MBEDTLS_X509_BADCERT_CN_MISMATCH) {
533 *flags &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH;
534 }
535 if (setup_data->validate_cn_call_back) {
536 int ret;
537
539 setup_data->validate_cn_call_back(cn,
540 crt->raw.p,
541 crt->raw.len,
542 c_session,
543 depth,
544 *flags == 0,
545 setup_data->cn_call_back_arg));
546 if (!ret) {
547 *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH;
548 }
549 }
550 if (*flags != 0) {
551 char buf[128];
552 char *tcp;
553 int ret = mbedtls_x509_crt_verify_info(buf, sizeof(buf), "", *flags);
554
555 if (ret >= 0) {
556 tcp = strchr(buf, '\n');
557 while (tcp) {
558 *tcp = '\000';
559 coap_log_warn(" %s: %s: issue 0x%" PRIx32 ": '%s' depth %d\n",
560 coap_session_str(c_session),
561 buf, *flags, cn ? cn : "?", depth);
562 tcp = strchr(tcp+1, '\n');
563 }
564 } else {
565 coap_log_err("mbedtls_x509_crt_verify_info returned -0x%x: '%s'\n",
566 -ret, get_error_string(ret));
567 }
568 }
569
570 if (cn)
571 mbedtls_free(cn);
572
573 return 0;
574}
575
576static int
577setup_pki_credentials(mbedtls_x509_crt *cacert,
578 mbedtls_x509_crt *public_cert,
579 mbedtls_pk_context *private_key,
580 coap_mbedtls_env_t *m_env,
581 coap_mbedtls_context_t *m_context,
582 coap_session_t *c_session,
583 coap_dtls_pki_t *setup_data,
584 coap_dtls_role_t role) {
585 coap_dtls_key_t key;
586 int ret;
587 int done_private_key = 0;
588 int done_public_cert = 0;
589 uint8_t *buffer;
590 size_t length;
591
592 /* Map over to the new define format to save code duplication */
593 coap_dtls_map_key_type_to_define(setup_data, &key);
594
595 assert(key.key_type == COAP_PKI_KEY_DEFINE);
596
597 /*
598 * Configure the Private Key
599 */
600 if (key.key.define.private_key.u_byte &&
601 key.key.define.private_key.u_byte[0]) {
602 switch (key.key.define.private_key_def) {
603 case COAP_PKI_KEY_DEF_DER: /* define private key */
604 /* Fall Through */
605 case COAP_PKI_KEY_DEF_PEM: /* define private key */
606#if defined(MBEDTLS_FS_IO)
607 mbedtls_pk_init(private_key);
608#ifdef MBEDTLS_2_X_COMPAT
609 ret = mbedtls_pk_parse_keyfile(private_key,
610 key.key.define.private_key.s_byte, NULL);
611#else
612 ret = mbedtls_pk_parse_keyfile(private_key,
614 NULL, coap_rng, (void *)&m_env->ctr_drbg);
615#endif /* MBEDTLS_2_X_COMPAT */
616 if (ret < 0) {
619 &key, role, ret);
620 }
621 done_private_key = 1;
622 break;
623#else /* ! MBEDTLS_FS_IO */
626 &key, role, -1);
627#endif /* ! MBEDTLS_FS_IO */
628 case COAP_PKI_KEY_DEF_PEM_BUF: /* define private key */
629 mbedtls_pk_init(private_key);
630 length = key.key.define.private_key_len;
631 if (key.key.define.private_key.u_byte[length-1] != '\000') {
632 /* Need to allocate memory to add in NULL terminator */
633 buffer = mbedtls_malloc(length + 1);
634 if (!buffer) {
635 coap_log_err("mbedtls_malloc failed\n");
636 return 0;
637 }
638 memcpy(buffer, key.key.define.private_key.u_byte, length);
639 buffer[length] = '\000';
640 length++;
641#ifdef MBEDTLS_2_X_COMPAT
642 ret = mbedtls_pk_parse_key(private_key, buffer, length, NULL, 0);
643#else
644 ret = mbedtls_pk_parse_key(private_key, buffer, length,
645 NULL, 0, coap_rng, (void *)&m_env->ctr_drbg);
646#endif /* MBEDTLS_2_X_COMPAT */
647 mbedtls_free(buffer);
648 } else {
649#ifdef MBEDTLS_2_X_COMPAT
650 ret = mbedtls_pk_parse_key(private_key,
652 key.key.define.private_key_len, NULL, 0);
653#else
654 ret = mbedtls_pk_parse_key(private_key,
657 NULL, 0, coap_rng, (void *)&m_env->ctr_drbg);
658#endif /* MBEDTLS_2_X_COMPAT */
659 }
660 if (ret < 0) {
663 &key, role, ret);
664 }
665 done_private_key = 1;
666 break;
667 case COAP_PKI_KEY_DEF_DER_BUF: /* define private key */
668 mbedtls_pk_init(private_key);
669#ifdef MBEDTLS_2_X_COMPAT
670 ret = mbedtls_pk_parse_key(private_key,
672 key.key.define.private_key_len, NULL, 0);
673#else
674 ret = mbedtls_pk_parse_key(private_key,
676 key.key.define.private_key_len, NULL, 0, coap_rng,
677 (void *)&m_env->ctr_drbg);
678#endif /* MBEDTLS_2_X_COMPAT */
679 if (ret < 0) {
682 &key, role, ret);
683 }
684 done_private_key = 1;
685 break;
686 case COAP_PKI_KEY_DEF_RPK_BUF: /* define private key */
687 case COAP_PKI_KEY_DEF_PKCS11: /* define private key */
688 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define private key */
689 case COAP_PKI_KEY_DEF_ENGINE: /* define private key */
690 default:
693 &key, role, -1);
694 }
695 } else if (role == COAP_DTLS_ROLE_SERVER ||
697 key.key.define.public_cert.u_byte[0])) {
700 &key, role, -1);
701 }
702
703 /*
704 * Configure the Public Certificate / Key
705 */
706 if (key.key.define.public_cert.u_byte &&
707 key.key.define.public_cert.u_byte[0]) {
708 switch (key.key.define.public_cert_def) {
709 case COAP_PKI_KEY_DEF_DER: /* define public cert */
710 /* Fall Through */
711 case COAP_PKI_KEY_DEF_PEM: /* define public cert */
712#if defined(MBEDTLS_FS_IO)
713 mbedtls_x509_crt_init(public_cert);
714 ret = mbedtls_x509_crt_parse_file(public_cert,
716 if (ret < 0) {
719 &key, role, ret);
720 }
721 done_public_cert = 1;
722 break;
723#else /* ! MBEDTLS_FS_IO */
726 &key, role, -1);
727#endif /* ! MBEDTLS_FS_IO */
728 case COAP_PKI_KEY_DEF_PEM_BUF: /* define public cert */
729 mbedtls_x509_crt_init(public_cert);
730
731 length = key.key.define.public_cert_len;
732 if (key.key.define.public_cert.u_byte[length-1] != '\000') {
733 /* Need to allocate memory to add in NULL terminator */
734 buffer = mbedtls_malloc(length + 1);
735 if (!buffer) {
736 coap_log_err("mbedtls_malloc failed\n");
737 return 0;
738 }
739 memcpy(buffer, key.key.define.public_cert.u_byte, length);
740 buffer[length] = '\000';
741 length++;
742 ret = mbedtls_x509_crt_parse(public_cert, buffer, length);
743 mbedtls_free(buffer);
744 } else {
745 ret = mbedtls_x509_crt_parse(public_cert,
748 }
749 if (ret < 0) {
752 &key, role, ret);
753 }
754 done_public_cert = 1;
755 break;
756 case COAP_PKI_KEY_DEF_RPK_BUF: /* define public cert */
759 &key, role, -1);
760 case COAP_PKI_KEY_DEF_DER_BUF: /* define public cert */
761 mbedtls_x509_crt_init(public_cert);
762 ret = mbedtls_x509_crt_parse(public_cert,
765 if (ret < 0) {
768 &key, role, ret);
769 }
770 done_public_cert = 1;
771 break;
772 case COAP_PKI_KEY_DEF_PKCS11: /* define public cert */
773 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define public cert */
774 case COAP_PKI_KEY_DEF_ENGINE: /* define public cert */
775 default:
778 &key, role, -1);
779 }
780 } else if (role == COAP_DTLS_ROLE_SERVER ||
782 key.key.define.private_key.u_byte[0])) {
785 &key, role, -1);
786 }
787
788 if (done_private_key && done_public_cert) {
789 ret = mbedtls_ssl_conf_own_cert(&m_env->conf, public_cert, private_key);
790 if (ret < 0) {
791 coap_log_err("mbedtls_ssl_conf_own_cert returned -0x%x: '%s'\n",
792 -ret, get_error_string(ret));
793 return 0;
794 }
795 }
796
797 /*
798 * Configure the CA
799 */
800 if (
801 key.key.define.ca.u_byte &&
802 key.key.define.ca.u_byte[0]) {
803 switch (key.key.define.ca_def) {
804 case COAP_PKI_KEY_DEF_DER: /* define ca */
805 /* Fall Through */
807#if defined(MBEDTLS_FS_IO)
808 mbedtls_x509_crt_init(cacert);
809 ret = mbedtls_x509_crt_parse_file(cacert,
810 key.key.define.ca.s_byte);
811 if (ret < 0) {
814 &key, role, ret);
815 }
816 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
817#else /* ! MBEDTLS_FS_IO */
820 &key, role, -1);
821#endif /* ! MBEDTLS_FS_IO */
822 break;
823 case COAP_PKI_KEY_DEF_PEM_BUF: /* define ca */
824 mbedtls_x509_crt_init(cacert);
825 length = key.key.define.ca_len;
826 if (key.key.define.ca.u_byte[length-1] != '\000') {
827 /* Need to allocate memory to add in NULL terminator */
828 buffer = mbedtls_malloc(length + 1);
829 if (!buffer) {
830 coap_log_err("mbedtls_malloc failed\n");
831 return 0;
832 }
833 memcpy(buffer, key.key.define.ca.u_byte, length);
834 buffer[length] = '\000';
835 length++;
836 ret = mbedtls_x509_crt_parse(cacert, buffer, length);
837 mbedtls_free(buffer);
838 } else {
839 ret = mbedtls_x509_crt_parse(cacert,
840 key.key.define.ca.u_byte,
841 key.key.define.ca_len);
842 }
843 if (ret < 0) {
846 &key, role, ret);
847 }
848 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
849 break;
850 case COAP_PKI_KEY_DEF_RPK_BUF: /* define ca */
853 &key, role, -1);
854 case COAP_PKI_KEY_DEF_DER_BUF: /* define ca */
855 mbedtls_x509_crt_init(cacert);
856 ret = mbedtls_x509_crt_parse(cacert,
857 key.key.define.ca.u_byte,
858 key.key.define.ca_len);
859 if (ret < 0) {
862 &key, role, ret);
863 }
864 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
865 break;
866 case COAP_PKI_KEY_DEF_PKCS11: /* define ca */
867 case COAP_PKI_KEY_DEF_PKCS11_RPK: /* define ca */
868 case COAP_PKI_KEY_DEF_ENGINE: /* define ca */
869 default:
872 &key, role, -1);
873 }
874 }
875
876 /* Add in any root CA definitons */
877
878#if defined(MBEDTLS_FS_IO)
879 if (m_context->root_ca_file) {
880 ret = mbedtls_x509_crt_parse_file(cacert, m_context->root_ca_file);
881 if (ret < 0) {
885 &key, role, ret);
886 }
887 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
888 }
889 if (m_context->root_ca_path) {
890 ret = mbedtls_x509_crt_parse_path(cacert, m_context->root_ca_path);
891 if (ret < 0) {
895 &key, role, ret);
896 }
897 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
898 }
899 if (m_context->trust_store_defined) {
900 /* Until Trust Store is implemented in MbedTLS */
901 const char *trust_list[] = {
902 "/etc/ssl/ca-bundle.pem",
903 "/etc/ssl/certs/ca-certificates.crt",
904 "/etc/pki/tls/cert.pem",
905 "/usr/local/share/certs/ca-root-nss.crt",
906 "/etc/ssl/cert.pem"
907 };
908 static const char *trust_file_found = NULL;
909 static int trust_file_done = 0;
910 unsigned int i;
911
912 if (trust_file_found) {
913 ret = mbedtls_x509_crt_parse_file(cacert, trust_file_found);
914 if (ret >= 0) {
915 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
916 } else {
917 coap_log_warn("Unable to load trusted root CAs (%s)\n",
918 trust_file_found);
919 }
920 } else if (!trust_file_done) {
921 trust_file_done = 1;
922 for (i = 0; i < sizeof(trust_list)/sizeof(trust_list[0]); i++) {
923 ret = mbedtls_x509_crt_parse_file(cacert, trust_list[i]);
924 if (ret >= 0) {
925 mbedtls_ssl_conf_ca_chain(&m_env->conf, cacert, NULL);
926 trust_file_found = trust_list[i];
927 break;
928 }
929 }
930 if (i == sizeof(trust_list)/sizeof(trust_list[0])) {
931 coap_log_warn("Unable to load trusted root CAs\n");
932 }
933 }
934 }
935#else /* ! MBEDTLS_FS_IO */
936 (void)m_context;
939 &key, role, -1);
940#endif /* ! MBEDTLS_FS_IO */
941
942#if defined(MBEDTLS_SSL_SRV_C)
943 mbedtls_ssl_conf_cert_req_ca_list(&m_env->conf,
944 setup_data->check_common_ca ?
945 MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED :
946 MBEDTLS_SSL_CERT_REQ_CA_LIST_DISABLED);
947#endif
948 mbedtls_ssl_conf_authmode(&m_env->conf, setup_data->verify_peer_cert ?
949 MBEDTLS_SSL_VERIFY_REQUIRED :
950 MBEDTLS_SSL_VERIFY_NONE);
951 /*
952 * Verify Peer.
953 * Need to do all checking, even if setup_data->verify_peer_cert is not set
954 */
955 mbedtls_ssl_conf_verify(&m_env->conf,
956 cert_verify_callback_mbedtls, c_session);
957
958 return 1;
959}
960
961#if defined(MBEDTLS_SSL_SRV_C)
962/*
963 * PKI SNI callback.
964 */
965static int
966pki_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
967 const unsigned char *uname, size_t name_len) {
968 unsigned int i;
969 coap_dtls_pki_t sni_setup_data;
970 coap_session_t *c_session = (coap_session_t *)p_info;
971 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
972 coap_mbedtls_context_t *m_context =
973 (coap_mbedtls_context_t *)c_session->context->dtls_context;
974 char *name;
975
976 name = mbedtls_malloc(name_len+1);
977 if (!name)
978 return -1;
979
980 memcpy(name, uname, name_len);
981 name[name_len] = '\000';
982
983 /* Is this a cached entry? */
984 for (i = 0; i < m_context->pki_sni_count; i++) {
985 if (strcasecmp(name, m_context->pki_sni_entry_list[i].sni) == 0) {
986 break;
987 }
988 }
989 if (i == m_context->pki_sni_count) {
990 /*
991 * New PKI SNI request
992 */
993 coap_dtls_key_t *new_entry;
994 pki_sni_entry *pki_sni_entry_list;
995
996 coap_lock_callback_ret(new_entry,
997 m_context->setup_data.validate_sni_call_back(name,
998 m_context->setup_data.sni_call_back_arg));
999 if (!new_entry) {
1000 mbedtls_free(name);
1001 return -1;
1002 }
1003
1004 pki_sni_entry_list = mbedtls_realloc(m_context->pki_sni_entry_list,
1005 (i+1)*sizeof(pki_sni_entry));
1006
1007 if (pki_sni_entry_list == NULL) {
1008 mbedtls_free(name);
1009 return -1;
1010 }
1011 m_context->pki_sni_entry_list = pki_sni_entry_list;
1012 memset(&m_context->pki_sni_entry_list[i], 0,
1013 sizeof(m_context->pki_sni_entry_list[i]));
1014 m_context->pki_sni_entry_list[i].sni = name;
1015 m_context->pki_sni_entry_list[i].pki_key = *new_entry;
1016 sni_setup_data = m_context->setup_data;
1017 sni_setup_data.pki_key = *new_entry;
1018 if (setup_pki_credentials(&m_context->pki_sni_entry_list[i].cacert,
1019 &m_context->pki_sni_entry_list[i].public_cert,
1020 &m_context->pki_sni_entry_list[i].private_key,
1021 m_env,
1022 m_context,
1023 c_session,
1024 &sni_setup_data, COAP_DTLS_ROLE_SERVER) < 0) {
1025 mbedtls_free(name);
1026 return -1;
1027 }
1028 /* name has been absorbed into pki_sni_entry_list[].sni entry */
1029 m_context->pki_sni_count++;
1030 } else {
1031 mbedtls_free(name);
1032 }
1033
1034 mbedtls_ssl_set_hs_ca_chain(ssl, &m_context->pki_sni_entry_list[i].cacert,
1035 NULL);
1036 return mbedtls_ssl_set_hs_own_cert(ssl,
1037 &m_context->pki_sni_entry_list[i].public_cert,
1038 &m_context->pki_sni_entry_list[i].private_key);
1039}
1040
1041#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1042/*
1043 * PSK SNI callback.
1044 */
1045static int
1046psk_sni_callback(void *p_info, mbedtls_ssl_context *ssl,
1047 const unsigned char *uname, size_t name_len) {
1048 unsigned int i;
1049 coap_session_t *c_session = (coap_session_t *)p_info;
1050 coap_mbedtls_context_t *m_context =
1051 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1052 char *name;
1053
1054 name = mbedtls_malloc(name_len+1);
1055 if (!name)
1056 return -1;
1057
1058 memcpy(name, uname, name_len);
1059 name[name_len] = '\000';
1060
1061 /* Is this a cached entry? */
1062 for (i = 0; i < m_context->psk_sni_count; i++) {
1063 if (strcasecmp(name, m_context->psk_sni_entry_list[i].sni) == 0) {
1064 break;
1065 }
1066 }
1067 if (i == m_context->psk_sni_count) {
1068 /*
1069 * New PSK SNI request
1070 */
1071 const coap_dtls_spsk_info_t *new_entry;
1072 psk_sni_entry *psk_sni_entry_list;
1073
1074 coap_lock_callback_ret(new_entry,
1076 c_session,
1078 if (!new_entry) {
1079 mbedtls_free(name);
1080 return -1;
1081 }
1082
1083 psk_sni_entry_list = mbedtls_realloc(m_context->psk_sni_entry_list,
1084 (i+1)*sizeof(psk_sni_entry));
1085
1086 if (psk_sni_entry_list == NULL) {
1087 mbedtls_free(name);
1088 return -1;
1089 }
1090 m_context->psk_sni_entry_list = psk_sni_entry_list;
1091 m_context->psk_sni_entry_list[i].sni = name;
1092 m_context->psk_sni_entry_list[i].psk_info = *new_entry;
1093 /* name has been absorbed into psk_sni_entry_list[].sni entry */
1094 m_context->psk_sni_count++;
1095 } else {
1096 mbedtls_free(name);
1097 }
1098
1100 &m_context->psk_sni_entry_list[i].psk_info.hint);
1102 &m_context->psk_sni_entry_list[i].psk_info.key);
1103 return mbedtls_ssl_set_hs_psk(ssl,
1104 m_context->psk_sni_entry_list[i].psk_info.key.s,
1105 m_context->psk_sni_entry_list[i].psk_info.key.length);
1106}
1107#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1108
1109static int
1110setup_server_ssl_session(coap_session_t *c_session,
1111 coap_mbedtls_env_t *m_env) {
1112 coap_mbedtls_context_t *m_context =
1113 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1114 int ret = 0;
1115 m_context->psk_pki_enabled |= IS_SERVER;
1116
1117 mbedtls_ssl_cookie_init(&m_env->cookie_ctx);
1118 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
1119 MBEDTLS_SSL_IS_SERVER,
1120 c_session->proto == COAP_PROTO_DTLS ?
1121 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
1122 MBEDTLS_SSL_TRANSPORT_STREAM,
1123 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
1124 coap_log_err("mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
1125 -ret, get_error_string(ret));
1126 goto fail;
1127 }
1128
1129 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
1130
1131#if defined(MBEDTLS_SSL_PROTO_DTLS)
1132 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
1133 COAP_DTLS_RETRANSMIT_TOTAL_MS);
1134#endif /* MBEDTLS_SSL_PROTO_DTLS */
1135
1136 if (m_context->psk_pki_enabled & IS_PSK) {
1137#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1138 mbedtls_ssl_conf_psk_cb(&m_env->conf, psk_server_callback, c_session);
1140 mbedtls_ssl_conf_sni(&m_env->conf, psk_sni_callback, c_session);
1141 }
1142#ifdef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
1143 m_env->ec_jpake = c_session->context->spsk_setup_data.ec_jpake;
1144#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1145#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1146 coap_log_warn("PSK not enabled in Mbed TLS library\n");
1147#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1148 }
1149
1150 if (m_context->psk_pki_enabled & IS_PKI) {
1151 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
1152 &m_env->private_key, m_env, m_context,
1153 c_session, &m_context->setup_data,
1155 if (ret < 0) {
1156 coap_log_err("PKI setup failed\n");
1157 return ret;
1158 }
1159 if (m_context->setup_data.validate_sni_call_back) {
1160 mbedtls_ssl_conf_sni(&m_env->conf, pki_sni_callback, c_session);
1161 }
1162 }
1163
1164 if ((ret = mbedtls_ssl_cookie_setup(&m_env->cookie_ctx,
1165 mbedtls_ctr_drbg_random,
1166 &m_env->ctr_drbg)) != 0) {
1167 coap_log_err("mbedtls_ssl_cookie_setup: returned -0x%x: '%s'\n",
1168 -ret, get_error_string(ret));
1169 goto fail;
1170 }
1171
1172#if defined(MBEDTLS_SSL_PROTO_DTLS)
1173 mbedtls_ssl_conf_dtls_cookies(&m_env->conf, mbedtls_ssl_cookie_write,
1174 mbedtls_ssl_cookie_check,
1175 &m_env->cookie_ctx);
1176#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1177 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1178#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1179#endif /* MBEDTLS_SSL_PROTO_DTLS */
1180#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
1181 /*
1182 * Configure CID max length.
1183 *
1184 * Note: Set MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT to 0 (the default)
1185 * to use RFC9146 extension ID of 54, rather than the draft version -05
1186 * value of 254.
1187 */
1188 mbedtls_ssl_conf_cid(&m_env->conf, COAP_DTLS_CID_LENGTH, MBEDTLS_SSL_UNEXPECTED_CID_IGNORE);
1189#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
1190fail:
1191 return ret;
1192}
1193#endif /* MBEDTLS_SSL_SRV_C */
1194
1195#if COAP_CLIENT_SUPPORT
1196static int *psk_ciphers = NULL;
1197static int *pki_ciphers = NULL;
1198static int *ecjpake_ciphers = NULL;
1199static int processed_ciphers = 0;
1200
1201#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1202static int
1203coap_ssl_ciphersuite_uses_psk(const mbedtls_ssl_ciphersuite_t *info) {
1204#if MBEDTLS_VERSION_NUMBER >= 0x03060000
1205 switch (info->key_exchange) {
1206 case MBEDTLS_KEY_EXCHANGE_PSK:
1207 case MBEDTLS_KEY_EXCHANGE_RSA_PSK:
1208 case MBEDTLS_KEY_EXCHANGE_DHE_PSK:
1209 case MBEDTLS_KEY_EXCHANGE_ECDHE_PSK:
1210 return 1;
1211 case MBEDTLS_KEY_EXCHANGE_NONE:
1212 case MBEDTLS_KEY_EXCHANGE_RSA:
1213 case MBEDTLS_KEY_EXCHANGE_DHE_RSA:
1214 case MBEDTLS_KEY_EXCHANGE_ECDHE_RSA:
1215 case MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA:
1216 case MBEDTLS_KEY_EXCHANGE_ECDH_RSA:
1217 case MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA:
1218 case MBEDTLS_KEY_EXCHANGE_ECJPAKE:
1219 default:
1220 return 0;
1221 }
1222#else /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
1223 return mbedtls_ssl_ciphersuite_uses_psk(info);
1224#endif /* MBEDTLS_VERSION_NUMBER < 0x03060000 */
1225}
1226#endif /* defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) */
1227
1228static void
1229set_ciphersuites(mbedtls_ssl_config *conf, coap_enc_method_t method) {
1230 if (!processed_ciphers) {
1231 const int *list = mbedtls_ssl_list_ciphersuites();
1232 const int *base = list;
1233 int *psk_list;
1234 int *pki_list;
1235#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
1236 int *ecjpake_list;
1237 int ecjpake_count = 1;
1238#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1239 int psk_count = 1; /* account for empty terminator */
1240 int pki_count = 1;
1241
1242 while (*list) {
1243 const mbedtls_ssl_ciphersuite_t *cur =
1244 mbedtls_ssl_ciphersuite_from_id(*list);
1245
1246 if (cur) {
1247#if MBEDTLS_VERSION_NUMBER >= 0x03020000
1248 if (cur->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2) {
1249 /* Minimum of TLS1.2 required - skip */
1250 }
1251#else
1252 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1253 /* Minimum of TLS1.2 required - skip */
1254 }
1255#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */
1256#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
1257 else if (cur->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
1258 ecjpake_count++;
1259 }
1260#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1261#if MBEDTLS_VERSION_NUMBER >= 0x03060000
1262 else if (cur->min_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3) {
1263 psk_count++;
1264 pki_count++;
1265 }
1266#endif /* MBEDTLS_VERSION_NUMBER >= 0x03060000 */
1267#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1268 else if (coap_ssl_ciphersuite_uses_psk(cur)) {
1269 psk_count++;
1270 }
1271#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1272 else {
1273 pki_count++;
1274 }
1275 }
1276 list++;
1277 }
1278 list = base;
1279
1280 psk_ciphers = mbedtls_malloc(psk_count * sizeof(psk_ciphers[0]));
1281 if (psk_ciphers == NULL) {
1282 coap_log_err("set_ciphers: mbedtls_malloc with count %d failed\n", psk_count);
1283 return;
1284 }
1285 pki_ciphers = mbedtls_malloc(pki_count * sizeof(pki_ciphers[0]));
1286 if (pki_ciphers == NULL) {
1287 coap_log_err("set_ciphers: mbedtls_malloc with count %d failed\n", pki_count);
1288 mbedtls_free(psk_ciphers);
1289 psk_ciphers = NULL;
1290 return;
1291 }
1292#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
1293 ecjpake_ciphers = mbedtls_malloc(ecjpake_count * sizeof(ecjpake_ciphers[0]));
1294 if (ecjpake_ciphers == NULL) {
1295 coap_log_err("set_ciphers: mbedtls_malloc with count %d failed\n", pki_count);
1296 mbedtls_free(psk_ciphers);
1297 mbedtls_free(pki_ciphers);
1298 psk_ciphers = NULL;
1299 pki_ciphers = NULL;
1300 return;
1301 }
1302#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1303
1304 psk_list = psk_ciphers;
1305 pki_list = pki_ciphers;
1306#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
1307 ecjpake_list = ecjpake_ciphers;
1308#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1309
1310 while (*list) {
1311 const mbedtls_ssl_ciphersuite_t *cur =
1312 mbedtls_ssl_ciphersuite_from_id(*list);
1313 if (cur) {
1314#if MBEDTLS_VERSION_NUMBER >= 0x03020000
1315 if (cur->max_tls_version < MBEDTLS_SSL_VERSION_TLS1_2) {
1316 /* Minimum of TLS1.2 required - skip */
1317 }
1318#else
1319 if (cur->max_minor_ver < MBEDTLS_SSL_MINOR_VERSION_3) {
1320 /* Minimum of TLS1.2 required - skip */
1321 }
1322#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */
1323#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED)
1324 else if (cur->key_exchange == MBEDTLS_KEY_EXCHANGE_ECJPAKE) {
1325 *ecjpake_list = *list;
1326 ecjpake_list++;
1327 }
1328#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1329#if MBEDTLS_VERSION_NUMBER >= 0x03060000
1330 else if (cur->min_tls_version >= MBEDTLS_SSL_VERSION_TLS1_3) {
1331 *psk_list = *list;
1332 psk_list++;
1333 *pki_list = *list;
1334 pki_list++;
1335 }
1336#endif /* MBEDTLS_VERSION_NUMBER >= 0x03060000 */
1337#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1338 else if (coap_ssl_ciphersuite_uses_psk(cur)) {
1339 *psk_list = *list;
1340 psk_list++;
1341 }
1342#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1343 else {
1344 *pki_list = *list;
1345 pki_list++;
1346 }
1347 }
1348 list++;
1349 }
1350 /* zero terminate */
1351 *psk_list = 0;
1352 *pki_list = 0;
1353 processed_ciphers = 1;
1354 }
1355 switch (method) {
1356 case COAP_ENC_PSK:
1357 mbedtls_ssl_conf_ciphersuites(conf, psk_ciphers);
1358 break;
1359 case COAP_ENC_PKI:
1360 mbedtls_ssl_conf_ciphersuites(conf, pki_ciphers);
1361 break;
1362 case COAP_ENC_ECJPAKE:
1363 mbedtls_ssl_conf_ciphersuites(conf, ecjpake_ciphers);
1364 break;
1365 default:
1366 assert(0);
1367 break;
1368 }
1369}
1370
1371static int
1372setup_client_ssl_session(coap_session_t *c_session,
1373 coap_mbedtls_env_t *m_env) {
1374 int ret;
1375
1376 coap_mbedtls_context_t *m_context =
1377 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1378
1379 m_context->psk_pki_enabled |= IS_CLIENT;
1380
1381 if ((ret = mbedtls_ssl_config_defaults(&m_env->conf,
1382 MBEDTLS_SSL_IS_CLIENT,
1383 c_session->proto == COAP_PROTO_DTLS ?
1384 MBEDTLS_SSL_TRANSPORT_DATAGRAM :
1385 MBEDTLS_SSL_TRANSPORT_STREAM,
1386 MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
1387 coap_log_err("mbedtls_ssl_config_defaults returned -0x%x: '%s'\n",
1388 -ret, get_error_string(ret));
1389 goto fail;
1390 }
1391
1392#if defined(MBEDTLS_SSL_PROTO_DTLS)
1393 mbedtls_ssl_conf_handshake_timeout(&m_env->conf, COAP_DTLS_RETRANSMIT_MS,
1394 COAP_DTLS_RETRANSMIT_TOTAL_MS);
1395#endif /* MBEDTLS_SSL_PROTO_DTLS */
1396
1397 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_REQUIRED);
1398 mbedtls_ssl_conf_rng(&m_env->conf, mbedtls_ctr_drbg_random, &m_env->ctr_drbg);
1399
1400 if (m_context->psk_pki_enabled & IS_PSK) {
1401#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED)
1402 const coap_bin_const_t *psk_key;
1403 const coap_bin_const_t *psk_identity;
1404
1405 coap_log_info("Setting PSK key\n");
1406
1407 psk_key = coap_get_session_client_psk_key(c_session);
1408 psk_identity = coap_get_session_client_psk_identity(c_session);
1409 if (psk_key == NULL || psk_identity == NULL) {
1410 ret = MBEDTLS_ERR_SSL_ALLOC_FAILED;
1411 goto fail;
1412 }
1413
1414 if ((ret = mbedtls_ssl_conf_psk(&m_env->conf, psk_key->s,
1415 psk_key->length, psk_identity->s,
1416 psk_identity->length)) != 0) {
1417 coap_log_err("mbedtls_ssl_conf_psk returned -0x%x: '%s'\n",
1418 -ret, get_error_string(ret));
1419 goto fail;
1420 }
1421 if (c_session->cpsk_setup_data.client_sni) {
1422 if ((ret = mbedtls_ssl_set_hostname(&m_env->ssl,
1423 c_session->cpsk_setup_data.client_sni)) != 0) {
1424 coap_log_err("mbedtls_ssl_set_hostname returned -0x%x: '%s'\n",
1425 -ret, get_error_string(ret));
1426 goto fail;
1427 }
1428 }
1429 /* Identity Hint currently not supported in Mbed TLS so code removed */
1430
1431#ifdef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
1432 if (c_session->cpsk_setup_data.ec_jpake) {
1433 m_env->ec_jpake = 1;
1434 set_ciphersuites(&m_env->conf, COAP_ENC_ECJPAKE);
1435#if MBEDTLS_VERSION_NUMBER >= 0x03020000
1436 mbedtls_ssl_conf_max_tls_version(&m_env->conf, MBEDTLS_SSL_VERSION_TLS1_2);
1437#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */
1438 } else {
1439 set_ciphersuites(&m_env->conf, COAP_ENC_PSK);
1440 }
1441#else /* ! MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1442 set_ciphersuites(&m_env->conf, COAP_ENC_PSK);
1443#endif /* ! MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1444#else /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1445 coap_log_warn("PSK not enabled in Mbed TLS library\n");
1446#endif /* ! MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */
1447 } else if ((m_context->psk_pki_enabled & IS_PKI) ||
1448 (m_context->psk_pki_enabled & (IS_PSK | IS_PKI)) == 0) {
1449 /*
1450 * If neither PSK or PKI have been set up, use PKI basics.
1451 * This works providing COAP_PKI_KEY_PEM has a value of 0.
1452 */
1453 coap_dtls_pki_t *setup_data = &m_context->setup_data;
1454
1455 if (!(m_context->psk_pki_enabled & IS_PKI)) {
1456 /* PKI not defined - set up some defaults */
1457 setup_data->verify_peer_cert = 1;
1458 setup_data->check_common_ca = 0;
1459 setup_data->allow_self_signed = 1;
1460 setup_data->allow_expired_certs = 1;
1461 setup_data->cert_chain_validation = 1;
1462 setup_data->cert_chain_verify_depth = 2;
1463 setup_data->check_cert_revocation = 1;
1464 setup_data->allow_no_crl = 1;
1465 setup_data->allow_expired_crl = 1;
1466 setup_data->is_rpk_not_cert = 0;
1467 setup_data->use_cid = 0;
1468 }
1469 mbedtls_ssl_conf_authmode(&m_env->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
1470 ret = setup_pki_credentials(&m_env->cacert, &m_env->public_cert,
1471 &m_env->private_key, m_env, m_context,
1472 c_session, setup_data,
1474 if (ret < 0) {
1475 coap_log_err("PKI setup failed\n");
1476 return ret;
1477 }
1478#if defined(MBEDTLS_SSL_SRV_C) && defined(MBEDTLS_SSL_ALPN)
1479 if (c_session->proto == COAP_PROTO_TLS ||
1480 c_session->proto == COAP_PROTO_WSS) {
1481 static const char *alpn_list[] = { "coap", NULL };
1482
1483 ret = mbedtls_ssl_conf_alpn_protocols(&m_env->conf, alpn_list);
1484 if (ret != 0) {
1485 coap_log_err("ALPN setup failed %d)\n", ret);
1486 }
1487 }
1488#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_ALPN */
1489 mbedtls_ssl_set_hostname(&m_env->ssl, m_context->setup_data.client_sni);
1490#if defined(MBEDTLS_SSL_PROTO_DTLS)
1491#if MBEDTLS_VERSION_NUMBER >= 0x02100100
1492 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
1493#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
1494#endif /* MBEDTLS_SSL_PROTO_DTLS */
1495 set_ciphersuites(&m_env->conf, COAP_ENC_PKI);
1496 }
1497 return 0;
1498
1499fail:
1500 return ret;
1501}
1502#endif /* COAP_CLIENT_SUPPORT */
1503
1504static void
1505mbedtls_cleanup(coap_mbedtls_env_t *m_env) {
1506 if (!m_env) {
1507 return;
1508 }
1509
1510 mbedtls_x509_crt_free(&m_env->cacert);
1511 mbedtls_x509_crt_free(&m_env->public_cert);
1512 mbedtls_pk_free(&m_env->private_key);
1513 mbedtls_entropy_free(&m_env->entropy);
1514 mbedtls_ssl_config_free(&m_env->conf);
1515 mbedtls_ctr_drbg_free(&m_env->ctr_drbg);
1516 mbedtls_ssl_free(&m_env->ssl);
1517 mbedtls_ssl_cookie_free(&m_env->cookie_ctx);
1518}
1519
1520static void
1521coap_dtls_free_mbedtls_env(coap_mbedtls_env_t *m_env) {
1522 if (m_env) {
1523 if (!m_env->sent_alert)
1524 mbedtls_ssl_close_notify(&m_env->ssl);
1525 mbedtls_cleanup(m_env);
1526 mbedtls_free(m_env);
1527 }
1528}
1529
1530#if COAP_MAX_LOGGING_LEVEL > 0
1531static const char *
1532report_mbedtls_alert(unsigned char alert) {
1533 switch (alert) {
1534 case MBEDTLS_SSL_ALERT_MSG_BAD_RECORD_MAC:
1535 return ": Bad Record MAC";
1536 case MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE:
1537 return ": Handshake failure";
1538 case MBEDTLS_SSL_ALERT_MSG_NO_CERT:
1539 return ": No Certificate provided";
1540 case MBEDTLS_SSL_ALERT_MSG_BAD_CERT:
1541 return ": Certificate is bad";
1542 case MBEDTLS_SSL_ALERT_MSG_CERT_UNKNOWN:
1543 return ": Certificate is unknown";
1544 case MBEDTLS_SSL_ALERT_MSG_UNKNOWN_CA:
1545 return ": CA is unknown";
1546 case MBEDTLS_SSL_ALERT_MSG_ACCESS_DENIED:
1547 return ": Access was denied";
1548 case MBEDTLS_SSL_ALERT_MSG_DECRYPT_ERROR:
1549 return ": Decrypt error";
1550 default:
1551 return "";
1552 }
1553}
1554#endif /* COAP_MAX_LOGGING_LEVEL */
1555
1556/*
1557 * return -1 failure
1558 * 0 not completed
1559 * 1 established
1560 */
1561static int
1562do_mbedtls_handshake(coap_session_t *c_session,
1563 coap_mbedtls_env_t *m_env) {
1564 int ret;
1565 int alert;
1566
1567 ret = mbedtls_ssl_handshake(&m_env->ssl);
1568 switch (ret) {
1569 case 0:
1570 m_env->established = 1;
1571 coap_log_debug("* %s: Mbed TLS established\n",
1572 coap_session_str(c_session));
1573 ret = 1;
1574#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
1575#if COAP_CLIENT_SUPPORT
1576 if (c_session->type == COAP_SESSION_TYPE_CLIENT &&
1577 c_session->proto == COAP_PROTO_DTLS) {
1578 coap_mbedtls_context_t *m_context;
1579
1580 m_context = (coap_mbedtls_context_t *)c_session->context->dtls_context;
1581 if ((m_context->psk_pki_enabled & IS_PSK && c_session->cpsk_setup_data.use_cid) ||
1582 m_context->setup_data.use_cid) {
1583 unsigned char peer_cid[MBEDTLS_SSL_CID_OUT_LEN_MAX];
1584 int enabled;
1585 size_t peer_cid_len;
1586
1587 /* See whether CID was negotiated */
1588 if (mbedtls_ssl_get_peer_cid(&m_env->ssl, &enabled, peer_cid, &peer_cid_len) == 0 &&
1589 enabled == MBEDTLS_SSL_CID_ENABLED) {
1590 c_session->negotiated_cid = 1;
1591 } else {
1592 coap_log_info("** %s: CID was not negotiated\n", coap_session_str(c_session));
1593 c_session->negotiated_cid = 0;
1594 }
1595 }
1596 }
1597#endif /* COAP_CLIENT_SUPPORT */
1598#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
1599 break;
1600 case MBEDTLS_ERR_SSL_WANT_READ:
1601 case MBEDTLS_ERR_SSL_WANT_WRITE:
1602 if (m_env->ssl.state == MBEDTLS_SSL_SERVER_HELLO
1603#if MBEDTLS_VERSION_NUMBER >= 0x03030000
1604 || m_env->ssl.state == MBEDTLS_SSL_NEW_SESSION_TICKET
1605#endif /* MBEDTLS_VERSION_NUMBER >= 0x03030000 */
1606 ) {
1607 if (++m_env->server_hello_cnt > 10) {
1608 /* retried this too many times */
1609 goto fail;
1610 }
1611 }
1612 errno = EAGAIN;
1613 ret = 0;
1614 break;
1615 case MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED:
1616 coap_log_debug("hello verification requested\n");
1617 goto reset;
1618 case MBEDTLS_ERR_SSL_INVALID_MAC:
1619 goto fail;
1620#ifdef MBEDTLS_2_X_COMPAT
1621 case MBEDTLS_ERR_SSL_UNKNOWN_CIPHER:
1622#else /* ! MBEDTLS_2_X_COMPAT */
1623 case MBEDTLS_ERR_SSL_DECODE_ERROR:
1624#endif /* ! MBEDTLS_2_X_COMPAT */
1625 goto fail;
1626 case MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE:
1627 alert = MBEDTLS_SSL_ALERT_MSG_NO_CERT;
1628 goto fail_alert;
1629#ifdef MBEDTLS_2_X_COMPAT
1630 case MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO:
1631 case MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO:
1632 alert = MBEDTLS_SSL_ALERT_MSG_HANDSHAKE_FAILURE;
1633 goto fail_alert;
1634#endif /* MBEDTLS_2_X_COMPAT */
1635 case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
1636 goto fail;
1637 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
1638 if (m_env->ssl.in_msg[1] != MBEDTLS_SSL_ALERT_MSG_CLOSE_NOTIFY)
1639 coap_log_warn("***%s: Alert '%d'%s\n",
1640 coap_session_str(c_session), m_env->ssl.in_msg[1],
1641 report_mbedtls_alert(m_env->ssl.in_msg[1]));
1642 /* Fall through */
1643 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
1644 case MBEDTLS_ERR_SSL_CONN_EOF:
1645 case MBEDTLS_ERR_NET_CONN_RESET:
1647 ret = -1;
1648 break;
1649 default:
1650 coap_log_warn("do_mbedtls_handshake: session establish "
1651 "returned -0x%x: '%s'\n",
1652 -ret, get_error_string(ret));
1653 ret = -1;
1654 break;
1655 }
1656 return ret;
1657
1658fail_alert:
1659 mbedtls_ssl_send_alert_message(&m_env->ssl,
1660 MBEDTLS_SSL_ALERT_LEVEL_FATAL,
1661 alert);
1662 m_env->sent_alert = 1;
1663fail:
1664 c_session->dtls_event = COAP_EVENT_DTLS_ERROR;
1665 coap_log_warn("do_mbedtls_handshake: session establish "
1666 "returned '%s'\n",
1667 get_error_string(ret));
1668reset:
1669 mbedtls_ssl_session_reset(&m_env->ssl);
1670#ifdef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
1671 if (m_env->ec_jpake) {
1672 const coap_bin_const_t *psk_key;
1673
1674#if COAP_CLIENT_SUPPORT && COAP_SERVER_SUPPORT
1675 if (c_session->type == COAP_SESSION_TYPE_CLIENT) {
1676 psk_key = coap_get_session_client_psk_key(c_session);
1677 } else {
1678 psk_key = coap_get_session_server_psk_key(c_session);
1679 }
1680#elif COAP_CLIENT_SUPPORT
1681 psk_key = coap_get_session_client_psk_key(c_session);
1682#else /* COAP_SERVER_SUPPORT */
1683 psk_key = coap_get_session_server_psk_key(c_session);
1684#endif /* COAP_SERVER_SUPPORT */
1685 if (psk_key) {
1686 mbedtls_ssl_set_hs_ecjpake_password(&m_env->ssl, psk_key->s, psk_key->length);
1687 }
1688 }
1689#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1690 return -1;
1691}
1692
1693static void
1694mbedtls_debug_out(void *ctx COAP_UNUSED, int level,
1695 const char *file COAP_UNUSED,
1696 int line COAP_UNUSED, const char *str) {
1697
1698 coap_log_t coap_level = COAP_LOG_DEBUG;
1699 /*
1700 * 0 No debug
1701 * 1 Error
1702 * 2 State change
1703 * 3 Informational
1704 * 4 Verbose
1705 */
1706 switch (level) {
1707 case 0:
1708 coap_level = COAP_LOG_EMERG;
1709 break;
1710 case 1:
1711 coap_level = COAP_LOG_WARN;
1712 break;
1713 case 2:
1714 coap_level = COAP_LOG_NOTICE;
1715 break;
1716 case 3:
1717 coap_level = COAP_LOG_INFO;
1718 break;
1719 case 4:
1720 default:
1721 coap_level = COAP_LOG_DEBUG;
1722 break;
1723 }
1724 coap_dtls_log(coap_level, "%s", str);
1725}
1726
1727#if !COAP_DISABLE_TCP
1728/*
1729 * strm
1730 * return +ve data amount
1731 * 0 no more
1732 * -ve Mbed TLS error
1733 */
1734static int
1735coap_sock_read(void *ctx, unsigned char *out, size_t outl) {
1736 int ret = MBEDTLS_ERR_SSL_CONN_EOF;
1737 coap_session_t *c_session = (coap_session_t *)ctx;
1738
1739 if (out != NULL) {
1740 ret = (int)c_session->sock.lfunc[COAP_LAYER_TLS].l_read(c_session, out, outl);
1741 /* Translate layer returns into what MbedTLS expects */
1742 if (ret == -1) {
1743 if (errno == ECONNRESET) {
1744 /* graceful shutdown */
1745 ret = MBEDTLS_ERR_SSL_CONN_EOF;
1746 } else {
1747 ret = MBEDTLS_ERR_NET_RECV_FAILED;
1748 }
1749 } else if (ret == 0) {
1750 errno = EAGAIN;
1751 ret = MBEDTLS_ERR_SSL_WANT_READ;
1752 }
1753 }
1754 return ret;
1755}
1756
1757/*
1758 * strm
1759 * return +ve data amount
1760 * 0 no more
1761 * -ve Mbed TLS error
1762 */
1763static int
1764coap_sock_write(void *context, const unsigned char *in, size_t inl) {
1765 int ret = 0;
1766 coap_session_t *c_session = (coap_session_t *)context;
1767
1768 ret = c_session->sock.lfunc[COAP_LAYER_TLS].l_write(c_session,
1769 (const uint8_t *)in,
1770 inl);
1771 /* Translate layer what returns into what MbedTLS expects */
1772 if (ret < 0) {
1773 if ((c_session->state == COAP_SESSION_STATE_CSM ||
1774 c_session->state == COAP_SESSION_STATE_HANDSHAKE) &&
1775 (errno == EPIPE || errno == ECONNRESET)) {
1776 /*
1777 * Need to handle a TCP timing window where an agent continues with
1778 * the sending of the next handshake or a CSM.
1779 * However, the peer does not like a certificate and so sends a
1780 * fatal alert and closes the TCP session.
1781 * The sending of the next handshake or CSM may get terminated because
1782 * of the closed TCP session, but there is still an outstanding alert
1783 * to be read in and reported on.
1784 * In this case, pretend that sending the info was fine so that the
1785 * alert can be read (which effectively is what happens with DTLS).
1786 */
1787 ret = inl;
1788 } else {
1789#ifdef _WIN32
1790 int lasterror = WSAGetLastError();
1791
1792 if (lasterror == WSAEWOULDBLOCK) {
1793 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1794 } else if (lasterror == WSAECONNRESET) {
1795 ret = MBEDTLS_ERR_NET_CONN_RESET;
1796 }
1797#else
1798 if (errno == EAGAIN || errno == EINTR) {
1799 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1800 } else if (errno == EPIPE || errno == ECONNRESET) {
1801 ret = MBEDTLS_ERR_NET_CONN_RESET;
1802 }
1803#endif
1804 else {
1805 ret = MBEDTLS_ERR_NET_SEND_FAILED;
1806 }
1807 coap_log_debug("* %s: failed to send %zd bytes (%s) state %d\n",
1808 coap_session_str(c_session), inl, coap_socket_strerror(),
1809 c_session->state);
1810 }
1811 }
1812 if (ret == 0) {
1813 errno = EAGAIN;
1814 ret = MBEDTLS_ERR_SSL_WANT_WRITE;
1815 }
1816 return ret;
1817}
1818#endif /* !COAP_DISABLE_TCP */
1819
1820static coap_mbedtls_env_t *
1821coap_dtls_new_mbedtls_env(coap_session_t *c_session,
1822 coap_dtls_role_t role,
1823 coap_proto_t proto) {
1824 int ret = 0;
1825 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
1826
1827 if (m_env)
1828 return m_env;
1829
1830 m_env = (coap_mbedtls_env_t *)mbedtls_malloc(sizeof(coap_mbedtls_env_t));
1831 if (!m_env) {
1832 return NULL;
1833 }
1834 memset(m_env, 0, sizeof(coap_mbedtls_env_t));
1835
1836 mbedtls_ssl_init(&m_env->ssl);
1837 mbedtls_ctr_drbg_init(&m_env->ctr_drbg);
1838 mbedtls_ssl_config_init(&m_env->conf);
1839 mbedtls_entropy_init(&m_env->entropy);
1840
1841#if defined(MBEDTLS_PSA_CRYPTO_C)
1842 psa_crypto_init();
1843#endif /* MBEDTLS_PSA_CRYPTO_C */
1844
1845#if defined(ESPIDF_VERSION) && defined(CONFIG_MBEDTLS_DEBUG)
1846 mbedtls_esp_enable_debug_log(&m_env->conf, CONFIG_MBEDTLS_DEBUG_LEVEL);
1847#endif /* ESPIDF_VERSION && CONFIG_MBEDTLS_DEBUG */
1848 if ((ret = mbedtls_ctr_drbg_seed(&m_env->ctr_drbg,
1849 mbedtls_entropy_func, &m_env->entropy, NULL, 0)) != 0) {
1850 if (ret != MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) {
1851 coap_log_info("mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n",
1852 -ret, get_error_string(ret));
1853 goto fail;
1854 }
1855 coap_log_err("mbedtls_ctr_drbg_seed returned -0x%x: '%s'\n",
1856 -ret, get_error_string(ret));
1857 }
1858
1859 if (role == COAP_DTLS_ROLE_CLIENT) {
1860#if COAP_CLIENT_SUPPORT
1861 if (setup_client_ssl_session(c_session, m_env) != 0) {
1862 goto fail;
1863 }
1864#else /* !COAP_CLIENT_SUPPORT */
1865 goto fail;
1866#endif /* !COAP_CLIENT_SUPPORT */
1867 } else if (role == COAP_DTLS_ROLE_SERVER) {
1868#if defined(MBEDTLS_SSL_SRV_C)
1869 if (setup_server_ssl_session(c_session, m_env) != 0) {
1870 goto fail;
1871 }
1872#else /* ! MBEDTLS_SSL_SRV_C */
1873 goto fail;
1874#endif /* ! MBEDTLS_SSL_SRV_C */
1875 } else {
1876 goto fail;
1877 }
1878
1879#if MBEDTLS_VERSION_NUMBER >= 0x03020000
1880 mbedtls_ssl_conf_min_tls_version(&m_env->conf, MBEDTLS_SSL_VERSION_TLS1_2);
1881#else
1882 mbedtls_ssl_conf_min_version(&m_env->conf, MBEDTLS_SSL_MAJOR_VERSION_3,
1883 MBEDTLS_SSL_MINOR_VERSION_3);
1884#endif /* MBEDTLS_VERSION_NUMBER >= 0x03020000 */
1885
1886 if (mbedtls_ssl_setup(&m_env->ssl, &m_env->conf) != 0) {
1887 goto fail;
1888 }
1889 if (proto == COAP_PROTO_DTLS) {
1890 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_dgram_write,
1891 coap_dgram_read, NULL);
1892#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
1893 if (COAP_PROTO_NOT_RELIABLE(c_session->proto)) {
1894 if (role == COAP_DTLS_ROLE_CLIENT) {
1895#if COAP_CLIENT_SUPPORT
1896 coap_mbedtls_context_t *m_context =
1897 (coap_mbedtls_context_t *)c_session->context->dtls_context;
1898
1899 if ((m_context->psk_pki_enabled & IS_PSK && c_session->cpsk_setup_data.use_cid) ||
1900 m_context->setup_data.use_cid) {
1901 /*
1902 * Enable passive DTLS CID support.
1903 *
1904 * Note: Set MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT to 0 (the default)
1905 * to use RFC9146 extension ID of 54, rather than the draft version -05
1906 * value of 254.
1907 */
1908 mbedtls_ssl_set_cid(&m_env->ssl, MBEDTLS_SSL_CID_ENABLED, NULL, 0);
1909 }
1910#endif /* COAP_CLIENT_SUPPORT */
1911 } else {
1912#if COAP_SERVER_SUPPORT
1913 uint8_t cid[COAP_DTLS_CID_LENGTH];
1914 /*
1915 * Enable server DTLS CID support.
1916 *
1917 * Note: Set MBEDTLS_SSL_DTLS_CONNECTION_ID_COMPAT to 0 (the default)
1918 * to use RFC9146 extension ID of 54, rather than the draft version -05
1919 * value of 254.
1920 */
1921 coap_prng_lkd(cid, sizeof(cid));
1922 mbedtls_ssl_set_cid(&m_env->ssl, MBEDTLS_SSL_CID_ENABLED, cid,
1923 sizeof(cid));
1924 c_session->client_cid = coap_new_bin_const(cid, sizeof(cid));
1925#endif /* COAP_SERVER_SUPPORT */
1926 }
1927 }
1928#endif /* MBEDTLS_SSL_DTLS_CONNECTION_ID */
1929 }
1930#if !COAP_DISABLE_TCP
1931 else {
1932 assert(proto == COAP_PROTO_TLS);
1933 mbedtls_ssl_set_bio(&m_env->ssl, c_session, coap_sock_write,
1934 coap_sock_read, NULL);
1935 }
1936#endif /* ! COAP_DISABLE_TCP */
1937#ifdef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
1938 coap_mbedtls_context_t *m_context =
1939 ((coap_mbedtls_context_t *)c_session->context->dtls_context);
1940 if ((m_context->psk_pki_enabled & IS_PSK) &&
1941 m_env->ec_jpake) {
1942 const coap_bin_const_t *psk_key;
1943
1944#if COAP_CLIENT_SUPPORT && COAP_SERVER_SUPPORT
1945 if (role == COAP_DTLS_ROLE_CLIENT) {
1946 psk_key = coap_get_session_client_psk_key(c_session);
1947 } else {
1948 psk_key = coap_get_session_server_psk_key(c_session);
1949 }
1950#elif COAP_CLIENT_SUPPORT
1951 psk_key = coap_get_session_client_psk_key(c_session);
1952#else /* COAP_SERVER_SUPPORT */
1953 psk_key = coap_get_session_server_psk_key(c_session);
1954#endif /* COAP_SERVER_SUPPORT */
1955 mbedtls_ssl_set_hs_ecjpake_password(&m_env->ssl, psk_key->s, psk_key->length);
1956 }
1957#endif /* MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
1958#ifdef __ZEPHYR__
1959 mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer,
1960 zephyr_timing_set_delay,
1961 zephyr_timing_get_delay);
1962#else
1963 mbedtls_ssl_set_timer_cb(&m_env->ssl, &m_env->timer,
1964 mbedtls_timing_set_delay,
1965 mbedtls_timing_get_delay);
1966#endif
1967
1968 mbedtls_ssl_conf_dbg(&m_env->conf, mbedtls_debug_out, stdout);
1969 return m_env;
1970
1971fail:
1972 if (m_env) {
1973 mbedtls_free(m_env);
1974 }
1975 return NULL;
1976}
1977
1978int
1980#if defined(MBEDTLS_SSL_PROTO_DTLS)
1981 return 1;
1982#else /* !MBEDTLS_SSL_PROTO_DTLS */
1983 static int reported = 0;
1984 if (!reported) {
1985 reported = 1;
1986 coap_log_emerg("libcoap not compiled for DTLS with Mbed TLS"
1987 " - update Mbed TLS to include DTLS\n");
1988 }
1989 return 0;
1990#endif /* !MBEDTLS_SSL_PROTO_DTLS */
1991}
1992
1993int
1995#if !COAP_DISABLE_TCP
1996 return 1;
1997#else /* COAP_DISABLE_TCP */
1998 return 0;
1999#endif /* COAP_DISABLE_TCP */
2000}
2001
2002/*
2003 * return 0 failed
2004 * 1 passed
2005 */
2006int
2008 return 1;
2009}
2010
2011/*
2012 * return 0 failed
2013 * 1 passed
2014 */
2015int
2017 return 1;
2018}
2019
2020/*
2021 * return 0 failed
2022 * 1 passed
2023 */
2024int
2026 return 0;
2027}
2028
2029/*
2030 * return 0 failed
2031 * 1 passed
2032 */
2033int
2035 return 0;
2036}
2037
2038/*
2039 * return 0 failed
2040 * 1 passed
2041 */
2042int
2044#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
2045 return 1;
2046#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2047 return 0;
2048#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2049}
2050
2051#if COAP_CLIENT_SUPPORT
2052int
2053coap_dtls_set_cid_tuple_change(coap_context_t *c_context, uint8_t every) {
2054#ifdef MBEDTLS_SSL_DTLS_CONNECTION_ID
2055 c_context->testing_cids = every;
2056 return 1;
2057#else /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2058 (void)c_context;
2059 (void)every;
2060 return 0;
2061#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2062}
2063#endif /* COAP_CLIENT_SUPPORT */
2064
2065void *
2067 coap_mbedtls_context_t *m_context;
2068 (void)c_context;
2069
2070 m_context = (coap_mbedtls_context_t *)mbedtls_malloc(sizeof(coap_mbedtls_context_t));
2071 if (m_context) {
2072 memset(m_context, 0, sizeof(coap_mbedtls_context_t));
2073 }
2074 return m_context;
2075}
2076
2077#if COAP_SERVER_SUPPORT
2078/*
2079 * return 0 failed
2080 * 1 passed
2081 */
2082int
2084 coap_dtls_spsk_t *setup_data
2085 ) {
2086 coap_mbedtls_context_t *m_context =
2087 ((coap_mbedtls_context_t *)c_context->dtls_context);
2088
2089#if !defined(MBEDTLS_SSL_SRV_C)
2090 coap_log_emerg("coap_context_set_spsk:"
2091 " libcoap not compiled for Server Mode for Mbed TLS"
2092 " - update Mbed TLS to include Server Mode\n");
2093 return 0;
2094#endif /* !MBEDTLS_SSL_SRV_C */
2095 if (!m_context || !setup_data)
2096 return 0;
2097
2098 if (setup_data->ec_jpake) {
2099#ifndef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
2100 coap_log_warn("Mbed TLS not compiled for EC-JPAKE support\n");
2101#endif /* ! MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
2102 }
2103 m_context->psk_pki_enabled |= IS_PSK;
2104 return 1;
2105}
2106#endif /* COAP_SERVER_SUPPORT */
2107
2108#if COAP_CLIENT_SUPPORT
2109/*
2110 * return 0 failed
2111 * 1 passed
2112 */
2113int
2115 coap_dtls_cpsk_t *setup_data
2116 ) {
2117#if !defined(MBEDTLS_SSL_CLI_C)
2118 (void)c_context;
2119 (void)setup_data;
2120
2121 coap_log_emerg("coap_context_set_cpsk:"
2122 " libcoap not compiled for Client Mode for Mbed TLS"
2123 " - update Mbed TLS to include Client Mode\n");
2124 return 0;
2125#else /* MBEDTLS_SSL_CLI_C */
2126 coap_mbedtls_context_t *m_context =
2127 ((coap_mbedtls_context_t *)c_context->dtls_context);
2128
2129 if (!m_context || !setup_data)
2130 return 0;
2131
2132 if (setup_data->validate_ih_call_back) {
2133 coap_log_warn("CoAP Client with Mbed TLS does not support Identity Hint selection\n");
2134 }
2135 if (setup_data->ec_jpake) {
2136#ifndef MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED
2137 coap_log_warn("Mbed TLS not compiled for EC-JPAKE support\n");
2138#endif /* ! MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED */
2139 }
2140 if (setup_data->use_cid) {
2141#ifndef MBEDTLS_SSL_DTLS_CONNECTION_ID
2142 coap_log_warn("Mbed TLS not compiled for Connection-ID support\n");
2143#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2144 }
2145 m_context->psk_pki_enabled |= IS_PSK;
2146 return 1;
2147#endif /* MBEDTLS_SSL_CLI_C */
2148}
2149#endif /* COAP_CLIENT_SUPPORT */
2150
2151int
2153 const coap_dtls_pki_t *setup_data,
2154 const coap_dtls_role_t role COAP_UNUSED) {
2155 coap_mbedtls_context_t *m_context =
2156 ((coap_mbedtls_context_t *)c_context->dtls_context);
2157
2158 m_context->setup_data = *setup_data;
2159 if (!m_context->setup_data.verify_peer_cert) {
2160 /* Needs to be clear so that no CA DNs are transmitted */
2161 m_context->setup_data.check_common_ca = 0;
2162 /* Allow all of these but warn if issue */
2163 m_context->setup_data.allow_self_signed = 1;
2164 m_context->setup_data.allow_expired_certs = 1;
2165 m_context->setup_data.cert_chain_validation = 1;
2166 m_context->setup_data.cert_chain_verify_depth = 10;
2167 m_context->setup_data.check_cert_revocation = 1;
2168 m_context->setup_data.allow_no_crl = 1;
2169 m_context->setup_data.allow_expired_crl = 1;
2170 m_context->setup_data.allow_bad_md_hash = 1;
2171 m_context->setup_data.allow_short_rsa_length = 1;
2172 }
2173 m_context->psk_pki_enabled |= IS_PKI;
2174 if (setup_data->use_cid) {
2175#ifndef MBEDTLS_SSL_DTLS_CONNECTION_ID
2176 coap_log_warn("Mbed TLS not compiled for Connection-ID support\n");
2177#endif /* ! MBEDTLS_SSL_DTLS_CONNECTION_ID */
2178 }
2179 return 1;
2180}
2181
2182int
2184 const char *ca_file,
2185 const char *ca_path) {
2186 coap_mbedtls_context_t *m_context =
2187 ((coap_mbedtls_context_t *)c_context->dtls_context);
2188
2189 if (!m_context) {
2190 coap_log_warn("coap_context_set_pki_root_cas: (D)TLS environment "
2191 "not set up\n");
2192 return 0;
2193 }
2194
2195 if (ca_file == NULL && ca_path == NULL) {
2196 coap_log_warn("coap_context_set_pki_root_cas: ca_file and/or ca_path "
2197 "not defined\n");
2198 return 0;
2199 }
2200 if (m_context->root_ca_file) {
2201 mbedtls_free(m_context->root_ca_file);
2202 m_context->root_ca_file = NULL;
2203 }
2204
2205 if (ca_file) {
2206 m_context->root_ca_file = mbedtls_strdup(ca_file);
2207 }
2208
2209 if (m_context->root_ca_path) {
2210 mbedtls_free(m_context->root_ca_path);
2211 m_context->root_ca_path = NULL;
2212 }
2213
2214 if (ca_path) {
2215 m_context->root_ca_path = mbedtls_strdup(ca_path);
2216 }
2217 return 1;
2218}
2219
2220/*
2221 * return 0 failed
2222 * 1 passed
2223 */
2224int
2226 coap_mbedtls_context_t *m_context =
2227 ((coap_mbedtls_context_t *)c_context->dtls_context);
2228
2229 if (!m_context) {
2230 coap_log_warn("coap_context_load_pki_trust_store: (D)TLS environment "
2231 "not set up\n");
2232 return 0;
2233 }
2234 m_context->trust_store_defined = 1;
2235
2236 /* No proper support for this in MbedTLS at this point */
2237 return 1;
2238}
2239
2240
2241int
2243 coap_mbedtls_context_t *m_context =
2244 ((coap_mbedtls_context_t *)c_context->dtls_context);
2245 return m_context->psk_pki_enabled ? 1 : 0;
2246}
2247
2248void
2249coap_dtls_free_context(void *dtls_context) {
2250 coap_mbedtls_context_t *m_context = (coap_mbedtls_context_t *)dtls_context;
2251 unsigned int i;
2252
2253 for (i = 0; i < m_context->pki_sni_count; i++) {
2254 mbedtls_free(m_context->pki_sni_entry_list[i].sni);
2255
2256 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].public_cert);
2257
2258 mbedtls_pk_free(&m_context->pki_sni_entry_list[i].private_key);
2259
2260 mbedtls_x509_crt_free(&m_context->pki_sni_entry_list[i].cacert);
2261 }
2262 if (m_context->pki_sni_entry_list)
2263 mbedtls_free(m_context->pki_sni_entry_list);
2264
2265 for (i = 0; i < m_context->psk_sni_count; i++) {
2266 mbedtls_free(m_context->psk_sni_entry_list[i].sni);
2267 }
2268 if (m_context->psk_sni_entry_list)
2269 mbedtls_free(m_context->psk_sni_entry_list);
2270
2271 if (m_context->root_ca_path)
2272 mbedtls_free(m_context->root_ca_path);
2273 if (m_context->root_ca_file)
2274 mbedtls_free(m_context->root_ca_file);
2275
2276 mbedtls_free(m_context);
2277}
2278
2279#if COAP_CLIENT_SUPPORT
2280void *
2282#if !defined(MBEDTLS_SSL_CLI_C)
2283 (void)c_session;
2284 coap_log_emerg("coap_dtls_new_client_session:"
2285 " libcoap not compiled for Client Mode for Mbed TLS"
2286 " - update Mbed TLS to include Client Mode\n");
2287 return NULL;
2288#else /* MBEDTLS_SSL_CLI_C */
2289 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
2292 int ret;
2293
2294 if (m_env) {
2295 coap_tick_t now;
2296
2297 coap_ticks(&now);
2298 m_env->last_timeout = now;
2299 ret = do_mbedtls_handshake(c_session, m_env);
2300 if (ret == -1) {
2301 coap_dtls_free_mbedtls_env(m_env);
2302 return NULL;
2303 }
2304 }
2305 return m_env;
2306#endif /* MBEDTLS_SSL_CLI_C */
2307}
2308#endif /* COAP_CLIENT_SUPPORT */
2309
2310#if COAP_SERVER_SUPPORT
2311void *
2313#if !defined(MBEDTLS_SSL_SRV_C)
2314 (void)c_session;
2315 coap_log_emerg("coap_dtls_new_server_session:"
2316 " libcoap not compiled for Server Mode for Mbed TLS"
2317 " - update Mbed TLS to include Server Mode\n");
2318 return NULL;
2319#else /* MBEDTLS_SSL_SRV_C */
2320 coap_mbedtls_env_t *m_env =
2321 (coap_mbedtls_env_t *)c_session->tls;
2322 if (m_env) {
2323#if defined(MBEDTLS_SSL_PROTO_DTLS)
2324#if MBEDTLS_VERSION_NUMBER >= 0x02100100
2325 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
2326#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
2327#endif /* MBEDTLS_SSL_PROTO_DTLS */
2328 }
2329 return m_env;
2330#endif /* MBEDTLS_SSL_SRV_C */
2331}
2332#endif /* COAP_SERVER_SUPPORT */
2333
2334void
2336 if (c_session && c_session->context && c_session->tls) {
2337 coap_dtls_free_mbedtls_env(c_session->tls);
2338 c_session->tls = NULL;
2340 }
2341 return;
2342}
2343
2344void
2346#if defined(MBEDTLS_SSL_PROTO_DTLS)
2347 coap_mbedtls_env_t *m_env =
2348 (coap_mbedtls_env_t *)c_session->tls;
2349 if (m_env) {
2350#if MBEDTLS_VERSION_NUMBER >= 0x02100100
2351 mbedtls_ssl_set_mtu(&m_env->ssl, (uint16_t)c_session->mtu);
2352#endif /* MBEDTLS_VERSION_NUMBER >= 0x02100100 */
2353 }
2354#else /* ! MBEDTLS_SSL_PROTO_DTLS */
2355 (void)c_session;
2356#endif /* MBEDTLS_SSL_PROTO_DTLS */
2357}
2358
2359ssize_t
2361 const uint8_t *data, size_t data_len) {
2362 int ret;
2363 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2364
2365 assert(m_env != NULL);
2366
2367 if (!m_env) {
2368 return -1;
2369 }
2370 c_session->dtls_event = -1;
2371 coap_log_debug("* %s: dtls: sent %4d bytes\n",
2372 coap_session_str(c_session), (int)data_len);
2373 if (m_env->established) {
2374 ret = mbedtls_ssl_write(&m_env->ssl, (const unsigned char *) data, data_len);
2375 if (ret <= 0) {
2376 switch (ret) {
2377 case MBEDTLS_ERR_SSL_WANT_READ:
2378 case MBEDTLS_ERR_SSL_WANT_WRITE:
2379 ret = 0;
2380 break;
2381 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2383 ret = -1;
2384 break;
2385 default:
2386 coap_log_warn("coap_dtls_send: "
2387 "returned -0x%x: '%s'\n",
2388 -ret, get_error_string(ret));
2389 ret = -1;
2390 break;
2391 }
2392 if (ret == -1) {
2393 coap_log_warn("coap_dtls_send: cannot send PDU\n");
2394 }
2395 }
2396 } else {
2397 ret = do_mbedtls_handshake(c_session, m_env);
2398 if (ret == 1) {
2399 /* Just connected, so send the data */
2400 return coap_dtls_send(c_session, data, data_len);
2401 }
2402 ret = -1;
2403 }
2404
2405 if (c_session->dtls_event >= 0) {
2406 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2407 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2408 coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session);
2409 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2410 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2412 ret = -1;
2413 }
2414 }
2415 return ret;
2416}
2417
2418int
2420 return 0;
2421}
2422
2424coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED) {
2425 return 0;
2426}
2427
2430 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2431#ifdef __ZEPHYR__
2432 int ret = zephyr_timing_get_delay(&m_env->timer);
2433#else
2434 int ret = mbedtls_timing_get_delay(&m_env->timer);
2435#endif
2436 unsigned int scalar = 1 << m_env->retry_scalar;
2437
2438 assert(c_session->state == COAP_SESSION_STATE_HANDSHAKE);
2439 switch (ret) {
2440 case 0:
2441 /* int_ms has not timed out */
2442 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
2443 /* Need to indicate remaining timeout time */
2444 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
2445 }
2446 m_env->last_timeout = now;
2447 /* This may cause a minor extra delay */
2448 return now + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
2449 case 1:
2450 /* int_ms has timed out, but not fin_ms */
2451 /*
2452 * Need to make sure that we do not do this too frequently
2453 */
2454 if (m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar > now) {
2455 return m_env->last_timeout + COAP_DTLS_RETRANSMIT_COAP_TICKS * scalar;
2456 }
2457
2458 /* Reset for the next time */
2459 m_env->last_timeout = now;
2460 return now;
2461 case 2:
2462 /* fin_ms has timed out - timed out - one final try */
2463 return now;
2464 default:
2465 break;
2466 }
2467
2468 return 0;
2469}
2470
2471/*
2472 * return 1 timed out
2473 * 0 still timing out
2474 */
2475int
2477 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2478
2479 assert(m_env != NULL && c_session->state == COAP_SESSION_STATE_HANDSHAKE);
2480 m_env->retry_scalar++;
2481 if ((++c_session->dtls_timeout_count > c_session->max_retransmit) ||
2482 (do_mbedtls_handshake(c_session, m_env) < 0)) {
2483 /* Too many retries */
2485 return 1;
2486 }
2487 return 0;
2488}
2489
2490/*
2491 * return +ve data amount
2492 * 0 no more
2493 * -1 error
2494 */
2495int
2497 const uint8_t *data,
2498 size_t data_len) {
2499 int ret = 1;
2500
2501 c_session->dtls_event = -1;
2502 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2503 coap_ssl_t *ssl_data;
2504
2505 assert(m_env != NULL);
2506
2507 ssl_data = &m_env->coap_ssl_data;
2508 if (ssl_data->pdu_len) {
2509 coap_log_err("** %s: Previous data not read %u bytes\n",
2510 coap_session_str(c_session), ssl_data->pdu_len);
2511 }
2512 ssl_data->pdu = data;
2513 ssl_data->pdu_len = (unsigned)data_len;
2514
2515 if (m_env->established) {
2516#if COAP_CONSTRAINED_STACK
2517 /* pdu can be protected by global_lock if needed */
2518 static uint8_t pdu[COAP_RXBUFFER_SIZE];
2519#else /* ! COAP_CONSTRAINED_STACK */
2520 uint8_t pdu[COAP_RXBUFFER_SIZE];
2521#endif /* ! COAP_CONSTRAINED_STACK */
2522
2523 if (c_session->state == COAP_SESSION_STATE_HANDSHAKE) {
2525 c_session);
2526 c_session->sock.lfunc[COAP_LAYER_TLS].l_establish(c_session);
2527 }
2528
2529 ret = mbedtls_ssl_read(&m_env->ssl, pdu, sizeof(pdu));
2530 if (ret > 0) {
2531 coap_log_debug("* %s: dtls: recv %4d bytes\n",
2532 coap_session_str(c_session), ret);
2533 ret = coap_handle_dgram(c_session->context, c_session, pdu, (size_t)ret);
2534 goto finish;
2535 }
2536 switch (ret) {
2537 case 0:
2538 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
2539 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2541 break;
2542 case MBEDTLS_ERR_SSL_WANT_READ:
2543 break;
2544 default:
2545 coap_log_warn("coap_dtls_receive: "
2546 "returned -0x%x: '%s' (length %zd)\n",
2547 -ret, get_error_string(ret), data_len);
2548 break;
2549 }
2550 ret = -1;
2551 } else {
2552 ret = do_mbedtls_handshake(c_session, m_env);
2553 if (ret == 1) {
2554 /* Just connected, so send the data */
2555 coap_session_connected(c_session);
2556 } else {
2557 if (ssl_data->pdu_len) {
2558 /* Do the handshake again incase of internal timeout */
2559 ret = do_mbedtls_handshake(c_session, m_env);
2560 if (ret == 1) {
2561 /* Just connected, so send the data */
2562 coap_session_connected(c_session);
2563 }
2564 }
2565 ret = -1;
2566 }
2567 }
2568 if (c_session->dtls_event >= 0) {
2569 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2570 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2571 coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session);
2572 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2573 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2575 ssl_data = NULL;
2576 ret = -1;
2577 }
2578 }
2579finish:
2580 if (ssl_data && ssl_data->pdu_len) {
2581 /* pdu data is held on stack which will not stay there */
2582 coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
2583 ssl_data->pdu_len = 0;
2584 ssl_data->pdu = NULL;
2585 }
2586 return ret;
2587}
2588
2589#if COAP_SERVER_SUPPORT
2590/*
2591 * return -1 failure
2592 * 0 not completed
2593 * 1 client hello seen
2594 */
2595int
2597 const uint8_t *data,
2598 size_t data_len) {
2599#if !defined(MBEDTLS_SSL_PROTO_DTLS) || !defined(MBEDTLS_SSL_SRV_C)
2600 (void)c_session;
2601 (void)data;
2602 (void)data_len;
2603 coap_log_emerg("coap_dtls_hello:"
2604 " libcoap not compiled for DTLS or Server Mode for Mbed TLS"
2605 " - update Mbed TLS to include DTLS and Server Mode\n");
2606 return -1;
2607#else /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
2608 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2609 coap_ssl_t *ssl_data;
2610 int ret;
2611
2612 if (!m_env) {
2613 m_env = coap_dtls_new_mbedtls_env(c_session, COAP_DTLS_ROLE_SERVER,
2615 if (m_env) {
2616 c_session->tls = m_env;
2617 } else {
2618 /* error should have already been reported */
2619 return -1;
2620 }
2621 }
2622
2623 if ((ret = mbedtls_ssl_set_client_transport_id(&m_env->ssl,
2624 (unsigned char *)&c_session->addr_info.remote,
2625 sizeof(c_session->addr_info.remote))) != 0) {
2626 coap_log_err("mbedtls_ssl_set_client_transport_id() returned -0x%x: '%s'\n",
2627 -ret, get_error_string(ret));
2628 return -1;
2629 }
2630
2631 ssl_data = &m_env->coap_ssl_data;
2632 if (ssl_data->pdu_len) {
2633 coap_log_err("** %s: Previous data not read %u bytes\n",
2634 coap_session_str(c_session), ssl_data->pdu_len);
2635 }
2636 ssl_data->pdu = data;
2637 ssl_data->pdu_len = (unsigned)data_len;
2638
2639 ret = do_mbedtls_handshake(c_session, m_env);
2640 if (ret == 0 || m_env->seen_client_hello) {
2641 /* The test for seen_client_hello gives the ability to setup a new
2642 c_session to continue the do_mbedtls_handshake past the client hello
2643 and safely allow updating of the m_env and separately
2644 letting a new session cleanly start up.
2645 */
2646 m_env->seen_client_hello = 0;
2647 ret = 1;
2648 } else {
2649 ret = 0;
2650 }
2651
2652 if (ssl_data->pdu_len) {
2653 /* pdu data is held on stack which will not stay there */
2654 coap_log_debug("coap_dtls_hello: ret %d: remaining data %u\n", ret, ssl_data->pdu_len);
2655 ssl_data->pdu_len = 0;
2656 ssl_data->pdu = NULL;
2657 }
2658 return ret;
2659#endif /* MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_SSL_SRV_C */
2660}
2661#endif /* COAP_SERVER_SUPPORT */
2662
2663unsigned int
2665 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2666 int expansion = mbedtls_ssl_get_record_expansion(&m_env->ssl);
2667
2668 if (expansion == MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) {
2669 return 13 + 8 + 8;
2670 }
2671 return expansion;
2672}
2673
2674#if !COAP_DISABLE_TCP
2675#if COAP_CLIENT_SUPPORT
2676void *
2678#if !defined(MBEDTLS_SSL_CLI_C)
2679 (void)c_session;
2680 *connected = 0;
2681 coap_log_emerg("coap_tls_new_client_session:"
2682 " libcoap not compiled for Client Mode for Mbed TLS"
2683 " - update Mbed TLS to include Client Mode\n");
2684 return NULL;
2685#else /* MBEDTLS_SSL_CLI_C */
2686 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
2689 int ret;
2690 coap_tick_t now;
2691 coap_ticks(&now);
2692
2693 if (!m_env)
2694 return NULL;
2695
2696 m_env->last_timeout = now;
2697 c_session->tls = m_env;
2698 ret = do_mbedtls_handshake(c_session, m_env);
2699 if (ret == 1) {
2701 c_session->sock.lfunc[COAP_LAYER_TLS].l_establish(c_session);
2702 }
2703 return m_env;
2704#endif /* MBEDTLS_SSL_CLI_C */
2705}
2706#endif /* COAP_CLIENT_SUPPORT */
2707
2708#if COAP_SERVER_SUPPORT
2709void *
2711#if !defined(MBEDTLS_SSL_SRV_C)
2712 (void)c_session;
2713 (void)connected;
2714
2715 coap_log_emerg("coap_tls_new_server_session:"
2716 " libcoap not compiled for Server Mode for Mbed TLS"
2717 " - update Mbed TLS to include Server Mode\n");
2718 return NULL;
2719#else /* MBEDTLS_SSL_SRV_C */
2720 coap_mbedtls_env_t *m_env = coap_dtls_new_mbedtls_env(c_session,
2723 int ret;
2724
2725 if (!m_env)
2726 return NULL;
2727
2728 c_session->tls = m_env;
2729 ret = do_mbedtls_handshake(c_session, m_env);
2730 if (ret == 1) {
2732 c_session->sock.lfunc[COAP_LAYER_TLS].l_establish(c_session);
2733 }
2734 return m_env;
2735#endif /* MBEDTLS_SSL_SRV_C */
2736}
2737#endif /* COAP_SERVER_SUPPORT */
2738
2739void
2741 coap_dtls_free_session(c_session);
2742 return;
2743}
2744
2745/*
2746 * strm
2747 * return +ve Number of bytes written.
2748 * -1 Error (error in errno).
2749 */
2750ssize_t
2751coap_tls_write(coap_session_t *c_session, const uint8_t *data,
2752 size_t data_len) {
2753 int ret = 0;
2754 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2755 size_t amount_sent = 0;
2756
2757 assert(m_env != NULL);
2758
2759 if (!m_env) {
2760 errno = ENXIO;
2761 return -1;
2762 }
2763 c_session->dtls_event = -1;
2764 if (m_env->established) {
2765 while (amount_sent < data_len) {
2766 ret = mbedtls_ssl_write(&m_env->ssl, &data[amount_sent],
2767 data_len - amount_sent);
2768 if (ret <= 0) {
2769 switch (ret) {
2770 case MBEDTLS_ERR_SSL_WANT_READ:
2771 case MBEDTLS_ERR_SSL_WANT_WRITE:
2772 if (amount_sent)
2773 ret = amount_sent;
2774 else
2775 ret = 0;
2776 c_session->sock.flags |= COAP_SOCKET_WANT_WRITE;
2777 break;
2778 case MBEDTLS_ERR_NET_CONN_RESET:
2779 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2781 break;
2782 default:
2783 coap_log_warn("coap_tls_write: "
2784 "returned -0x%x: '%s'\n",
2785 -ret, get_error_string(ret));
2786 ret = -1;
2787 break;
2788 }
2789 if (ret == -1) {
2790 coap_log_warn("coap_tls_write: cannot send PDU\n");
2791 }
2792 break;
2793 }
2794 amount_sent += ret;
2795 }
2796 } else {
2797 ret = do_mbedtls_handshake(c_session, m_env);
2798 if (ret == 1) {
2800 c_session);
2801 c_session->sock.lfunc[COAP_LAYER_TLS].l_establish(c_session);
2802 } else {
2803 ret = -1;
2804 }
2805 }
2806
2807 if (c_session->dtls_event >= 0) {
2808 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2809 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2810 coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session);
2811 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2812 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2814 ret = -1;
2815 }
2816 }
2817 if (ret > 0) {
2818 if (ret == (ssize_t)data_len)
2819 coap_log_debug("* %s: tls: sent %4d bytes\n",
2820 coap_session_str(c_session), ret);
2821 else
2822 coap_log_debug("* %s: tls: sent %4d of %4zd bytes\n",
2823 coap_session_str(c_session), ret, data_len);
2824 }
2825 return ret;
2826}
2827
2828/*
2829 * strm
2830 * return >=0 Number of bytes read.
2831 * -1 Error (error in errno).
2832 */
2833ssize_t
2834coap_tls_read(coap_session_t *c_session, uint8_t *data, size_t data_len) {
2835 int ret = -1;
2836
2837 coap_mbedtls_env_t *m_env = (coap_mbedtls_env_t *)c_session->tls;
2838
2839 if (!m_env) {
2840 errno = ENXIO;
2841 return -1;
2842 }
2843
2844 c_session->dtls_event = -1;
2845
2846 if (!m_env->established && !m_env->sent_alert) {
2847 ret = do_mbedtls_handshake(c_session, m_env);
2848 if (ret == 1) {
2850 c_session);
2851 c_session->sock.lfunc[COAP_LAYER_TLS].l_establish(c_session);
2852 }
2853 }
2854
2855 if (c_session->state != COAP_SESSION_STATE_NONE && m_env->established) {
2856 ret = mbedtls_ssl_read(&m_env->ssl, data, data_len);
2857 if (ret <= 0) {
2858 switch (ret) {
2859 case 0:
2860 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
2862 ret = -1;
2863 break;
2864 case MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE:
2865 /* Stop the sending of an alert on closedown */
2866 m_env->sent_alert = 1;
2868 break;
2869#if MBEDTLS_VERSION_NUMBER >= 0x03060000
2870 case MBEDTLS_ERR_SSL_RECEIVED_NEW_SESSION_TICKET:
2871#endif /* MBEDTLS_VERSION_NUMBER >= 0x03060000 */
2872 case MBEDTLS_ERR_SSL_WANT_READ:
2873 errno = EAGAIN;
2874 ret = 0;
2875 break;
2876 default:
2877 coap_log_warn("coap_tls_read: "
2878 "returned -0x%x: '%s' (length %zd)\n",
2879 -ret, get_error_string(ret), data_len);
2880 ret = -1;
2881 break;
2882 }
2883 } else if (ret < (int)data_len) {
2884 c_session->sock.flags &= ~COAP_SOCKET_CAN_READ;
2885 }
2886 }
2887
2888 if (c_session->dtls_event >= 0) {
2889 /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected_lkd() */
2890 if (c_session->dtls_event != COAP_EVENT_DTLS_CLOSED)
2891 coap_handle_event_lkd(c_session->context, c_session->dtls_event, c_session);
2892 if (c_session->dtls_event == COAP_EVENT_DTLS_ERROR ||
2893 c_session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
2895 ret = -1;
2896 }
2897 }
2898 if (ret > 0) {
2899 coap_log_debug("* %s: tls: recv %4d bytes\n",
2900 coap_session_str(c_session), ret);
2901 }
2902 return ret;
2903}
2904#endif /* !COAP_DISABLE_TCP */
2905
2906void
2907coap_dtls_startup(void) {
2908}
2909
2910void
2911coap_dtls_shutdown(void) {
2912#if COAP_CLIENT_SUPPORT
2913 mbedtls_free(psk_ciphers);
2914 mbedtls_free(pki_ciphers);
2915 mbedtls_free(ecjpake_ciphers);
2916 psk_ciphers = NULL;
2917 pki_ciphers = NULL;
2918 ecjpake_ciphers = NULL;
2919 processed_ciphers = 0;
2920#endif /* COAP_CLIENT_SUPPORT */
2922}
2923
2924void *
2925coap_dtls_get_tls(const coap_session_t *c_session,
2926 coap_tls_library_t *tls_lib) {
2927 if (tls_lib)
2928 *tls_lib = COAP_TLS_LIBRARY_MBEDTLS;
2929 if (c_session && c_session->tls) {
2930 coap_mbedtls_env_t *m_env;
2931
2932 /* To get around const issue */
2933 memcpy(&m_env, &c_session->tls, sizeof(m_env));
2934
2935 return (void *)&m_env->ssl;
2936 }
2937 return NULL;
2938}
2939
2940static coap_log_t keep_log_level = COAP_LOG_EMERG;
2941
2942void
2944#if !defined(ESPIDF_VERSION)
2945 int use_level;
2946 /*
2947 * Mbed TLS debug levels filter
2948 * 0 No debug
2949 * 1 Error
2950 * 2 State change
2951 * 3 Informational
2952 * 4 Verbose
2953 */
2954 switch ((int)level) {
2955 case COAP_LOG_EMERG:
2956 use_level = 0;
2957 break;
2958 case COAP_LOG_ALERT:
2959 case COAP_LOG_CRIT:
2960 case COAP_LOG_ERR:
2961 case COAP_LOG_WARN:
2962 use_level = 1;
2963 break;
2964 case COAP_LOG_NOTICE:
2965 use_level = 2;
2966 break;
2967 case COAP_LOG_INFO:
2968 use_level = 3;
2969 break;
2970 case COAP_LOG_DEBUG:
2971 default:
2972 use_level = 4;
2973 break;
2974 }
2975 mbedtls_debug_set_threshold(use_level);
2976#endif /* !ESPIDF_VERSION) */
2977 keep_log_level = level;
2978}
2979
2982 return keep_log_level;
2983}
2984
2987 static coap_tls_version_t version;
2988 version.version = mbedtls_version_get_number();
2989 version.built_version = MBEDTLS_VERSION_NUMBER;
2991 return &version;
2992}
2993
2994#if COAP_SERVER_SUPPORT
2996coap_digest_setup(void) {
2997 mbedtls_sha256_context *digest_ctx = mbedtls_malloc(sizeof(mbedtls_sha256_context));
2998
2999 if (digest_ctx) {
3000 mbedtls_sha256_init(digest_ctx);
3001#ifdef MBEDTLS_2_X_COMPAT
3002 if (mbedtls_sha256_starts_ret(digest_ctx, 0) != 0) {
3003#else
3004 if (mbedtls_sha256_starts(digest_ctx, 0) != 0) {
3005#endif /* MBEDTLS_2_X_COMPAT */
3006 coap_digest_free(digest_ctx);
3007 return NULL;
3008 }
3009 }
3010 return digest_ctx;
3011}
3012
3013void
3015 if (digest_ctx) {
3016 mbedtls_sha256_free(digest_ctx);
3017 mbedtls_free(digest_ctx);
3018 }
3019}
3020
3021int
3023 const uint8_t *data,
3024 size_t data_len) {
3025#ifdef MBEDTLS_2_X_COMPAT
3026 int ret = mbedtls_sha256_update_ret(digest_ctx, data, data_len);
3027#else
3028 int ret = mbedtls_sha256_update(digest_ctx, data, data_len);
3029#endif /* MBEDTLS_2_X_COMPAT */
3030
3031 return ret == 0;
3032}
3033
3034int
3036 coap_digest_t *digest_buffer) {
3037#ifdef MBEDTLS_2_X_COMPAT
3038 int ret = mbedtls_sha256_finish_ret(digest_ctx, (uint8_t *)digest_buffer);
3039#else
3040 int ret = mbedtls_sha256_finish(digest_ctx, (uint8_t *)digest_buffer);
3041#endif /* MBEDTLS_2_X_COMPAT */
3042
3043 coap_digest_free(digest_ctx);
3044 return ret == 0;
3045}
3046#endif /* COAP_SERVER_SUPPORT */
3047
3048#include <mbedtls/cipher.h>
3049#include <mbedtls/md.h>
3050
3051#ifndef MBEDTLS_CIPHER_MODE_AEAD
3052#error need MBEDTLS_CIPHER_MODE_AEAD, please enable MBEDTLS_CCM_C
3053#endif /* MBEDTLS_CIPHER_MODE_AEAD */
3054
3055#ifdef MBEDTLS_ERROR_C
3056#include <mbedtls/error.h>
3057#endif /* MBEDTLS_ERROR_C */
3058
3059#ifdef MBEDTLS_ERROR_C
3060#define C(Func) \
3061 do { \
3062 int c_tmp = (int)(Func); \
3063 if (c_tmp != 0) { \
3064 char error_buf[64]; \
3065 mbedtls_strerror(c_tmp, error_buf, sizeof(error_buf)); \
3066 coap_log_err("mbedtls: -0x%04x: %s\n", -c_tmp, error_buf); \
3067 goto error; \
3068 } \
3069 } while (0);
3070#else /* !MBEDTLS_ERROR_C */
3071#define C(Func) \
3072 do { \
3073 int c_tmp = (int)(Func); \
3074 if (c_tmp != 0) { \
3075 coap_log_err("mbedtls: %d\n", tmp); \
3076 goto error; \
3077 } \
3078 } while (0);
3079#endif /* !MBEDTLS_ERROR_C */
3080
3081#if COAP_WS_SUPPORT
3082/*
3083 * The struct hash_algs and the function get_hash_alg() are used to
3084 * determine which hash type to use for creating the required hash object.
3085 */
3086static struct hash_algs {
3087 cose_alg_t alg;
3088 mbedtls_md_type_t hash_type;
3089 size_t hash_size;
3090} hashs[] = {
3091 {COSE_ALGORITHM_SHA_1, MBEDTLS_MD_SHA1, 20},
3092 {COSE_ALGORITHM_SHA_256_256, MBEDTLS_MD_SHA256, 32},
3093 {COSE_ALGORITHM_SHA_512, MBEDTLS_MD_SHA512, 64},
3094};
3095
3096static mbedtls_md_type_t
3097get_hash_alg(cose_alg_t alg, size_t *hash_len) {
3098 size_t idx;
3099
3100 for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
3101 if (hashs[idx].alg == alg) {
3102 *hash_len = hashs[idx].hash_size;
3103 return hashs[idx].hash_type;
3104 }
3105 }
3106 coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
3107 return MBEDTLS_MD_NONE;
3108}
3109
3110int
3112 const coap_bin_const_t *data,
3113 coap_bin_const_t **hash) {
3114 mbedtls_md_context_t ctx;
3115 int ret = 0;
3116 const mbedtls_md_info_t *md_info;
3117 unsigned int len;
3118 coap_binary_t *dummy = NULL;
3119 size_t hash_length;
3120 mbedtls_md_type_t dig_type = get_hash_alg(alg, &hash_length);
3121
3122 if (dig_type == MBEDTLS_MD_NONE) {
3123 coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
3124 return 0;
3125 }
3126 md_info = mbedtls_md_info_from_type(dig_type);
3127
3128 len = mbedtls_md_get_size(md_info);
3129 if (len == 0) {
3130 return 0;
3131 }
3132
3133 mbedtls_md_init(&ctx);
3134 C(mbedtls_md_setup(&ctx, md_info, 0));
3135
3136 C(mbedtls_md_starts(&ctx));
3137 C(mbedtls_md_update(&ctx, (const unsigned char *)data->s, data->length));
3138 dummy = coap_new_binary(len);
3139 if (dummy == NULL)
3140 goto error;
3141 C(mbedtls_md_finish(&ctx, dummy->s));
3142
3143 *hash = (coap_bin_const_t *)dummy;
3144 ret = 1;
3145error:
3146 mbedtls_md_free(&ctx);
3147 return ret;
3148}
3149#endif /* COAP_WS_SUPPORT */
3150
3151#if COAP_OSCORE_SUPPORT
3152int
3154 return 1;
3155}
3156
3157/*
3158 * The struct cipher_algs and the function get_cipher_alg() are used to
3159 * determine which cipher type to use for creating the required cipher
3160 * suite object.
3161 */
3162static struct cipher_algs {
3163 cose_alg_t alg;
3164 mbedtls_cipher_type_t cipher_type;
3165} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, MBEDTLS_CIPHER_AES_128_CCM},
3166 {COSE_ALGORITHM_AES_CCM_16_64_256, MBEDTLS_CIPHER_AES_256_CCM}
3167};
3168
3169static mbedtls_cipher_type_t
3170get_cipher_alg(cose_alg_t alg) {
3171 size_t idx;
3172
3173 for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
3174 if (ciphers[idx].alg == alg)
3175 return ciphers[idx].cipher_type;
3176 }
3177 coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
3178 return 0;
3179}
3180
3181/*
3182 * The struct hmac_algs and the function get_hmac_alg() are used to
3183 * determine which hmac type to use for creating the required hmac
3184 * suite object.
3185 */
3186static struct hmac_algs {
3187 cose_hmac_alg_t hmac_alg;
3188 mbedtls_md_type_t hmac_type;
3189} hmacs[] = {
3190 {COSE_HMAC_ALG_HMAC256_256, MBEDTLS_MD_SHA256},
3191 {COSE_HMAC_ALG_HMAC384_384, MBEDTLS_MD_SHA384},
3192 {COSE_HMAC_ALG_HMAC512_512, MBEDTLS_MD_SHA512},
3193};
3194
3195static mbedtls_md_type_t
3196get_hmac_alg(cose_hmac_alg_t hmac_alg) {
3197 size_t idx;
3198
3199 for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
3200 if (hmacs[idx].hmac_alg == hmac_alg)
3201 return hmacs[idx].hmac_type;
3202 }
3203 coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
3204 return 0;
3205}
3206
3207int
3209 return get_cipher_alg(alg) != 0;
3210}
3211
3212int
3214 cose_hmac_alg_t hmac_alg;
3215
3216 if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
3217 return 0;
3218 return get_hmac_alg(hmac_alg) != 0;
3219}
3220
3225static int
3226setup_cipher_context(mbedtls_cipher_context_t *ctx,
3227 cose_alg_t coap_alg,
3228 const uint8_t *key_data,
3229 size_t key_length,
3230 mbedtls_operation_t mode) {
3231 const mbedtls_cipher_info_t *cipher_info;
3232 mbedtls_cipher_type_t cipher_type;
3233 uint8_t key[COAP_CRYPTO_MAX_KEY_SIZE]; /* buffer for normalizing the key
3234 according to its key length */
3235 int klen;
3236 memset(key, 0, sizeof(key));
3237
3238 if ((cipher_type = get_cipher_alg(coap_alg)) == 0) {
3239 coap_log_debug("coap_crypto_encrypt: algorithm %d not supported\n",
3240 coap_alg);
3241 return 0;
3242 }
3243 cipher_info = mbedtls_cipher_info_from_type(cipher_type);
3244 if (!cipher_info) {
3245 coap_log_crit("coap_crypto_encrypt: cannot get cipher info\n");
3246 return 0;
3247 }
3248
3249 mbedtls_cipher_init(ctx);
3250
3251 C(mbedtls_cipher_setup(ctx, cipher_info));
3252 klen = mbedtls_cipher_get_key_bitlen(ctx);
3253 if ((klen > (int)(sizeof(key) * 8)) || (key_length > sizeof(key))) {
3254 coap_log_crit("coap_crypto: cannot set key\n");
3255 goto error;
3256 }
3257 memcpy(key, key_data, key_length);
3258 C(mbedtls_cipher_setkey(ctx, key, klen, mode));
3259
3260 /* On success, the cipher context is released by the caller. */
3261 return 1;
3262error:
3263 mbedtls_cipher_free(ctx);
3264 return 0;
3265}
3266
3267int
3269 coap_bin_const_t *data,
3270 coap_bin_const_t *aad,
3271 uint8_t *result,
3272 size_t *max_result_len) {
3273 mbedtls_cipher_context_t ctx;
3274 const coap_crypto_aes_ccm_t *ccm;
3275#if (MBEDTLS_VERSION_NUMBER < 0x02150000)
3276 unsigned char tag[16];
3277#endif /* MBEDTLS_VERSION_NUMBER < 0x02150000 */
3278 int ret = 0;
3279 size_t result_len = *max_result_len;
3280 coap_bin_const_t laad;
3281
3282 if (data == NULL)
3283 return 0;
3284
3285 assert(params != NULL);
3286
3287 if (!params) {
3288 return 0;
3289 }
3290 ccm = &params->params.aes;
3291
3292 if (!setup_cipher_context(&ctx,
3293 params->alg,
3294 ccm->key.s,
3295 ccm->key.length,
3296 MBEDTLS_ENCRYPT)) {
3297 return 0;
3298 }
3299
3300 if (aad) {
3301 laad = *aad;
3302 } else {
3303 laad.s = NULL;
3304 laad.length = 0;
3305 }
3306
3307#if (MBEDTLS_VERSION_NUMBER < 0x02150000)
3308 C(mbedtls_cipher_auth_encrypt(&ctx,
3309 ccm->nonce,
3310 15 - ccm->l, /* iv */
3311 laad.s,
3312 laad.length, /* ad */
3313 data->s,
3314 data->length, /* input */
3315 result,
3316 &result_len, /* output */
3317 tag,
3318 ccm->tag_len /* tag */
3319 ));
3320 /* check if buffer is sufficient to hold tag */
3321 if ((result_len + ccm->tag_len) > *max_result_len) {
3322 coap_log_err("coap_encrypt: buffer too small\n");
3323 goto error;
3324 }
3325 /* append tag to result */
3326 memcpy(result + result_len, tag, ccm->tag_len);
3327 *max_result_len = result_len + ccm->tag_len;
3328 ret = 1;
3329#else /* MBEDTLS_VERSION_NUMBER >= 0x02150000 */
3330 C(mbedtls_cipher_auth_encrypt_ext(&ctx,
3331 ccm->nonce,
3332 15 - ccm->l, /* iv */
3333 laad.s,
3334 laad.length, /* ad */
3335 data->s,
3336 data->length, /* input */
3337 result,
3338 result_len,
3339 &result_len, /* output */
3340 ccm->tag_len /* tag */
3341 ));
3342 *max_result_len = result_len;
3343 ret = 1;
3344#endif /* MBEDTLS_VERSION_NUMBER >= 0x02150000 */
3345
3346error:
3347 mbedtls_cipher_free(&ctx);
3348 return ret;
3349}
3350
3351int
3353 coap_bin_const_t *data,
3354 coap_bin_const_t *aad,
3355 uint8_t *result,
3356 size_t *max_result_len) {
3357 mbedtls_cipher_context_t ctx;
3358 const coap_crypto_aes_ccm_t *ccm;
3359#if (MBEDTLS_VERSION_NUMBER < 0x02150000)
3360 const unsigned char *tag;
3361#endif /* MBEDTLS_VERSION_NUMBER < 0x02150000 */
3362 int ret = 0;
3363 size_t result_len = *max_result_len;
3364 coap_bin_const_t laad;
3365
3366 if (data == NULL)
3367 return 0;
3368
3369 assert(params != NULL);
3370
3371 if (!params) {
3372 return 0;
3373 }
3374
3375 ccm = &params->params.aes;
3376
3377 if (!setup_cipher_context(&ctx,
3378 params->alg,
3379 ccm->key.s,
3380 ccm->key.length,
3381 MBEDTLS_DECRYPT)) {
3382 return 0;
3383 }
3384
3385 if (data->length < ccm->tag_len) {
3386 coap_log_err("coap_decrypt: invalid tag length\n");
3387 goto error;
3388 }
3389
3390 if (aad) {
3391 laad = *aad;
3392 } else {
3393 laad.s = NULL;
3394 laad.length = 0;
3395 }
3396
3397#if (MBEDTLS_VERSION_NUMBER < 0x02150000)
3398 tag = data->s + data->length - ccm->tag_len;
3399 C(mbedtls_cipher_auth_decrypt(&ctx,
3400 ccm->nonce,
3401 15 - ccm->l, /* iv */
3402 laad.s,
3403 laad.length, /* ad */
3404 data->s,
3405 data->length - ccm->tag_len, /* input */
3406 result,
3407 &result_len, /* output */
3408 tag,
3409 ccm->tag_len /* tag */
3410 ));
3411#else /* MBEDTLS_VERSION_NUMBER >= 0x02150000 */
3412 C(mbedtls_cipher_auth_decrypt_ext(&ctx,
3413 ccm->nonce,
3414 15 - ccm->l, /* iv */
3415 laad.s,
3416 laad.length, /* ad */
3417 data->s,
3418 // data->length - ccm->tag_len, /* input */
3419 data->length, /* input */
3420 result,
3421 result_len,
3422 &result_len, /* output */
3423 ccm->tag_len /* tag */
3424 ));
3425#endif /* MBEDTLS_VERSION_NUMBER >= 0x02150000 */
3426
3427 *max_result_len = result_len;
3428 ret = 1;
3429error:
3430 mbedtls_cipher_free(&ctx);
3431 return ret;
3432}
3433
3434int
3436 coap_bin_const_t *key,
3437 coap_bin_const_t *data,
3438 coap_bin_const_t **hmac) {
3439 mbedtls_md_context_t ctx;
3440 int ret = 0;
3441 const int use_hmac = 1;
3442 const mbedtls_md_info_t *md_info;
3443 mbedtls_md_type_t mac_algo;
3444 unsigned int len;
3445 coap_binary_t *dummy = NULL;
3446
3447 assert(key);
3448 assert(data);
3449 assert(hmac);
3450
3451 if ((mac_algo = get_hmac_alg(hmac_alg)) == 0) {
3452 coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
3453 return 0;
3454 }
3455 md_info = mbedtls_md_info_from_type(mac_algo);
3456
3457 len = mbedtls_md_get_size(md_info);
3458 if (len == 0) {
3459 return 0;
3460 }
3461
3462 mbedtls_md_init(&ctx);
3463 C(mbedtls_md_setup(&ctx, md_info, use_hmac));
3464
3465 C(mbedtls_md_hmac_starts(&ctx, key->s, key->length));
3466 C(mbedtls_md_hmac_update(&ctx, (const unsigned char *)data->s, data->length));
3467 dummy = coap_new_binary(len);
3468 if (dummy == NULL)
3469 goto error;
3470 C(mbedtls_md_hmac_finish(&ctx, dummy->s));
3471
3472 *hmac = (coap_bin_const_t *)dummy;
3473 ret = 1;
3474error:
3475 mbedtls_md_free(&ctx);
3476 return ret;
3477}
3478
3479#endif /* COAP_OSCORE_SUPPORT */
3480
3481#else /* !COAP_WITH_LIBMBEDTLS */
3482
3483#ifdef __clang__
3484/* Make compilers happy that do not like empty modules. As this function is
3485 * never used, we ignore -Wunused-function at the end of compiling this file
3486 */
3487#pragma GCC diagnostic ignored "-Wunused-function"
3488#endif
3489static inline void
3490dummy(void) {
3491}
3492
3493#endif /* COAP_WITH_LIBMBEDTLS */
#define COAP_SERVER_SUPPORT
#define PRIx32
const char * coap_socket_strerror(void)
Definition coap_io.c:2355
#define COAP_RXBUFFER_SIZE
Definition coap_io.h:29
@ COAP_NACK_TLS_FAILED
Definition coap_io.h:66
#define COAP_SOCKET_WANT_WRITE
non blocking socket is waiting for writing
@ COAP_LAYER_TLS
Library specific build wrapper for coap_internal.h.
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:108
coap_tick_t coap_dtls_get_timeout(coap_session_t *session COAP_UNUSED, coap_tick_t now COAP_UNUSED)
Definition coap_notls.c:229
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:301
coap_tick_t coap_dtls_get_context_timeout(void *dtls_context COAP_UNUSED)
Definition coap_notls.c:224
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:243
void * coap_dtls_get_tls(const coap_session_t *c_session COAP_UNUSED, coap_tls_library_t *tls_lib)
Definition coap_notls.c:158
unsigned int coap_dtls_get_overhead(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:261
int coap_dtls_context_load_pki_trust_store(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:124
int coap_dtls_context_check_keys_enabled(coap_context_t *ctx COAP_UNUSED)
Definition coap_notls.c:147
ssize_t coap_dtls_send(coap_session_t *session COAP_UNUSED, const uint8_t *data COAP_UNUSED, size_t data_len COAP_UNUSED)
Definition coap_notls.c:212
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:289
void coap_dtls_session_update_mtu(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:208
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:116
int coap_dtls_handle_timeout(coap_session_t *session COAP_UNUSED)
Definition coap_notls.c:238
void coap_dtls_free_context(void *handle COAP_UNUSED)
Definition coap_notls.c:186
void coap_dtls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:204
void * coap_dtls_new_context(coap_context_t *coap_context COAP_UNUSED)
Definition coap_notls.c:181
void coap_tls_free_session(coap_session_t *coap_session COAP_UNUSED)
Definition coap_notls.c:280
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.
uint64_t coap_tick_t
This data type represents internal timer ticks with COAP_TICKS_PER_SECOND resolution.
Definition coap_time.h:143
int coap_prng_lkd(void *buf, size_t len)
Fills buf with len random bytes using the default pseudo random number generator.
Definition coap_prng.c:190
int coap_handle_event_lkd(coap_context_t *context, coap_event_t event, coap_session_t *session)
Invokes the event handler of context for the given event and data.
Definition coap_net.c:4880
int coap_handle_dgram(coap_context_t *ctx, coap_session_t *session, uint8_t *msg, size_t msg_len)
Parses and interprets a CoAP datagram with context ctx.
Definition coap_net.c:2882
void coap_ticks(coap_tick_t *)
Returns the current value of an internal tick counter.
int coap_crypto_hmac(cose_hmac_alg_t hmac_alg, coap_bin_const_t *key, coap_bin_const_t *data, coap_bin_const_t **hmac)
Create a HMAC hash of the provided data.
int coap_crypto_aead_decrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Decrypt the provided encrypted data into plaintext.
int coap_crypto_aead_encrypt(const coap_crypto_param_t *params, coap_bin_const_t *data, coap_bin_const_t *aad, uint8_t *result, size_t *max_result_len)
Encrypt the provided plaintext data.
#define COAP_CRYPTO_MAX_KEY_SIZE
int coap_crypto_hash(cose_alg_t alg, const coap_bin_const_t *data, coap_bin_const_t **hash)
Create a hash of the provided data.
int coap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg)
Check whether the defined hkdf algorithm is supported by the underlying crypto library.
int coap_crypto_check_cipher_alg(cose_alg_t alg)
Check whether the defined cipher algorithm is supported by the underlying crypto library.
void * coap_tls_new_server_session(coap_session_t *coap_session)
Create a TLS new server-side session.
const coap_bin_const_t * coap_get_session_client_psk_identity(const coap_session_t *coap_session)
Get the current client's PSK identity.
void coap_dtls_startup(void)
Initialize the underlying (D)TLS Library layer.
Definition coap_notls.c:154
int coap_dtls_define_issue(coap_define_issue_key_t type, coap_define_issue_fail_t fail, coap_dtls_key_t *key, const coap_dtls_role_t role, int ret)
Report PKI DEFINE type issue.
Definition coap_dtls.c:165
void * coap_dtls_new_client_session(coap_session_t *coap_session)
Create a new client-side session.
void * coap_dtls_new_server_session(coap_session_t *coap_session)
Create a new DTLS server-side session.
int coap_dtls_hello(coap_session_t *coap_session, const uint8_t *data, size_t data_len)
Handling client HELLO messages from a new candiate peer.
int coap_dtls_set_cid_tuple_change(coap_context_t *context, uint8_t every)
Set the Connection ID client tuple frequency change for testing CIDs.
int coap_dtls_is_context_timeout(void)
Check if timeout is handled per CoAP session or per CoAP context.
Definition coap_notls.c:219
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:166
const coap_bin_const_t * coap_get_session_client_psk_key(const coap_session_t *coap_session)
Get the current client's PSK key.
void * coap_tls_new_client_session(coap_session_t *coap_session)
Create a new TLS client-side session.
#define COAP_DTLS_RETRANSMIT_COAP_TICKS
void coap_dtls_map_key_type_to_define(const coap_dtls_pki_t *setup_data, coap_dtls_key_t *key)
Map the PKI key definitions to the new DEFINE format.
Definition coap_dtls.c:26
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_DEFINE_KEY_PRIVATE
@ COAP_DEFINE_KEY_ROOT_CA
@ COAP_DEFINE_KEY_CA
@ COAP_DEFINE_KEY_PUBLIC
@ COAP_DEFINE_FAIL_NONE
@ COAP_DEFINE_FAIL_NOT_SUPPORTED
@ COAP_DEFINE_FAIL_BAD
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:100
coap_dtls_role_t
Definition coap_dtls.h:44
coap_tls_library_t
Definition coap_dtls.h:70
@ COAP_PKI_KEY_DEF_PKCS11
The PKI key type is PKCS11 (pkcs11:...).
Definition coap_dtls.h:245
@ COAP_PKI_KEY_DEF_DER_BUF
The PKI key type is DER buffer (ASN.1).
Definition coap_dtls.h:242
@ COAP_PKI_KEY_DEF_PEM_BUF
The PKI key type is PEM buffer.
Definition coap_dtls.h:236
@ COAP_PKI_KEY_DEF_PEM
The PKI key type is PEM file.
Definition coap_dtls.h:234
@ COAP_PKI_KEY_DEF_ENGINE
The PKI key type is to be passed to ENGINE.
Definition coap_dtls.h:251
@ COAP_PKI_KEY_DEF_RPK_BUF
The PKI key type is RPK in buffer.
Definition coap_dtls.h:238
@ COAP_PKI_KEY_DEF_DER
The PKI key type is DER file.
Definition coap_dtls.h:240
@ COAP_PKI_KEY_DEF_PKCS11_RPK
The PKI key type is PKCS11 w/ RPK (pkcs11:...).
Definition coap_dtls.h:248
@ COAP_DTLS_ROLE_SERVER
Internal function invoked for server.
Definition coap_dtls.h:46
@ COAP_DTLS_ROLE_CLIENT
Internal function invoked for client.
Definition coap_dtls.h:45
@ COAP_PKI_KEY_DEFINE
The individual PKI key types are Definable.
Definition coap_dtls.h:172
@ COAP_TLS_LIBRARY_MBEDTLS
Using Mbed TLS library.
Definition coap_dtls.h:75
@ COAP_EVENT_DTLS_CLOSED
Triggerred when (D)TLS session closed.
Definition coap_event.h:39
@ COAP_EVENT_DTLS_CONNECTED
Triggered when (D)TLS session connected.
Definition coap_event.h:41
@ COAP_EVENT_DTLS_ERROR
Triggered when (D)TLS error occurs.
Definition coap_event.h:45
#define coap_lock_callback_ret(r, func)
Dummy for no thread-safe code.
#define coap_log_debug(...)
Definition coap_debug.h:120
#define coap_log_emerg(...)
Definition coap_debug.h:81
coap_log_t
Logging type.
Definition coap_debug.h:50
coap_log_t coap_dtls_get_log_level(void)
Get the current (D)TLS logging.
Definition coap_notls.c:176
#define coap_dtls_log(level,...)
Logging function.
Definition coap_debug.h:300
void coap_dtls_set_log_level(coap_log_t level)
Sets the (D)TLS logging level to the specified level.
Definition coap_notls.c:171
const char * coap_session_str(const coap_session_t *session)
Get session description.
#define coap_log_info(...)
Definition coap_debug.h:108
#define coap_log_warn(...)
Definition coap_debug.h:102
#define coap_log_err(...)
Definition coap_debug.h:96
#define coap_log_crit(...)
Definition coap_debug.h:90
@ COAP_LOG_INFO
Definition coap_debug.h:57
@ COAP_LOG_EMERG
Definition coap_debug.h:51
@ COAP_LOG_NOTICE
Definition coap_debug.h:56
@ COAP_LOG_DEBUG
Definition coap_debug.h:58
@ COAP_LOG_ALERT
Definition coap_debug.h:52
@ COAP_LOG_CRIT
Definition coap_debug.h:53
@ COAP_LOG_ERR
Definition coap_debug.h:54
@ COAP_LOG_WARN
Definition coap_debug.h:55
int coap_netif_available(coap_session_t *session)
Function interface to check whether netif for session is still available.
Definition coap_netif.c:25
int cose_get_hmac_alg_for_hkdf(cose_hkdf_alg_t hkdf_alg, cose_hmac_alg_t *hmac_alg)
cose_hkdf_alg_t
cose_hmac_alg_t
cose_alg_t
@ COSE_HMAC_ALG_HMAC384_384
@ COSE_HMAC_ALG_HMAC256_256
@ COSE_HMAC_ALG_HMAC512_512
@ COSE_ALGORITHM_SHA_256_256
@ COSE_ALGORITHM_SHA_1
@ COSE_ALGORITHM_AES_CCM_16_64_128
@ COSE_ALGORITHM_SHA_512
@ COSE_ALGORITHM_AES_CCM_16_64_256
coap_proto_t
CoAP protocol types.
Definition coap_pdu.h:313
@ COAP_PROTO_DTLS
Definition coap_pdu.h:316
@ COAP_PROTO_TLS
Definition coap_pdu.h:318
@ COAP_PROTO_WSS
Definition coap_pdu.h:320
int coap_session_refresh_psk_hint(coap_session_t *session, const coap_bin_const_t *psk_hint)
Refresh the session's current Identity Hint (PSK).
int coap_session_refresh_psk_key(coap_session_t *session, const coap_bin_const_t *psk_key)
Refresh the session's current pre-shared key (PSK).
void coap_session_connected(coap_session_t *session)
Notify session that it has just connected or reconnected.
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_lkd(coap_session_t *session, coap_nack_reason_t reason)
Notify session that it has failed.
#define COAP_PROTO_NOT_RELIABLE(p)
@ COAP_SESSION_TYPE_CLIENT
client-side
@ COAP_SESSION_STATE_HANDSHAKE
@ COAP_SESSION_STATE_CSM
@ COAP_SESSION_STATE_NONE
coap_binary_t * coap_new_binary(size_t size)
Returns a new binary object with at least size bytes storage allocated.
Definition coap_str.c:77
coap_bin_const_t * coap_new_bin_const(const uint8_t *data, size_t size)
Take the specified byte array (text) and create a coap_bin_const_t * Returns a new const binary objec...
Definition coap_str.c:110
int coap_dtls_cid_is_supported(void)
Check whether (D)TLS CID is available.
Definition coap_notls.c:86
int coap_dtls_psk_is_supported(void)
Check whether (D)TLS PSK is available.
Definition coap_notls.c:50
int coap_tls_is_supported(void)
Check whether TLS is available.
Definition coap_notls.c:41
int coap_oscore_is_supported(void)
Check whether OSCORE is available.
int coap_dtls_is_supported(void)
Check whether DTLS is available.
Definition coap_notls.c:36
int coap_dtls_pki_is_supported(void)
Check whether (D)TLS PKI is available.
Definition coap_notls.c:59
int coap_dtls_rpk_is_supported(void)
Check whether (D)TLS RPK is available.
Definition coap_notls.c:77
int coap_dtls_pkcs11_is_supported(void)
Check whether (D)TLS PKCS11 is available.
Definition coap_notls.c:68
#define COAP_UNUSED
Definition libcoap.h:72
coap_address_t remote
remote address and port
Definition coap_io.h:56
CoAP binary data definition with const data.
Definition coap_str.h:64
size_t length
length of binary data
Definition coap_str.h:65
const uint8_t * s
read-only binary data
Definition coap_str.h:66
CoAP binary data definition.
Definition coap_str.h:56
The CoAP stack's global state is stored in a coap_context_t object.
uint8_t testing_cids
Change client's source port every testing_cids.
coap_dtls_spsk_t spsk_setup_data
Contains the initial PSK server setup data.
The structure that holds the AES Crypto information.
size_t l
The number of bytes in the length field.
const uint8_t * nonce
must be exactly 15 - l bytes
coap_crypto_key_t key
The Key to use.
size_t tag_len
The size of the Tag.
The common structure that holds the Crypto information.
union coap_crypto_param_t::@2 params
coap_crypto_aes_ccm_t aes
Used if AES type encryption.
cose_alg_t alg
The COSE algorith to use.
The structure used for defining the Client PSK setup data to be used.
Definition coap_dtls.h:410
uint8_t use_cid
Set to 1 if DTLS Connection ID is to be used.
Definition coap_dtls.h:417
char * client_sni
If not NULL, SNI to use in client TLS setup.
Definition coap_dtls.h:437
coap_dtls_ih_callback_t validate_ih_call_back
Identity Hint check callback function.
Definition coap_dtls.h:433
uint8_t ec_jpake
Set to COAP_DTLS_CPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:415
The structure that holds the PKI key information.
Definition coap_dtls.h:279
coap_pki_key_define_t define
for definable type keys
Definition coap_dtls.h:286
union coap_dtls_key_t::@3 key
coap_pki_key_t key_type
key format type
Definition coap_dtls.h:280
The structure used for defining the PKI setup data to be used.
Definition coap_dtls.h:312
uint8_t allow_no_crl
1 ignore if CRL not there
Definition coap_dtls.h:326
void * cn_call_back_arg
Passed in to the CN callback function.
Definition coap_dtls.h:351
uint8_t allow_short_rsa_length
1 if small RSA keysizes are allowed
Definition coap_dtls.h:329
uint8_t cert_chain_validation
1 if to check cert_chain_verify_depth
Definition coap_dtls.h:323
uint8_t allow_bad_md_hash
1 if unsupported MD hashes are allowed
Definition coap_dtls.h:328
uint8_t use_cid
1 if DTLS Connection ID is to be used (Client only, server always enabled) if supported
Definition coap_dtls.h:333
uint8_t check_cert_revocation
1 if revocation checks wanted
Definition coap_dtls.h:325
uint8_t cert_chain_verify_depth
recommended depth is 3
Definition coap_dtls.h:324
uint8_t allow_expired_certs
1 if expired certs are allowed
Definition coap_dtls.h:322
uint8_t verify_peer_cert
Set to COAP_DTLS_PKI_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:317
uint8_t allow_self_signed
1 if self-signed certs are allowed.
Definition coap_dtls.h:320
coap_dtls_cn_callback_t validate_cn_call_back
CN check callback function.
Definition coap_dtls.h:350
uint8_t allow_expired_crl
1 if expired crl is allowed
Definition coap_dtls.h:327
uint8_t is_rpk_not_cert
1 is RPK instead of Public Certificate.
Definition coap_dtls.h:330
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:318
The structure that holds the Server Pre-Shared Key and Identity Hint information.
Definition coap_dtls.h:450
The structure used for defining the Server PSK setup data to be used.
Definition coap_dtls.h:501
coap_dtls_psk_sni_callback_t validate_sni_call_back
SNI check callback function.
Definition coap_dtls.h:530
coap_dtls_id_callback_t validate_id_call_back
Identity check callback function.
Definition coap_dtls.h:522
void * id_call_back_arg
Passed in to the Identity callback function.
Definition coap_dtls.h:523
uint8_t ec_jpake
Set to COAP_DTLS_SPSK_SETUP_VERSION to support this version of the struct.
Definition coap_dtls.h:506
void * sni_call_back_arg
Passed in to the SNI callback function.
Definition coap_dtls.h:531
coap_layer_read_t l_read
coap_layer_write_t l_write
coap_layer_establish_t l_establish
coap_const_char_ptr_t public_cert
define: Public Cert
Definition coap_dtls.h:261
coap_const_char_ptr_t private_key
define: Private Key
Definition coap_dtls.h:262
coap_const_char_ptr_t ca
define: Common CA Certificate
Definition coap_dtls.h:260
size_t public_cert_len
define Public Cert length (if needed)
Definition coap_dtls.h:264
size_t ca_len
define CA Cert length (if needed)
Definition coap_dtls.h:263
coap_pki_define_t private_key_def
define: Private Key type definition
Definition coap_dtls.h:268
size_t private_key_len
define Private Key length (if needed)
Definition coap_dtls.h:265
coap_pki_define_t ca_def
define: Common CA type definition
Definition coap_dtls.h:266
coap_pki_define_t public_cert_def
define: Public Cert type definition
Definition coap_dtls.h:267
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_endpoint_t * endpoint
session's endpoint
coap_socket_t sock
socket object for the session, if any
coap_session_state_t state
current state of relationship with peer
coap_bin_const_t * client_cid
Contains client CID or NULL.
coap_addr_tuple_t addr_info
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)
uint8_t negotiated_cid
Set for a client if CID negotiated.
int dtls_event
Tracking any (D)TLS events on this session.
void * tls
security parameters
uint16_t max_retransmit
maximum re-transmit count (default 4)
coap_session_type_t type
client or server side socket
coap_context_t * context
session's context
coap_layer_func_t lfunc[COAP_LAYER_LAST]
Layer functions to use.
coap_socket_flags_t flags
1 or more of COAP_SOCKET* flag values
The structure used for returning the underlying (D)TLS library information.
Definition coap_dtls.h:83
uint64_t built_version
(D)TLS Built against Library Version
Definition coap_dtls.h:86
coap_tls_library_t type
Library type.
Definition coap_dtls.h:85
uint64_t version
(D)TLS runtime Library Version
Definition coap_dtls.h:84
const char * s_byte
signed char ptr
Definition coap_str.h:73
const uint8_t * u_byte
unsigned char ptr
Definition coap_str.h:74