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