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