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