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