1c87c5fbaSopenharmony_ci/*
2c87c5fbaSopenharmony_ci * coap_openssl.c -- Datagram Transport Layer Support for libcoap with openssl
3c87c5fbaSopenharmony_ci *
4c87c5fbaSopenharmony_ci * Copyright (C) 2017      Jean-Claude Michelou <jcm@spinetix.com>
5c87c5fbaSopenharmony_ci * Copyright (C) 2018-2023 Jon Shallow <supjps-libcoap@jpshallow.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_openssl.c
15c87c5fbaSopenharmony_ci * @brief OpenSSL specific interface functions.
16c87c5fbaSopenharmony_ci */
17c87c5fbaSopenharmony_ci
18c87c5fbaSopenharmony_ci#include "coap3/coap_internal.h"
19c87c5fbaSopenharmony_ci
20c87c5fbaSopenharmony_ci#ifdef COAP_WITH_LIBOPENSSL
21c87c5fbaSopenharmony_ci
22c87c5fbaSopenharmony_ci/*
23c87c5fbaSopenharmony_ci * OpenSSL 1.1.0 has support for making decisions during receipt of
24c87c5fbaSopenharmony_ci * the Client Hello - the call back function is set up using
25c87c5fbaSopenharmony_ci * SSL_CTX_set_tlsext_servername_callback() which is called later in the
26c87c5fbaSopenharmony_ci * Client Hello processing - but called every Client Hello.
27c87c5fbaSopenharmony_ci * Certificates and Preshared Keys have to be set up in the SSL CTX before
28c87c5fbaSopenharmony_ci * SSL_accept() is called, making the code messy to decide whether this is a
29c87c5fbaSopenharmony_ci * PKI or PSK incoming request to handle things accordingly if both are
30c87c5fbaSopenharmony_ci * defined.  SNI has to create a new SSL CTX to handle different server names
31c87c5fbaSopenharmony_ci * with different crtificates.
32c87c5fbaSopenharmony_ci *
33c87c5fbaSopenharmony_ci * OpenSSL 1.1.1 introduces a new function SSL_CTX_set_client_hello_cb().
34c87c5fbaSopenharmony_ci * The call back is invoked early on in the Client Hello processing giving
35c87c5fbaSopenharmony_ci * the ability to easily use different Preshared Keys, Certificates etc.
36c87c5fbaSopenharmony_ci * Certificates do not have to be set up in the SSL CTX before SSL_Accept is
37c87c5fbaSopenharmony_ci * called.
38c87c5fbaSopenharmony_ci * Later in the Client Hello code, the callback for
39c87c5fbaSopenharmony_ci * SSL_CTX_set_tlsext_servername_callback() is still called, but only if SNI
40c87c5fbaSopenharmony_ci * is being used by the client, so cannot be used for doing things the
41c87c5fbaSopenharmony_ci * OpenSSL 1.1.0 way.
42c87c5fbaSopenharmony_ci *
43c87c5fbaSopenharmony_ci * OpenSSL 1.1.1 supports TLS1.3.
44c87c5fbaSopenharmony_ci *
45c87c5fbaSopenharmony_ci * Consequently, this code has to have compile time options to include /
46c87c5fbaSopenharmony_ci * exclude code based on whether compiled against 1.1.0 or 1.1.1, as well as
47c87c5fbaSopenharmony_ci * have additional run time checks.
48c87c5fbaSopenharmony_ci *
49c87c5fbaSopenharmony_ci * It is possible to override the Ciphers, define the Algorithms or Groups
50c87c5fbaSopenharmony_ci * to use for the SSL negotiations at compile time. This is done by the adding
51c87c5fbaSopenharmony_ci * of the appropriate -D option to the CPPFLAGS parameter that is used on the
52c87c5fbaSopenharmony_ci * ./configure command line.
53c87c5fbaSopenharmony_ci * E.g.  ./configure CPPFLAGS="-DXX=\"YY\" -DUU=\"VV\""
54c87c5fbaSopenharmony_ci * The parameter value is case-sensitive.
55c87c5fbaSopenharmony_ci *
56c87c5fbaSopenharmony_ci * The ciphers can be overridden with (example)
57c87c5fbaSopenharmony_ci *  -DCOAP_OPENSSL_CIPHERS=\"ECDHE-ECDSA-AES256-GCM-SHA384\"
58c87c5fbaSopenharmony_ci *
59c87c5fbaSopenharmony_ci * The Algorithms can be defined by (example)
60c87c5fbaSopenharmony_ci *  -DCOAP_OPENSSL_SIGALGS=\"ed25519\"
61c87c5fbaSopenharmony_ci *
62c87c5fbaSopenharmony_ci * The Groups (OpenSSL 1.1.1 or later) can be defined by (example)
63c87c5fbaSopenharmony_ci *  -DCOAP_OPENSSL_GROUPS=\"X25519\"
64c87c5fbaSopenharmony_ci *
65c87c5fbaSopenharmony_ci */
66c87c5fbaSopenharmony_ci#include <openssl/ssl.h>
67c87c5fbaSopenharmony_ci#include <openssl/engine.h>
68c87c5fbaSopenharmony_ci#include <openssl/err.h>
69c87c5fbaSopenharmony_ci#include <openssl/rand.h>
70c87c5fbaSopenharmony_ci#include <openssl/hmac.h>
71c87c5fbaSopenharmony_ci#include <openssl/x509v3.h>
72c87c5fbaSopenharmony_ci
73c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x30000000L
74c87c5fbaSopenharmony_ci#ifdef __GNUC__
75c87c5fbaSopenharmony_ci/* Ignore OpenSSL 3.0 deprecated warnings for now */
76c87c5fbaSopenharmony_ci#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
77c87c5fbaSopenharmony_ci#endif
78c87c5fbaSopenharmony_ci#if defined(_WIN32)
79c87c5fbaSopenharmony_ci#if !defined(__MINGW32__)
80c87c5fbaSopenharmony_ci#pragma warning(disable : 4996)
81c87c5fbaSopenharmony_ci#endif /* ! __MINGW32__ */
82c87c5fbaSopenharmony_ci#endif /* _WIN32 */
83c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
84c87c5fbaSopenharmony_ci
85c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT
86c87c5fbaSopenharmony_ci# include <sys/epoll.h>
87c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */
88c87c5fbaSopenharmony_ci
89c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10100000L
90c87c5fbaSopenharmony_ci#error Must be compiled against OpenSSL 1.1.0 or later
91c87c5fbaSopenharmony_ci#endif
92c87c5fbaSopenharmony_ci
93c87c5fbaSopenharmony_ci#ifdef _WIN32
94c87c5fbaSopenharmony_ci#define strcasecmp _stricmp
95c87c5fbaSopenharmony_ci#define strncasecmp _strnicmp
96c87c5fbaSopenharmony_ci#endif
97c87c5fbaSopenharmony_ci
98c87c5fbaSopenharmony_ci/* RFC6091/RFC7250 */
99c87c5fbaSopenharmony_ci#ifndef TLSEXT_TYPE_client_certificate_type
100c87c5fbaSopenharmony_ci#define TLSEXT_TYPE_client_certificate_type 19
101c87c5fbaSopenharmony_ci#endif
102c87c5fbaSopenharmony_ci#ifndef TLSEXT_TYPE_server_certificate_type
103c87c5fbaSopenharmony_ci#define TLSEXT_TYPE_server_certificate_type 20
104c87c5fbaSopenharmony_ci#endif
105c87c5fbaSopenharmony_ci
106c87c5fbaSopenharmony_ci#ifndef COAP_OPENSSL_CIPHERS
107c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L
108c87c5fbaSopenharmony_ci#define COAP_OPENSSL_CIPHERS "TLSv1.3:TLSv1.2:!NULL"
109c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER < 0x10101000L */
110c87c5fbaSopenharmony_ci#define COAP_OPENSSL_CIPHERS "TLSv1.2:!NULL"
111c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
112c87c5fbaSopenharmony_ci#endif /*COAP_OPENSSL_CIPHERS */
113c87c5fbaSopenharmony_ci
114c87c5fbaSopenharmony_ci#ifndef COAP_OPENSSL_PSK_CIPHERS
115c87c5fbaSopenharmony_ci#define COAP_OPENSSL_PSK_CIPHERS "PSK:!NULL"
116c87c5fbaSopenharmony_ci#endif /*COAP_OPENSSL_PSK_CIPHERS */
117c87c5fbaSopenharmony_ci
118c87c5fbaSopenharmony_ci/* This structure encapsulates the OpenSSL context object. */
119c87c5fbaSopenharmony_citypedef struct coap_dtls_context_t {
120c87c5fbaSopenharmony_ci  SSL_CTX *ctx;
121c87c5fbaSopenharmony_ci  SSL *ssl;        /* OpenSSL object for listening to connection requests */
122c87c5fbaSopenharmony_ci  HMAC_CTX *cookie_hmac;
123c87c5fbaSopenharmony_ci  BIO_METHOD *meth;
124c87c5fbaSopenharmony_ci  BIO_ADDR *bio_addr;
125c87c5fbaSopenharmony_ci} coap_dtls_context_t;
126c87c5fbaSopenharmony_ci
127c87c5fbaSopenharmony_citypedef struct coap_tls_context_t {
128c87c5fbaSopenharmony_ci  SSL_CTX *ctx;
129c87c5fbaSopenharmony_ci  BIO_METHOD *meth;
130c87c5fbaSopenharmony_ci} coap_tls_context_t;
131c87c5fbaSopenharmony_ci
132c87c5fbaSopenharmony_ci#define IS_PSK 0x1
133c87c5fbaSopenharmony_ci#define IS_PKI 0x2
134c87c5fbaSopenharmony_ci
135c87c5fbaSopenharmony_citypedef struct sni_entry {
136c87c5fbaSopenharmony_ci  char *sni;
137c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
138c87c5fbaSopenharmony_ci  SSL_CTX *ctx;
139c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
140c87c5fbaSopenharmony_ci  coap_dtls_key_t pki_key;
141c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
142c87c5fbaSopenharmony_ci} sni_entry;
143c87c5fbaSopenharmony_ci
144c87c5fbaSopenharmony_citypedef struct psk_sni_entry {
145c87c5fbaSopenharmony_ci  char *sni;
146c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
147c87c5fbaSopenharmony_ci  SSL_CTX *ctx;
148c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
149c87c5fbaSopenharmony_ci  coap_dtls_spsk_info_t psk_info;
150c87c5fbaSopenharmony_ci} psk_sni_entry;
151c87c5fbaSopenharmony_ci
152c87c5fbaSopenharmony_citypedef struct coap_openssl_context_t {
153c87c5fbaSopenharmony_ci  coap_dtls_context_t dtls;
154c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
155c87c5fbaSopenharmony_ci  coap_tls_context_t tls;
156c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
157c87c5fbaSopenharmony_ci  coap_dtls_pki_t setup_data;
158c87c5fbaSopenharmony_ci  int psk_pki_enabled;
159c87c5fbaSopenharmony_ci  size_t sni_count;
160c87c5fbaSopenharmony_ci  sni_entry *sni_entry_list;
161c87c5fbaSopenharmony_ci  size_t psk_sni_count;
162c87c5fbaSopenharmony_ci  psk_sni_entry *psk_sni_entry_list;
163c87c5fbaSopenharmony_ci} coap_openssl_context_t;
164c87c5fbaSopenharmony_ci
165c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
166c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
167c87c5fbaSopenharmony_cistatic int psk_tls_server_name_call_back(SSL *ssl, int *sd, void *arg);
168c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
169c87c5fbaSopenharmony_cistatic int psk_tls_client_hello_call_back(SSL *ssl, int *al, void *arg);
170c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
171c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
172c87c5fbaSopenharmony_ci
173c87c5fbaSopenharmony_ciint
174c87c5fbaSopenharmony_cicoap_dtls_is_supported(void) {
175c87c5fbaSopenharmony_ci  if (SSLeay() < 0x10100000L) {
176c87c5fbaSopenharmony_ci    coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
177c87c5fbaSopenharmony_ci    return 0;
178c87c5fbaSopenharmony_ci  }
179c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L
180c87c5fbaSopenharmony_ci  /*
181c87c5fbaSopenharmony_ci   * For 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
182c87c5fbaSopenharmony_ci   * which is not in 1.1.0 instead of SSL_CTX_set_tlsext_servername_callback()
183c87c5fbaSopenharmony_ci   *
184c87c5fbaSopenharmony_ci   * However, there could be a runtime undefined external reference error
185c87c5fbaSopenharmony_ci   * as SSL_CTX_set_client_hello_cb() is not there in 1.1.0.
186c87c5fbaSopenharmony_ci   */
187c87c5fbaSopenharmony_ci  if (SSLeay() < 0x10101000L) {
188c87c5fbaSopenharmony_ci    coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
189c87c5fbaSopenharmony_ci    return 0;
190c87c5fbaSopenharmony_ci  }
191c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
192c87c5fbaSopenharmony_ci  return 1;
193c87c5fbaSopenharmony_ci}
194c87c5fbaSopenharmony_ci
195c87c5fbaSopenharmony_ciint
196c87c5fbaSopenharmony_cicoap_tls_is_supported(void) {
197c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
198c87c5fbaSopenharmony_ci  if (SSLeay() < 0x10100000L) {
199c87c5fbaSopenharmony_ci    coap_log_warn("OpenSSL version 1.1.0 or later is required\n");
200c87c5fbaSopenharmony_ci    return 0;
201c87c5fbaSopenharmony_ci  }
202c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L
203c87c5fbaSopenharmony_ci  if (SSLeay() < 0x10101000L) {
204c87c5fbaSopenharmony_ci    coap_log_warn("OpenSSL version 1.1.1 or later is required\n");
205c87c5fbaSopenharmony_ci    return 0;
206c87c5fbaSopenharmony_ci  }
207c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
208c87c5fbaSopenharmony_ci  return 1;
209c87c5fbaSopenharmony_ci#else /* COAP_DISABLE_TCP */
210c87c5fbaSopenharmony_ci  return 0;
211c87c5fbaSopenharmony_ci#endif /* COAP_DISABLE_TCP */
212c87c5fbaSopenharmony_ci}
213c87c5fbaSopenharmony_ci
214c87c5fbaSopenharmony_ci/*
215c87c5fbaSopenharmony_ci * return 0 failed
216c87c5fbaSopenharmony_ci *        1 passed
217c87c5fbaSopenharmony_ci */
218c87c5fbaSopenharmony_ciint
219c87c5fbaSopenharmony_cicoap_dtls_psk_is_supported(void) {
220c87c5fbaSopenharmony_ci  return 1;
221c87c5fbaSopenharmony_ci}
222c87c5fbaSopenharmony_ci
223c87c5fbaSopenharmony_ci/*
224c87c5fbaSopenharmony_ci * return 0 failed
225c87c5fbaSopenharmony_ci *        1 passed
226c87c5fbaSopenharmony_ci */
227c87c5fbaSopenharmony_ciint
228c87c5fbaSopenharmony_cicoap_dtls_pki_is_supported(void) {
229c87c5fbaSopenharmony_ci  return 1;
230c87c5fbaSopenharmony_ci}
231c87c5fbaSopenharmony_ci
232c87c5fbaSopenharmony_ci/*
233c87c5fbaSopenharmony_ci * return 0 failed
234c87c5fbaSopenharmony_ci *        1 passed
235c87c5fbaSopenharmony_ci */
236c87c5fbaSopenharmony_ciint
237c87c5fbaSopenharmony_cicoap_dtls_pkcs11_is_supported(void) {
238c87c5fbaSopenharmony_ci  return 1;
239c87c5fbaSopenharmony_ci}
240c87c5fbaSopenharmony_ci
241c87c5fbaSopenharmony_ci/*
242c87c5fbaSopenharmony_ci * return 0 failed
243c87c5fbaSopenharmony_ci *        1 passed
244c87c5fbaSopenharmony_ci */
245c87c5fbaSopenharmony_ciint
246c87c5fbaSopenharmony_cicoap_dtls_rpk_is_supported(void) {
247c87c5fbaSopenharmony_ci  return 0;
248c87c5fbaSopenharmony_ci}
249c87c5fbaSopenharmony_ci
250c87c5fbaSopenharmony_cicoap_tls_version_t *
251c87c5fbaSopenharmony_cicoap_get_tls_library_version(void) {
252c87c5fbaSopenharmony_ci  static coap_tls_version_t version;
253c87c5fbaSopenharmony_ci  version.version = SSLeay();
254c87c5fbaSopenharmony_ci  version.built_version = OPENSSL_VERSION_NUMBER;
255c87c5fbaSopenharmony_ci  version.type = COAP_TLS_LIBRARY_OPENSSL;
256c87c5fbaSopenharmony_ci  return &version;
257c87c5fbaSopenharmony_ci}
258c87c5fbaSopenharmony_ci
259c87c5fbaSopenharmony_cistatic ENGINE *ssl_engine = NULL;
260c87c5fbaSopenharmony_ci
261c87c5fbaSopenharmony_civoid
262c87c5fbaSopenharmony_cicoap_dtls_startup(void) {
263c87c5fbaSopenharmony_ci  SSL_load_error_strings();
264c87c5fbaSopenharmony_ci  SSL_library_init();
265c87c5fbaSopenharmony_ci  ENGINE_load_dynamic();
266c87c5fbaSopenharmony_ci}
267c87c5fbaSopenharmony_ci
268c87c5fbaSopenharmony_civoid
269c87c5fbaSopenharmony_cicoap_dtls_shutdown(void) {
270c87c5fbaSopenharmony_ci  if (ssl_engine) {
271c87c5fbaSopenharmony_ci    /* Release the functional reference from ENGINE_init() */
272c87c5fbaSopenharmony_ci    ENGINE_finish(ssl_engine);
273c87c5fbaSopenharmony_ci    /* Release the structural reference from ENGINE_by_id() */
274c87c5fbaSopenharmony_ci    ENGINE_free(ssl_engine);
275c87c5fbaSopenharmony_ci    ssl_engine = NULL;
276c87c5fbaSopenharmony_ci  }
277c87c5fbaSopenharmony_ci  ERR_free_strings();
278c87c5fbaSopenharmony_ci  coap_dtls_set_log_level(COAP_LOG_EMERG);
279c87c5fbaSopenharmony_ci}
280c87c5fbaSopenharmony_ci
281c87c5fbaSopenharmony_civoid *
282c87c5fbaSopenharmony_cicoap_dtls_get_tls(const coap_session_t *c_session,
283c87c5fbaSopenharmony_ci                  coap_tls_library_t *tls_lib) {
284c87c5fbaSopenharmony_ci  if (tls_lib)
285c87c5fbaSopenharmony_ci    *tls_lib = COAP_TLS_LIBRARY_OPENSSL;
286c87c5fbaSopenharmony_ci  if (c_session) {
287c87c5fbaSopenharmony_ci    return c_session->tls;
288c87c5fbaSopenharmony_ci  }
289c87c5fbaSopenharmony_ci  return NULL;
290c87c5fbaSopenharmony_ci}
291c87c5fbaSopenharmony_ci
292c87c5fbaSopenharmony_ci/*
293c87c5fbaSopenharmony_ci * Logging levels use the standard CoAP logging levels
294c87c5fbaSopenharmony_ci */
295c87c5fbaSopenharmony_cistatic coap_log_t dtls_log_level = COAP_LOG_EMERG;
296c87c5fbaSopenharmony_ci
297c87c5fbaSopenharmony_civoid
298c87c5fbaSopenharmony_cicoap_dtls_set_log_level(coap_log_t level) {
299c87c5fbaSopenharmony_ci  dtls_log_level = level;
300c87c5fbaSopenharmony_ci}
301c87c5fbaSopenharmony_ci
302c87c5fbaSopenharmony_cicoap_log_t
303c87c5fbaSopenharmony_cicoap_dtls_get_log_level(void) {
304c87c5fbaSopenharmony_ci  return dtls_log_level;
305c87c5fbaSopenharmony_ci}
306c87c5fbaSopenharmony_ci
307c87c5fbaSopenharmony_citypedef struct coap_ssl_st {
308c87c5fbaSopenharmony_ci  coap_session_t *session;
309c87c5fbaSopenharmony_ci  const void *pdu;
310c87c5fbaSopenharmony_ci  unsigned pdu_len;
311c87c5fbaSopenharmony_ci  unsigned peekmode;
312c87c5fbaSopenharmony_ci  coap_tick_t timeout;
313c87c5fbaSopenharmony_ci} coap_ssl_data;
314c87c5fbaSopenharmony_ci
315c87c5fbaSopenharmony_cistatic int
316c87c5fbaSopenharmony_cicoap_dgram_create(BIO *a) {
317c87c5fbaSopenharmony_ci  coap_ssl_data *data = NULL;
318c87c5fbaSopenharmony_ci  data = malloc(sizeof(coap_ssl_data));
319c87c5fbaSopenharmony_ci  if (data == NULL)
320c87c5fbaSopenharmony_ci    return 0;
321c87c5fbaSopenharmony_ci  BIO_set_init(a, 1);
322c87c5fbaSopenharmony_ci  BIO_set_data(a, data);
323c87c5fbaSopenharmony_ci  memset(data, 0x00, sizeof(coap_ssl_data));
324c87c5fbaSopenharmony_ci  return 1;
325c87c5fbaSopenharmony_ci}
326c87c5fbaSopenharmony_ci
327c87c5fbaSopenharmony_cistatic int
328c87c5fbaSopenharmony_cicoap_dgram_destroy(BIO *a) {
329c87c5fbaSopenharmony_ci  coap_ssl_data *data;
330c87c5fbaSopenharmony_ci  if (a == NULL)
331c87c5fbaSopenharmony_ci    return 0;
332c87c5fbaSopenharmony_ci  data = (coap_ssl_data *)BIO_get_data(a);
333c87c5fbaSopenharmony_ci  if (data != NULL)
334c87c5fbaSopenharmony_ci    free(data);
335c87c5fbaSopenharmony_ci  return 1;
336c87c5fbaSopenharmony_ci}
337c87c5fbaSopenharmony_ci
338c87c5fbaSopenharmony_cistatic int
339c87c5fbaSopenharmony_cicoap_dgram_read(BIO *a, char *out, int outl) {
340c87c5fbaSopenharmony_ci  int ret = 0;
341c87c5fbaSopenharmony_ci  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
342c87c5fbaSopenharmony_ci
343c87c5fbaSopenharmony_ci  if (out != NULL) {
344c87c5fbaSopenharmony_ci    if (data != NULL && data->pdu_len > 0) {
345c87c5fbaSopenharmony_ci      if (outl < (int)data->pdu_len) {
346c87c5fbaSopenharmony_ci        memcpy(out, data->pdu, outl);
347c87c5fbaSopenharmony_ci        ret = outl;
348c87c5fbaSopenharmony_ci      } else {
349c87c5fbaSopenharmony_ci        memcpy(out, data->pdu, data->pdu_len);
350c87c5fbaSopenharmony_ci        ret = (int)data->pdu_len;
351c87c5fbaSopenharmony_ci      }
352c87c5fbaSopenharmony_ci      if (!data->peekmode) {
353c87c5fbaSopenharmony_ci        data->pdu_len = 0;
354c87c5fbaSopenharmony_ci        data->pdu = NULL;
355c87c5fbaSopenharmony_ci      }
356c87c5fbaSopenharmony_ci    } else {
357c87c5fbaSopenharmony_ci      ret = -1;
358c87c5fbaSopenharmony_ci    }
359c87c5fbaSopenharmony_ci    BIO_clear_retry_flags(a);
360c87c5fbaSopenharmony_ci    if (ret < 0)
361c87c5fbaSopenharmony_ci      BIO_set_retry_read(a);
362c87c5fbaSopenharmony_ci  }
363c87c5fbaSopenharmony_ci  return ret;
364c87c5fbaSopenharmony_ci}
365c87c5fbaSopenharmony_ci
366c87c5fbaSopenharmony_cistatic int
367c87c5fbaSopenharmony_cicoap_dgram_write(BIO *a, const char *in, int inl) {
368c87c5fbaSopenharmony_ci  int ret = 0;
369c87c5fbaSopenharmony_ci  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(a);
370c87c5fbaSopenharmony_ci
371c87c5fbaSopenharmony_ci  if (data->session) {
372c87c5fbaSopenharmony_ci    if (!coap_netif_available(data->session)
373c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
374c87c5fbaSopenharmony_ci        && data->session->endpoint == NULL
375c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
376c87c5fbaSopenharmony_ci       ) {
377c87c5fbaSopenharmony_ci      /* socket was closed on client due to error */
378c87c5fbaSopenharmony_ci      BIO_clear_retry_flags(a);
379c87c5fbaSopenharmony_ci      errno = ECONNRESET;
380c87c5fbaSopenharmony_ci      return -1;
381c87c5fbaSopenharmony_ci    }
382c87c5fbaSopenharmony_ci    ret = (int)data->session->sock.lfunc[COAP_LAYER_TLS].l_write(data->session,
383c87c5fbaSopenharmony_ci          (const uint8_t *)in,
384c87c5fbaSopenharmony_ci          inl);
385c87c5fbaSopenharmony_ci    BIO_clear_retry_flags(a);
386c87c5fbaSopenharmony_ci    if (ret <= 0)
387c87c5fbaSopenharmony_ci      BIO_set_retry_write(a);
388c87c5fbaSopenharmony_ci  } else {
389c87c5fbaSopenharmony_ci    BIO_clear_retry_flags(a);
390c87c5fbaSopenharmony_ci    ret = -1;
391c87c5fbaSopenharmony_ci  }
392c87c5fbaSopenharmony_ci  return ret;
393c87c5fbaSopenharmony_ci}
394c87c5fbaSopenharmony_ci
395c87c5fbaSopenharmony_cistatic int
396c87c5fbaSopenharmony_cicoap_dgram_puts(BIO *a, const char *pstr) {
397c87c5fbaSopenharmony_ci  return coap_dgram_write(a, pstr, (int)strlen(pstr));
398c87c5fbaSopenharmony_ci}
399c87c5fbaSopenharmony_ci
400c87c5fbaSopenharmony_cistatic long
401c87c5fbaSopenharmony_cicoap_dgram_ctrl(BIO *a, int cmd, long num, void *ptr) {
402c87c5fbaSopenharmony_ci  long ret = 1;
403c87c5fbaSopenharmony_ci  coap_ssl_data *data = BIO_get_data(a);
404c87c5fbaSopenharmony_ci
405c87c5fbaSopenharmony_ci  (void)ptr;
406c87c5fbaSopenharmony_ci
407c87c5fbaSopenharmony_ci  switch (cmd) {
408c87c5fbaSopenharmony_ci  case BIO_CTRL_GET_CLOSE:
409c87c5fbaSopenharmony_ci    ret = BIO_get_shutdown(a);
410c87c5fbaSopenharmony_ci    break;
411c87c5fbaSopenharmony_ci  case BIO_CTRL_SET_CLOSE:
412c87c5fbaSopenharmony_ci    BIO_set_shutdown(a, (int)num);
413c87c5fbaSopenharmony_ci    ret = 1;
414c87c5fbaSopenharmony_ci    break;
415c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_PEEK_MODE:
416c87c5fbaSopenharmony_ci    data->peekmode = (unsigned)num;
417c87c5fbaSopenharmony_ci    break;
418c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_CONNECT:
419c87c5fbaSopenharmony_ci  case BIO_C_SET_FD:
420c87c5fbaSopenharmony_ci  case BIO_C_GET_FD:
421c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_DONT_FRAG:
422c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_MTU:
423c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_MTU:
424c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_QUERY_MTU:
425c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_FALLBACK_MTU:
426c87c5fbaSopenharmony_ci    ret = -1;
427c87c5fbaSopenharmony_ci    break;
428c87c5fbaSopenharmony_ci  case BIO_CTRL_DUP:
429c87c5fbaSopenharmony_ci  case BIO_CTRL_FLUSH:
430c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_MTU_DISCOVER:
431c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_CONNECTED:
432c87c5fbaSopenharmony_ci    ret = 1;
433c87c5fbaSopenharmony_ci    break;
434c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_NEXT_TIMEOUT:
435c87c5fbaSopenharmony_ci    data->timeout = coap_ticks_from_rt_us((uint64_t)((struct timeval *)ptr)->tv_sec * 1000000 + ((
436c87c5fbaSopenharmony_ci                                              struct timeval *)ptr)->tv_usec);
437c87c5fbaSopenharmony_ci    ret = 1;
438c87c5fbaSopenharmony_ci    break;
439c87c5fbaSopenharmony_ci  case BIO_CTRL_RESET:
440c87c5fbaSopenharmony_ci  case BIO_C_FILE_SEEK:
441c87c5fbaSopenharmony_ci  case BIO_C_FILE_TELL:
442c87c5fbaSopenharmony_ci  case BIO_CTRL_INFO:
443c87c5fbaSopenharmony_ci  case BIO_CTRL_PENDING:
444c87c5fbaSopenharmony_ci  case BIO_CTRL_WPENDING:
445c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_PEER:
446c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_PEER:
447c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
448c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
449c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
450c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
451c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
452c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
453c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_MTU_EXCEEDED:
454c87c5fbaSopenharmony_ci  case BIO_CTRL_DGRAM_GET_MTU_OVERHEAD:
455c87c5fbaSopenharmony_ci  default:
456c87c5fbaSopenharmony_ci    ret = 0;
457c87c5fbaSopenharmony_ci    break;
458c87c5fbaSopenharmony_ci  }
459c87c5fbaSopenharmony_ci  return ret;
460c87c5fbaSopenharmony_ci}
461c87c5fbaSopenharmony_ci
462c87c5fbaSopenharmony_cistatic int
463c87c5fbaSopenharmony_cicoap_dtls_generate_cookie(SSL *ssl,
464c87c5fbaSopenharmony_ci                          unsigned char *cookie,
465c87c5fbaSopenharmony_ci                          unsigned int *cookie_len) {
466c87c5fbaSopenharmony_ci  coap_dtls_context_t *dtls =
467c87c5fbaSopenharmony_ci      (coap_dtls_context_t *)SSL_CTX_get_app_data(SSL_get_SSL_CTX(ssl));
468c87c5fbaSopenharmony_ci  coap_ssl_data *data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
469c87c5fbaSopenharmony_ci  int r = HMAC_Init_ex(dtls->cookie_hmac, NULL, 0, NULL, NULL);
470c87c5fbaSopenharmony_ci  r &= HMAC_Update(dtls->cookie_hmac,
471c87c5fbaSopenharmony_ci                   (const uint8_t *)&data->session->addr_info.local.addr,
472c87c5fbaSopenharmony_ci                   (size_t)data->session->addr_info.local.size);
473c87c5fbaSopenharmony_ci  r &= HMAC_Update(dtls->cookie_hmac,
474c87c5fbaSopenharmony_ci                   (const uint8_t *)&data->session->addr_info.remote.addr,
475c87c5fbaSopenharmony_ci                   (size_t)data->session->addr_info.remote.size);
476c87c5fbaSopenharmony_ci  r &= HMAC_Final(dtls->cookie_hmac, cookie, cookie_len);
477c87c5fbaSopenharmony_ci  return r;
478c87c5fbaSopenharmony_ci}
479c87c5fbaSopenharmony_ci
480c87c5fbaSopenharmony_cistatic int
481c87c5fbaSopenharmony_cicoap_dtls_verify_cookie(SSL *ssl,
482c87c5fbaSopenharmony_ci                        const uint8_t *cookie,
483c87c5fbaSopenharmony_ci                        unsigned int cookie_len) {
484c87c5fbaSopenharmony_ci  uint8_t hmac[32];
485c87c5fbaSopenharmony_ci  unsigned len = 32;
486c87c5fbaSopenharmony_ci  if (coap_dtls_generate_cookie(ssl, hmac, &len) &&
487c87c5fbaSopenharmony_ci      cookie_len == len && memcmp(cookie, hmac, len) == 0)
488c87c5fbaSopenharmony_ci    return 1;
489c87c5fbaSopenharmony_ci  else
490c87c5fbaSopenharmony_ci    return 0;
491c87c5fbaSopenharmony_ci}
492c87c5fbaSopenharmony_ci
493c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
494c87c5fbaSopenharmony_cistatic unsigned int
495c87c5fbaSopenharmony_cicoap_dtls_psk_client_callback(SSL *ssl,
496c87c5fbaSopenharmony_ci                              const char *hint,
497c87c5fbaSopenharmony_ci                              char *identity,
498c87c5fbaSopenharmony_ci                              unsigned int max_identity_len,
499c87c5fbaSopenharmony_ci                              unsigned char *psk,
500c87c5fbaSopenharmony_ci                              unsigned int max_psk_len) {
501c87c5fbaSopenharmony_ci  coap_session_t *c_session;
502c87c5fbaSopenharmony_ci  coap_openssl_context_t *o_context;
503c87c5fbaSopenharmony_ci  coap_dtls_cpsk_t *setup_data;
504c87c5fbaSopenharmony_ci  coap_bin_const_t temp;
505c87c5fbaSopenharmony_ci  const coap_dtls_cpsk_info_t *cpsk_info;
506c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_key;
507c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_identity;
508c87c5fbaSopenharmony_ci
509c87c5fbaSopenharmony_ci  c_session = (coap_session_t *)SSL_get_app_data(ssl);
510c87c5fbaSopenharmony_ci  if (c_session == NULL)
511c87c5fbaSopenharmony_ci    return 0;
512c87c5fbaSopenharmony_ci  o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
513c87c5fbaSopenharmony_ci  if (o_context == NULL)
514c87c5fbaSopenharmony_ci    return 0;
515c87c5fbaSopenharmony_ci  setup_data = &c_session->cpsk_setup_data;
516c87c5fbaSopenharmony_ci
517c87c5fbaSopenharmony_ci  temp.s = hint ? (const uint8_t *)hint : (const uint8_t *)"";
518c87c5fbaSopenharmony_ci  temp.length = strlen((const char *)temp.s);
519c87c5fbaSopenharmony_ci  coap_session_refresh_psk_hint(c_session, &temp);
520c87c5fbaSopenharmony_ci
521c87c5fbaSopenharmony_ci  coap_log_debug("got psk_identity_hint: '%.*s'\n", (int)temp.length,
522c87c5fbaSopenharmony_ci                 (const char *)temp.s);
523c87c5fbaSopenharmony_ci
524c87c5fbaSopenharmony_ci  if (setup_data->validate_ih_call_back) {
525c87c5fbaSopenharmony_ci    coap_str_const_t lhint;
526c87c5fbaSopenharmony_ci
527c87c5fbaSopenharmony_ci    lhint.s = temp.s;
528c87c5fbaSopenharmony_ci    lhint.length = temp.length;
529c87c5fbaSopenharmony_ci    cpsk_info =
530c87c5fbaSopenharmony_ci        setup_data->validate_ih_call_back(&lhint,
531c87c5fbaSopenharmony_ci                                          c_session,
532c87c5fbaSopenharmony_ci                                          setup_data->ih_call_back_arg);
533c87c5fbaSopenharmony_ci
534c87c5fbaSopenharmony_ci    if (cpsk_info == NULL)
535c87c5fbaSopenharmony_ci      return 0;
536c87c5fbaSopenharmony_ci
537c87c5fbaSopenharmony_ci    coap_session_refresh_psk_identity(c_session, &cpsk_info->identity);
538c87c5fbaSopenharmony_ci    coap_session_refresh_psk_key(c_session, &cpsk_info->key);
539c87c5fbaSopenharmony_ci    psk_identity = &cpsk_info->identity;
540c87c5fbaSopenharmony_ci    psk_key = &cpsk_info->key;
541c87c5fbaSopenharmony_ci  } else {
542c87c5fbaSopenharmony_ci    psk_identity = coap_get_session_client_psk_identity(c_session);
543c87c5fbaSopenharmony_ci    psk_key = coap_get_session_client_psk_key(c_session);
544c87c5fbaSopenharmony_ci  }
545c87c5fbaSopenharmony_ci
546c87c5fbaSopenharmony_ci  if (psk_identity == NULL || psk_key == NULL) {
547c87c5fbaSopenharmony_ci    coap_log_warn("no PSK available\n");
548c87c5fbaSopenharmony_ci    return 0;
549c87c5fbaSopenharmony_ci  }
550c87c5fbaSopenharmony_ci
551c87c5fbaSopenharmony_ci  /* identity has to be NULL terminated */
552c87c5fbaSopenharmony_ci  if (!max_identity_len)
553c87c5fbaSopenharmony_ci    return 0;
554c87c5fbaSopenharmony_ci  max_identity_len--;
555c87c5fbaSopenharmony_ci  if (psk_identity->length > max_identity_len) {
556c87c5fbaSopenharmony_ci    coap_log_warn("psk_identity too large, truncated to %d bytes\n",
557c87c5fbaSopenharmony_ci                  max_identity_len);
558c87c5fbaSopenharmony_ci  } else {
559c87c5fbaSopenharmony_ci    /* Reduce to match */
560c87c5fbaSopenharmony_ci    max_identity_len = (unsigned int)psk_identity->length;
561c87c5fbaSopenharmony_ci  }
562c87c5fbaSopenharmony_ci  memcpy(identity, psk_identity->s, max_identity_len);
563c87c5fbaSopenharmony_ci  identity[max_identity_len] = '\000';
564c87c5fbaSopenharmony_ci
565c87c5fbaSopenharmony_ci  if (psk_key->length > max_psk_len) {
566c87c5fbaSopenharmony_ci    coap_log_warn("psk_key too large, truncated to %d bytes\n",
567c87c5fbaSopenharmony_ci                  max_psk_len);
568c87c5fbaSopenharmony_ci  } else {
569c87c5fbaSopenharmony_ci    /* Reduce to match */
570c87c5fbaSopenharmony_ci    max_psk_len = (unsigned int)psk_key->length;
571c87c5fbaSopenharmony_ci  }
572c87c5fbaSopenharmony_ci  memcpy(psk, psk_key->s, max_psk_len);
573c87c5fbaSopenharmony_ci  return max_psk_len;
574c87c5fbaSopenharmony_ci}
575c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
576c87c5fbaSopenharmony_ci
577c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
578c87c5fbaSopenharmony_cistatic unsigned int
579c87c5fbaSopenharmony_cicoap_dtls_psk_server_callback(
580c87c5fbaSopenharmony_ci    SSL *ssl,
581c87c5fbaSopenharmony_ci    const char *identity,
582c87c5fbaSopenharmony_ci    unsigned char *psk,
583c87c5fbaSopenharmony_ci    unsigned int max_psk_len
584c87c5fbaSopenharmony_ci) {
585c87c5fbaSopenharmony_ci  coap_session_t *c_session;
586c87c5fbaSopenharmony_ci  coap_dtls_spsk_t *setup_data;
587c87c5fbaSopenharmony_ci  coap_bin_const_t lidentity;
588c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_key;
589c87c5fbaSopenharmony_ci
590c87c5fbaSopenharmony_ci  c_session = (coap_session_t *)SSL_get_app_data(ssl);
591c87c5fbaSopenharmony_ci  if (c_session == NULL)
592c87c5fbaSopenharmony_ci    return 0;
593c87c5fbaSopenharmony_ci
594c87c5fbaSopenharmony_ci  setup_data = &c_session->context->spsk_setup_data;
595c87c5fbaSopenharmony_ci
596c87c5fbaSopenharmony_ci  /* Track the Identity being used */
597c87c5fbaSopenharmony_ci  lidentity.s = identity ? (const uint8_t *)identity : (const uint8_t *)"";
598c87c5fbaSopenharmony_ci  lidentity.length = strlen((const char *)lidentity.s);
599c87c5fbaSopenharmony_ci  coap_session_refresh_psk_identity(c_session, &lidentity);
600c87c5fbaSopenharmony_ci
601c87c5fbaSopenharmony_ci  coap_log_debug("got psk_identity: '%.*s'\n",
602c87c5fbaSopenharmony_ci                 (int)lidentity.length, (const char *)lidentity.s);
603c87c5fbaSopenharmony_ci
604c87c5fbaSopenharmony_ci  if (setup_data->validate_id_call_back) {
605c87c5fbaSopenharmony_ci    psk_key = setup_data->validate_id_call_back(&lidentity,
606c87c5fbaSopenharmony_ci                                                c_session,
607c87c5fbaSopenharmony_ci                                                setup_data->id_call_back_arg);
608c87c5fbaSopenharmony_ci
609c87c5fbaSopenharmony_ci    coap_session_refresh_psk_key(c_session, psk_key);
610c87c5fbaSopenharmony_ci  } else {
611c87c5fbaSopenharmony_ci    psk_key = coap_get_session_server_psk_key(c_session);
612c87c5fbaSopenharmony_ci  }
613c87c5fbaSopenharmony_ci
614c87c5fbaSopenharmony_ci  if (psk_key == NULL)
615c87c5fbaSopenharmony_ci    return 0;
616c87c5fbaSopenharmony_ci
617c87c5fbaSopenharmony_ci  if (psk_key->length > max_psk_len) {
618c87c5fbaSopenharmony_ci    coap_log_warn("psk_key too large, truncated to %d bytes\n",
619c87c5fbaSopenharmony_ci                  max_psk_len);
620c87c5fbaSopenharmony_ci  } else {
621c87c5fbaSopenharmony_ci    /* Reduce to match */
622c87c5fbaSopenharmony_ci    max_psk_len = (unsigned int)psk_key->length;
623c87c5fbaSopenharmony_ci  }
624c87c5fbaSopenharmony_ci  memcpy(psk, psk_key->s, max_psk_len);
625c87c5fbaSopenharmony_ci  return max_psk_len;
626c87c5fbaSopenharmony_ci}
627c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
628c87c5fbaSopenharmony_ci
629c87c5fbaSopenharmony_cistatic const char *
630c87c5fbaSopenharmony_cissl_function_definition(unsigned long e) {
631c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x30000000L
632c87c5fbaSopenharmony_ci  (void)e;
633c87c5fbaSopenharmony_ci  return "";
634c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER < 0x30000000L */
635c87c5fbaSopenharmony_ci  static char buff[80];
636c87c5fbaSopenharmony_ci
637c87c5fbaSopenharmony_ci  snprintf(buff, sizeof(buff), " at %s:%s",
638c87c5fbaSopenharmony_ci           ERR_lib_error_string(e), ERR_func_error_string(e));
639c87c5fbaSopenharmony_ci  return buff;
640c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x30000000L */
641c87c5fbaSopenharmony_ci}
642c87c5fbaSopenharmony_ci
643c87c5fbaSopenharmony_cistatic void
644c87c5fbaSopenharmony_cicoap_dtls_info_callback(const SSL *ssl, int where, int ret) {
645c87c5fbaSopenharmony_ci  coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
646c87c5fbaSopenharmony_ci  const char *pstr;
647c87c5fbaSopenharmony_ci  int w = where &~SSL_ST_MASK;
648c87c5fbaSopenharmony_ci
649c87c5fbaSopenharmony_ci  if (w & SSL_ST_CONNECT)
650c87c5fbaSopenharmony_ci    pstr = "SSL_connect";
651c87c5fbaSopenharmony_ci  else if (w & SSL_ST_ACCEPT)
652c87c5fbaSopenharmony_ci    pstr = "SSL_accept";
653c87c5fbaSopenharmony_ci  else
654c87c5fbaSopenharmony_ci    pstr = "undefined";
655c87c5fbaSopenharmony_ci
656c87c5fbaSopenharmony_ci  if (where & SSL_CB_LOOP) {
657c87c5fbaSopenharmony_ci    coap_dtls_log(COAP_LOG_DEBUG, "*  %s: %s:%s\n",
658c87c5fbaSopenharmony_ci                  coap_session_str(session), pstr, SSL_state_string_long(ssl));
659c87c5fbaSopenharmony_ci  } else if (where & SSL_CB_ALERT) {
660c87c5fbaSopenharmony_ci    coap_log_t log_level = COAP_LOG_INFO;
661c87c5fbaSopenharmony_ci    pstr = (where & SSL_CB_READ) ? "read" : "write";
662c87c5fbaSopenharmony_ci    if ((where & (SSL_CB_WRITE|SSL_CB_READ)) && (ret >> 8) == SSL3_AL_FATAL) {
663c87c5fbaSopenharmony_ci      session->dtls_event = COAP_EVENT_DTLS_ERROR;
664c87c5fbaSopenharmony_ci      if ((ret & 0xff) != SSL3_AD_CLOSE_NOTIFY)
665c87c5fbaSopenharmony_ci        log_level = COAP_LOG_WARN;
666c87c5fbaSopenharmony_ci    }
667c87c5fbaSopenharmony_ci    /* Need to let CoAP logging know why this session is dying */
668c87c5fbaSopenharmony_ci    coap_log(log_level, "*  %s: SSL3 alert %s:%s:%s\n",
669c87c5fbaSopenharmony_ci             coap_session_str(session),
670c87c5fbaSopenharmony_ci             pstr,
671c87c5fbaSopenharmony_ci             SSL_alert_type_string_long(ret),
672c87c5fbaSopenharmony_ci             SSL_alert_desc_string_long(ret));
673c87c5fbaSopenharmony_ci  } else if (where & SSL_CB_EXIT) {
674c87c5fbaSopenharmony_ci    if (ret == 0) {
675c87c5fbaSopenharmony_ci      if (dtls_log_level >= COAP_LOG_WARN) {
676c87c5fbaSopenharmony_ci        unsigned long e;
677c87c5fbaSopenharmony_ci        coap_dtls_log(COAP_LOG_WARN, "*  %s: %s:failed in %s\n",
678c87c5fbaSopenharmony_ci                      coap_session_str(session), pstr, SSL_state_string_long(ssl));
679c87c5fbaSopenharmony_ci        while ((e = ERR_get_error()))
680c87c5fbaSopenharmony_ci          coap_dtls_log(COAP_LOG_WARN, "*  %s: %s%s\n",
681c87c5fbaSopenharmony_ci                        coap_session_str(session), ERR_reason_error_string(e),
682c87c5fbaSopenharmony_ci                        ssl_function_definition(e));
683c87c5fbaSopenharmony_ci      }
684c87c5fbaSopenharmony_ci    } else if (ret < 0) {
685c87c5fbaSopenharmony_ci      if (dtls_log_level >= COAP_LOG_WARN) {
686c87c5fbaSopenharmony_ci        int err = SSL_get_error(ssl, ret);
687c87c5fbaSopenharmony_ci        if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE &&
688c87c5fbaSopenharmony_ci            err != SSL_ERROR_WANT_CONNECT && err != SSL_ERROR_WANT_ACCEPT &&
689c87c5fbaSopenharmony_ci            err != SSL_ERROR_WANT_X509_LOOKUP) {
690c87c5fbaSopenharmony_ci          long e;
691c87c5fbaSopenharmony_ci          coap_dtls_log(COAP_LOG_WARN, "*  %s: %s:error in %s\n",
692c87c5fbaSopenharmony_ci                        coap_session_str(session), pstr, SSL_state_string_long(ssl));
693c87c5fbaSopenharmony_ci          while ((e = ERR_get_error()))
694c87c5fbaSopenharmony_ci            coap_dtls_log(COAP_LOG_WARN, "*  %s: %s%s\n",
695c87c5fbaSopenharmony_ci                          coap_session_str(session), ERR_reason_error_string(e),
696c87c5fbaSopenharmony_ci                          ssl_function_definition(e));
697c87c5fbaSopenharmony_ci        }
698c87c5fbaSopenharmony_ci      }
699c87c5fbaSopenharmony_ci    }
700c87c5fbaSopenharmony_ci  }
701c87c5fbaSopenharmony_ci
702c87c5fbaSopenharmony_ci  if (where == SSL_CB_HANDSHAKE_START && SSL_get_state(ssl) == TLS_ST_OK)
703c87c5fbaSopenharmony_ci    session->dtls_event = COAP_EVENT_DTLS_RENEGOTIATE;
704c87c5fbaSopenharmony_ci}
705c87c5fbaSopenharmony_ci
706c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
707c87c5fbaSopenharmony_cistatic int
708c87c5fbaSopenharmony_cicoap_sock_create(BIO *a) {
709c87c5fbaSopenharmony_ci  BIO_set_init(a, 1);
710c87c5fbaSopenharmony_ci  return 1;
711c87c5fbaSopenharmony_ci}
712c87c5fbaSopenharmony_ci
713c87c5fbaSopenharmony_cistatic int
714c87c5fbaSopenharmony_cicoap_sock_destroy(BIO *a) {
715c87c5fbaSopenharmony_ci  (void)a;
716c87c5fbaSopenharmony_ci  return 1;
717c87c5fbaSopenharmony_ci}
718c87c5fbaSopenharmony_ci
719c87c5fbaSopenharmony_ci/*
720c87c5fbaSopenharmony_ci * strm
721c87c5fbaSopenharmony_ci * return +ve data amount
722c87c5fbaSopenharmony_ci *        0   no more
723c87c5fbaSopenharmony_ci *        -1  error
724c87c5fbaSopenharmony_ci */
725c87c5fbaSopenharmony_cistatic int
726c87c5fbaSopenharmony_cicoap_sock_read(BIO *a, char *out, int outl) {
727c87c5fbaSopenharmony_ci  int ret = 0;
728c87c5fbaSopenharmony_ci  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
729c87c5fbaSopenharmony_ci
730c87c5fbaSopenharmony_ci  if (out != NULL) {
731c87c5fbaSopenharmony_ci    ret =(int)session->sock.lfunc[COAP_LAYER_TLS].l_read(session, (u_char *)out,
732c87c5fbaSopenharmony_ci                                                         outl);
733c87c5fbaSopenharmony_ci    /* Translate layer returns into what OpenSSL expects */
734c87c5fbaSopenharmony_ci    if (ret == 0) {
735c87c5fbaSopenharmony_ci      BIO_set_retry_read(a);
736c87c5fbaSopenharmony_ci      ret = -1;
737c87c5fbaSopenharmony_ci    } else {
738c87c5fbaSopenharmony_ci      BIO_clear_retry_flags(a);
739c87c5fbaSopenharmony_ci    }
740c87c5fbaSopenharmony_ci  }
741c87c5fbaSopenharmony_ci  return ret;
742c87c5fbaSopenharmony_ci}
743c87c5fbaSopenharmony_ci
744c87c5fbaSopenharmony_ci/*
745c87c5fbaSopenharmony_ci * strm
746c87c5fbaSopenharmony_ci * return +ve data amount
747c87c5fbaSopenharmony_ci *        0   no more
748c87c5fbaSopenharmony_ci *        -1  error (error in errno)
749c87c5fbaSopenharmony_ci */
750c87c5fbaSopenharmony_cistatic int
751c87c5fbaSopenharmony_cicoap_sock_write(BIO *a, const char *in, int inl) {
752c87c5fbaSopenharmony_ci  int ret = 0;
753c87c5fbaSopenharmony_ci  coap_session_t *session = (coap_session_t *)BIO_get_data(a);
754c87c5fbaSopenharmony_ci
755c87c5fbaSopenharmony_ci  ret = (int)session->sock.lfunc[COAP_LAYER_TLS].l_write(session,
756c87c5fbaSopenharmony_ci                                                         (const uint8_t *)in,
757c87c5fbaSopenharmony_ci                                                         inl);
758c87c5fbaSopenharmony_ci  /* Translate layer what returns into what OpenSSL expects */
759c87c5fbaSopenharmony_ci  BIO_clear_retry_flags(a);
760c87c5fbaSopenharmony_ci  if (ret == 0) {
761c87c5fbaSopenharmony_ci    BIO_set_retry_read(a);
762c87c5fbaSopenharmony_ci    ret = -1;
763c87c5fbaSopenharmony_ci  } else {
764c87c5fbaSopenharmony_ci    BIO_clear_retry_flags(a);
765c87c5fbaSopenharmony_ci    if (ret == -1) {
766c87c5fbaSopenharmony_ci      if ((session->state == COAP_SESSION_STATE_CSM ||
767c87c5fbaSopenharmony_ci           session->state == COAP_SESSION_STATE_HANDSHAKE) &&
768c87c5fbaSopenharmony_ci          (errno == EPIPE || errno == ECONNRESET)) {
769c87c5fbaSopenharmony_ci        /*
770c87c5fbaSopenharmony_ci         * Need to handle a TCP timing window where an agent continues with
771c87c5fbaSopenharmony_ci         * the sending of the next handshake or a CSM.
772c87c5fbaSopenharmony_ci         * However, the peer does not like a certificate and so sends a
773c87c5fbaSopenharmony_ci         * fatal alert and closes the TCP session.
774c87c5fbaSopenharmony_ci         * The sending of the next handshake or CSM may get terminated because
775c87c5fbaSopenharmony_ci         * of the closed TCP session, but there is still an outstanding alert
776c87c5fbaSopenharmony_ci         * to be read in and reported on.
777c87c5fbaSopenharmony_ci         * In this case, pretend that sending the info was fine so that the
778c87c5fbaSopenharmony_ci         * alert can be read (which effectively is what happens with DTLS).
779c87c5fbaSopenharmony_ci         */
780c87c5fbaSopenharmony_ci        ret = inl;
781c87c5fbaSopenharmony_ci      }
782c87c5fbaSopenharmony_ci    }
783c87c5fbaSopenharmony_ci  }
784c87c5fbaSopenharmony_ci  return ret;
785c87c5fbaSopenharmony_ci}
786c87c5fbaSopenharmony_ci
787c87c5fbaSopenharmony_cistatic int
788c87c5fbaSopenharmony_cicoap_sock_puts(BIO *a, const char *pstr) {
789c87c5fbaSopenharmony_ci  return coap_sock_write(a, pstr, (int)strlen(pstr));
790c87c5fbaSopenharmony_ci}
791c87c5fbaSopenharmony_ci
792c87c5fbaSopenharmony_cistatic long
793c87c5fbaSopenharmony_cicoap_sock_ctrl(BIO *a, int cmd, long num, void *ptr) {
794c87c5fbaSopenharmony_ci  int r = 1;
795c87c5fbaSopenharmony_ci  (void)a;
796c87c5fbaSopenharmony_ci  (void)ptr;
797c87c5fbaSopenharmony_ci  (void)num;
798c87c5fbaSopenharmony_ci
799c87c5fbaSopenharmony_ci  switch (cmd) {
800c87c5fbaSopenharmony_ci  case BIO_C_SET_FD:
801c87c5fbaSopenharmony_ci  case BIO_C_GET_FD:
802c87c5fbaSopenharmony_ci    r = -1;
803c87c5fbaSopenharmony_ci    break;
804c87c5fbaSopenharmony_ci  case BIO_CTRL_SET_CLOSE:
805c87c5fbaSopenharmony_ci  case BIO_CTRL_DUP:
806c87c5fbaSopenharmony_ci  case BIO_CTRL_FLUSH:
807c87c5fbaSopenharmony_ci    r = 1;
808c87c5fbaSopenharmony_ci    break;
809c87c5fbaSopenharmony_ci  default:
810c87c5fbaSopenharmony_ci  case BIO_CTRL_GET_CLOSE:
811c87c5fbaSopenharmony_ci    r = 0;
812c87c5fbaSopenharmony_ci    break;
813c87c5fbaSopenharmony_ci  }
814c87c5fbaSopenharmony_ci  return r;
815c87c5fbaSopenharmony_ci}
816c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
817c87c5fbaSopenharmony_ci
818c87c5fbaSopenharmony_cistatic void
819c87c5fbaSopenharmony_cicoap_set_user_prefs(SSL_CTX *ctx) {
820c87c5fbaSopenharmony_ci  SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
821c87c5fbaSopenharmony_ci
822c87c5fbaSopenharmony_ci#ifdef COAP_OPENSSL_SIGALGS
823c87c5fbaSopenharmony_ci  SSL_CTX_set1_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
824c87c5fbaSopenharmony_ci  SSL_CTX_set1_client_sigalgs_list(ctx, COAP_OPENSSL_SIGALGS);
825c87c5fbaSopenharmony_ci#endif
826c87c5fbaSopenharmony_ci
827c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L && defined(COAP_OPENSSL_GROUPS)
828c87c5fbaSopenharmony_ci  SSL_CTX_set1_groups_list(ctx, COAP_OPENSSL_GROUPS);
829c87c5fbaSopenharmony_ci#endif
830c87c5fbaSopenharmony_ci}
831c87c5fbaSopenharmony_ci
832c87c5fbaSopenharmony_civoid *
833c87c5fbaSopenharmony_cicoap_dtls_new_context(coap_context_t *coap_context) {
834c87c5fbaSopenharmony_ci  coap_openssl_context_t *context;
835c87c5fbaSopenharmony_ci  (void)coap_context;
836c87c5fbaSopenharmony_ci
837c87c5fbaSopenharmony_ci  context = (coap_openssl_context_t *)coap_malloc_type(COAP_STRING, sizeof(coap_openssl_context_t));
838c87c5fbaSopenharmony_ci  if (context) {
839c87c5fbaSopenharmony_ci    uint8_t cookie_secret[32];
840c87c5fbaSopenharmony_ci
841c87c5fbaSopenharmony_ci    memset(context, 0, sizeof(coap_openssl_context_t));
842c87c5fbaSopenharmony_ci
843c87c5fbaSopenharmony_ci    /* Set up DTLS context */
844c87c5fbaSopenharmony_ci    context->dtls.ctx = SSL_CTX_new(DTLS_method());
845c87c5fbaSopenharmony_ci    if (!context->dtls.ctx)
846c87c5fbaSopenharmony_ci      goto error;
847c87c5fbaSopenharmony_ci    SSL_CTX_set_min_proto_version(context->dtls.ctx, DTLS1_2_VERSION);
848c87c5fbaSopenharmony_ci    SSL_CTX_set_app_data(context->dtls.ctx, &context->dtls);
849c87c5fbaSopenharmony_ci    SSL_CTX_set_read_ahead(context->dtls.ctx, 1);
850c87c5fbaSopenharmony_ci    coap_set_user_prefs(context->dtls.ctx);
851c87c5fbaSopenharmony_ci    memset(cookie_secret, 0, sizeof(cookie_secret));
852c87c5fbaSopenharmony_ci    if (!RAND_bytes(cookie_secret, (int)sizeof(cookie_secret))) {
853c87c5fbaSopenharmony_ci      coap_dtls_log(COAP_LOG_WARN,
854c87c5fbaSopenharmony_ci                    "Insufficient entropy for random cookie generation");
855c87c5fbaSopenharmony_ci      coap_prng(cookie_secret, sizeof(cookie_secret));
856c87c5fbaSopenharmony_ci    }
857c87c5fbaSopenharmony_ci    context->dtls.cookie_hmac = HMAC_CTX_new();
858c87c5fbaSopenharmony_ci    if (!HMAC_Init_ex(context->dtls.cookie_hmac, cookie_secret, (int)sizeof(cookie_secret),
859c87c5fbaSopenharmony_ci                      EVP_sha256(), NULL))
860c87c5fbaSopenharmony_ci      goto error;
861c87c5fbaSopenharmony_ci    SSL_CTX_set_cookie_generate_cb(context->dtls.ctx, coap_dtls_generate_cookie);
862c87c5fbaSopenharmony_ci    SSL_CTX_set_cookie_verify_cb(context->dtls.ctx, coap_dtls_verify_cookie);
863c87c5fbaSopenharmony_ci    SSL_CTX_set_info_callback(context->dtls.ctx, coap_dtls_info_callback);
864c87c5fbaSopenharmony_ci    SSL_CTX_set_options(context->dtls.ctx, SSL_OP_NO_QUERY_MTU);
865c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x30000000L
866c87c5fbaSopenharmony_ci    SSL_CTX_set_options(context->dtls.ctx, SSL_OP_LEGACY_SERVER_CONNECT);
867c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x30000000L */
868c87c5fbaSopenharmony_ci    context->dtls.meth = BIO_meth_new(BIO_TYPE_DGRAM, "coapdgram");
869c87c5fbaSopenharmony_ci    if (!context->dtls.meth)
870c87c5fbaSopenharmony_ci      goto error;
871c87c5fbaSopenharmony_ci    context->dtls.bio_addr = BIO_ADDR_new();
872c87c5fbaSopenharmony_ci    if (!context->dtls.bio_addr)
873c87c5fbaSopenharmony_ci      goto error;
874c87c5fbaSopenharmony_ci    BIO_meth_set_write(context->dtls.meth, coap_dgram_write);
875c87c5fbaSopenharmony_ci    BIO_meth_set_read(context->dtls.meth, coap_dgram_read);
876c87c5fbaSopenharmony_ci    BIO_meth_set_puts(context->dtls.meth, coap_dgram_puts);
877c87c5fbaSopenharmony_ci    BIO_meth_set_ctrl(context->dtls.meth, coap_dgram_ctrl);
878c87c5fbaSopenharmony_ci    BIO_meth_set_create(context->dtls.meth, coap_dgram_create);
879c87c5fbaSopenharmony_ci    BIO_meth_set_destroy(context->dtls.meth, coap_dgram_destroy);
880c87c5fbaSopenharmony_ci
881c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
882c87c5fbaSopenharmony_ci    /* Set up TLS context */
883c87c5fbaSopenharmony_ci    context->tls.ctx = SSL_CTX_new(TLS_method());
884c87c5fbaSopenharmony_ci    if (!context->tls.ctx)
885c87c5fbaSopenharmony_ci      goto error;
886c87c5fbaSopenharmony_ci    SSL_CTX_set_app_data(context->tls.ctx, &context->tls);
887c87c5fbaSopenharmony_ci    SSL_CTX_set_min_proto_version(context->tls.ctx, TLS1_VERSION);
888c87c5fbaSopenharmony_ci    coap_set_user_prefs(context->tls.ctx);
889c87c5fbaSopenharmony_ci    SSL_CTX_set_info_callback(context->tls.ctx, coap_dtls_info_callback);
890c87c5fbaSopenharmony_ci    context->tls.meth = BIO_meth_new(BIO_TYPE_SOCKET, "coapsock");
891c87c5fbaSopenharmony_ci    if (!context->tls.meth)
892c87c5fbaSopenharmony_ci      goto error;
893c87c5fbaSopenharmony_ci    BIO_meth_set_write(context->tls.meth, coap_sock_write);
894c87c5fbaSopenharmony_ci    BIO_meth_set_read(context->tls.meth, coap_sock_read);
895c87c5fbaSopenharmony_ci    BIO_meth_set_puts(context->tls.meth, coap_sock_puts);
896c87c5fbaSopenharmony_ci    BIO_meth_set_ctrl(context->tls.meth, coap_sock_ctrl);
897c87c5fbaSopenharmony_ci    BIO_meth_set_create(context->tls.meth, coap_sock_create);
898c87c5fbaSopenharmony_ci    BIO_meth_set_destroy(context->tls.meth, coap_sock_destroy);
899c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
900c87c5fbaSopenharmony_ci  }
901c87c5fbaSopenharmony_ci
902c87c5fbaSopenharmony_ci  return context;
903c87c5fbaSopenharmony_ci
904c87c5fbaSopenharmony_cierror:
905c87c5fbaSopenharmony_ci  coap_dtls_free_context(context);
906c87c5fbaSopenharmony_ci  return NULL;
907c87c5fbaSopenharmony_ci}
908c87c5fbaSopenharmony_ci
909c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
910c87c5fbaSopenharmony_ciint
911c87c5fbaSopenharmony_cicoap_dtls_context_set_spsk(coap_context_t *c_context,
912c87c5fbaSopenharmony_ci                           coap_dtls_spsk_t *setup_data
913c87c5fbaSopenharmony_ci                          ) {
914c87c5fbaSopenharmony_ci  coap_openssl_context_t *o_context =
915c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)c_context->dtls_context);
916c87c5fbaSopenharmony_ci  BIO *bio;
917c87c5fbaSopenharmony_ci
918c87c5fbaSopenharmony_ci  if (!setup_data || !o_context)
919c87c5fbaSopenharmony_ci    return 0;
920c87c5fbaSopenharmony_ci
921c87c5fbaSopenharmony_ci  SSL_CTX_set_psk_server_callback(o_context->dtls.ctx,
922c87c5fbaSopenharmony_ci                                  coap_dtls_psk_server_callback);
923c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
924c87c5fbaSopenharmony_ci  SSL_CTX_set_psk_server_callback(o_context->tls.ctx,
925c87c5fbaSopenharmony_ci                                  coap_dtls_psk_server_callback);
926c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
927c87c5fbaSopenharmony_ci  if (setup_data->psk_info.hint.s) {
928c87c5fbaSopenharmony_ci    char hint[COAP_DTLS_HINT_LENGTH];
929c87c5fbaSopenharmony_ci    snprintf(hint, sizeof(hint), "%.*s", (int)setup_data->psk_info.hint.length,
930c87c5fbaSopenharmony_ci             setup_data->psk_info.hint.s);
931c87c5fbaSopenharmony_ci    SSL_CTX_use_psk_identity_hint(o_context->dtls.ctx, hint);
932c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
933c87c5fbaSopenharmony_ci    SSL_CTX_use_psk_identity_hint(o_context->tls.ctx, hint);
934c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
935c87c5fbaSopenharmony_ci  }
936c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
937c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
938c87c5fbaSopenharmony_ci    SSL_CTX_set_tlsext_servername_arg(o_context->dtls.ctx,
939c87c5fbaSopenharmony_ci                                      &c_context->spsk_setup_data);
940c87c5fbaSopenharmony_ci    SSL_CTX_set_tlsext_servername_callback(o_context->dtls.ctx,
941c87c5fbaSopenharmony_ci                                           psk_tls_server_name_call_back);
942c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
943c87c5fbaSopenharmony_ci    SSL_CTX_set_tlsext_servername_arg(o_context->tls.ctx,
944c87c5fbaSopenharmony_ci                                      &c_context->spsk_setup_data);
945c87c5fbaSopenharmony_ci    SSL_CTX_set_tlsext_servername_callback(o_context->tls.ctx,
946c87c5fbaSopenharmony_ci                                           psk_tls_server_name_call_back);
947c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
948c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
949c87c5fbaSopenharmony_ci    SSL_CTX_set_client_hello_cb(o_context->dtls.ctx,
950c87c5fbaSopenharmony_ci                                psk_tls_client_hello_call_back,
951c87c5fbaSopenharmony_ci                                NULL);
952c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
953c87c5fbaSopenharmony_ci    SSL_CTX_set_client_hello_cb(o_context->tls.ctx,
954c87c5fbaSopenharmony_ci                                psk_tls_client_hello_call_back,
955c87c5fbaSopenharmony_ci                                NULL);
956c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
957c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
958c87c5fbaSopenharmony_ci  }
959c87c5fbaSopenharmony_ci
960c87c5fbaSopenharmony_ci  if (!o_context->dtls.ssl) {
961c87c5fbaSopenharmony_ci    /* This is set up to handle new incoming sessions to a server */
962c87c5fbaSopenharmony_ci    o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
963c87c5fbaSopenharmony_ci    if (!o_context->dtls.ssl)
964c87c5fbaSopenharmony_ci      return 0;
965c87c5fbaSopenharmony_ci    bio = BIO_new(o_context->dtls.meth);
966c87c5fbaSopenharmony_ci    if (!bio) {
967c87c5fbaSopenharmony_ci      SSL_free(o_context->dtls.ssl);
968c87c5fbaSopenharmony_ci      o_context->dtls.ssl = NULL;
969c87c5fbaSopenharmony_ci      return 0;
970c87c5fbaSopenharmony_ci    }
971c87c5fbaSopenharmony_ci    SSL_set_bio(o_context->dtls.ssl, bio, bio);
972c87c5fbaSopenharmony_ci    SSL_set_app_data(o_context->dtls.ssl, NULL);
973c87c5fbaSopenharmony_ci    SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
974c87c5fbaSopenharmony_ci    SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
975c87c5fbaSopenharmony_ci  }
976c87c5fbaSopenharmony_ci  o_context->psk_pki_enabled |= IS_PSK;
977c87c5fbaSopenharmony_ci  return 1;
978c87c5fbaSopenharmony_ci}
979c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
980c87c5fbaSopenharmony_ci
981c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
982c87c5fbaSopenharmony_ciint
983c87c5fbaSopenharmony_cicoap_dtls_context_set_cpsk(coap_context_t *c_context,
984c87c5fbaSopenharmony_ci                           coap_dtls_cpsk_t *setup_data
985c87c5fbaSopenharmony_ci                          ) {
986c87c5fbaSopenharmony_ci  coap_openssl_context_t *o_context =
987c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)c_context->dtls_context);
988c87c5fbaSopenharmony_ci  BIO *bio;
989c87c5fbaSopenharmony_ci
990c87c5fbaSopenharmony_ci  if (!setup_data || !o_context)
991c87c5fbaSopenharmony_ci    return 0;
992c87c5fbaSopenharmony_ci
993c87c5fbaSopenharmony_ci  if (!o_context->dtls.ssl) {
994c87c5fbaSopenharmony_ci    /* This is set up to handle new incoming sessions to a server */
995c87c5fbaSopenharmony_ci    o_context->dtls.ssl = SSL_new(o_context->dtls.ctx);
996c87c5fbaSopenharmony_ci    if (!o_context->dtls.ssl)
997c87c5fbaSopenharmony_ci      return 0;
998c87c5fbaSopenharmony_ci    bio = BIO_new(o_context->dtls.meth);
999c87c5fbaSopenharmony_ci    if (!bio) {
1000c87c5fbaSopenharmony_ci      SSL_free(o_context->dtls.ssl);
1001c87c5fbaSopenharmony_ci      o_context->dtls.ssl = NULL;
1002c87c5fbaSopenharmony_ci      return 0;
1003c87c5fbaSopenharmony_ci    }
1004c87c5fbaSopenharmony_ci    SSL_set_bio(o_context->dtls.ssl, bio, bio);
1005c87c5fbaSopenharmony_ci    SSL_set_app_data(o_context->dtls.ssl, NULL);
1006c87c5fbaSopenharmony_ci    SSL_set_options(o_context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
1007c87c5fbaSopenharmony_ci    SSL_set_mtu(o_context->dtls.ssl, COAP_DEFAULT_MTU);
1008c87c5fbaSopenharmony_ci  }
1009c87c5fbaSopenharmony_ci  o_context->psk_pki_enabled |= IS_PSK;
1010c87c5fbaSopenharmony_ci  return 1;
1011c87c5fbaSopenharmony_ci}
1012c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
1013c87c5fbaSopenharmony_ci
1014c87c5fbaSopenharmony_cistatic int
1015c87c5fbaSopenharmony_cimap_key_type(int asn1_private_key_type
1016c87c5fbaSopenharmony_ci            ) {
1017c87c5fbaSopenharmony_ci  switch (asn1_private_key_type) {
1018c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_NONE:
1019c87c5fbaSopenharmony_ci    return EVP_PKEY_NONE;
1020c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_RSA:
1021c87c5fbaSopenharmony_ci    return EVP_PKEY_RSA;
1022c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_RSA2:
1023c87c5fbaSopenharmony_ci    return EVP_PKEY_RSA2;
1024c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DSA:
1025c87c5fbaSopenharmony_ci    return EVP_PKEY_DSA;
1026c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DSA1:
1027c87c5fbaSopenharmony_ci    return EVP_PKEY_DSA1;
1028c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DSA2:
1029c87c5fbaSopenharmony_ci    return EVP_PKEY_DSA2;
1030c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DSA3:
1031c87c5fbaSopenharmony_ci    return EVP_PKEY_DSA3;
1032c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DSA4:
1033c87c5fbaSopenharmony_ci    return EVP_PKEY_DSA4;
1034c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DH:
1035c87c5fbaSopenharmony_ci    return EVP_PKEY_DH;
1036c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_DHX:
1037c87c5fbaSopenharmony_ci    return EVP_PKEY_DHX;
1038c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_EC:
1039c87c5fbaSopenharmony_ci    return EVP_PKEY_EC;
1040c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_HMAC:
1041c87c5fbaSopenharmony_ci    return EVP_PKEY_HMAC;
1042c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_CMAC:
1043c87c5fbaSopenharmony_ci    return EVP_PKEY_CMAC;
1044c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_TLS1_PRF:
1045c87c5fbaSopenharmony_ci    return EVP_PKEY_TLS1_PRF;
1046c87c5fbaSopenharmony_ci  case COAP_ASN1_PKEY_HKDF:
1047c87c5fbaSopenharmony_ci    return EVP_PKEY_HKDF;
1048c87c5fbaSopenharmony_ci  default:
1049c87c5fbaSopenharmony_ci    coap_log_warn("*** setup_pki: DTLS: Unknown Private Key type %d for ASN1\n",
1050c87c5fbaSopenharmony_ci                  asn1_private_key_type);
1051c87c5fbaSopenharmony_ci    break;
1052c87c5fbaSopenharmony_ci  }
1053c87c5fbaSopenharmony_ci  return 0;
1054c87c5fbaSopenharmony_ci}
1055c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
1056c87c5fbaSopenharmony_cistatic uint8_t coap_alpn[] = { 4, 'c', 'o', 'a', 'p' };
1057c87c5fbaSopenharmony_ci
1058c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
1059c87c5fbaSopenharmony_cistatic int
1060c87c5fbaSopenharmony_ciserver_alpn_callback(SSL *ssl COAP_UNUSED,
1061c87c5fbaSopenharmony_ci                     const unsigned char **out,
1062c87c5fbaSopenharmony_ci                     unsigned char *outlen,
1063c87c5fbaSopenharmony_ci                     const unsigned char *in,
1064c87c5fbaSopenharmony_ci                     unsigned int inlen,
1065c87c5fbaSopenharmony_ci                     void *arg COAP_UNUSED
1066c87c5fbaSopenharmony_ci                    ) {
1067c87c5fbaSopenharmony_ci  unsigned char *tout = NULL;
1068c87c5fbaSopenharmony_ci  int ret;
1069c87c5fbaSopenharmony_ci  if (inlen == 0)
1070c87c5fbaSopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
1071c87c5fbaSopenharmony_ci  ret = SSL_select_next_proto(&tout,
1072c87c5fbaSopenharmony_ci                              outlen,
1073c87c5fbaSopenharmony_ci                              coap_alpn,
1074c87c5fbaSopenharmony_ci                              sizeof(coap_alpn),
1075c87c5fbaSopenharmony_ci                              in,
1076c87c5fbaSopenharmony_ci                              inlen);
1077c87c5fbaSopenharmony_ci  *out = tout;
1078c87c5fbaSopenharmony_ci  return (ret != OPENSSL_NPN_NEGOTIATED) ? SSL_TLSEXT_ERR_NOACK : SSL_TLSEXT_ERR_OK;
1079c87c5fbaSopenharmony_ci}
1080c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
1081c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
1082c87c5fbaSopenharmony_ci
1083c87c5fbaSopenharmony_cistatic void
1084c87c5fbaSopenharmony_ciadd_ca_to_cert_store(X509_STORE *st, X509 *x509) {
1085c87c5fbaSopenharmony_ci  long e;
1086c87c5fbaSopenharmony_ci
1087c87c5fbaSopenharmony_ci  /* Flush out existing errors */
1088c87c5fbaSopenharmony_ci  while ((e = ERR_get_error()) != 0) {
1089c87c5fbaSopenharmony_ci  }
1090c87c5fbaSopenharmony_ci
1091c87c5fbaSopenharmony_ci  if (!X509_STORE_add_cert(st, x509)) {
1092c87c5fbaSopenharmony_ci    while ((e = ERR_get_error()) != 0) {
1093c87c5fbaSopenharmony_ci      int r = ERR_GET_REASON(e);
1094c87c5fbaSopenharmony_ci      if (r != X509_R_CERT_ALREADY_IN_HASH_TABLE) {
1095c87c5fbaSopenharmony_ci        /* Not already added */
1096c87c5fbaSopenharmony_ci        coap_log_warn("***setup_pki: (D)TLS: %s%s\n",
1097c87c5fbaSopenharmony_ci                      ERR_reason_error_string(e),
1098c87c5fbaSopenharmony_ci                      ssl_function_definition(e));
1099c87c5fbaSopenharmony_ci      }
1100c87c5fbaSopenharmony_ci    }
1101c87c5fbaSopenharmony_ci  }
1102c87c5fbaSopenharmony_ci}
1103c87c5fbaSopenharmony_ci
1104c87c5fbaSopenharmony_cistatic X509 *
1105c87c5fbaSopenharmony_cimissing_ENGINE_load_cert(const char *cert_id) {
1106c87c5fbaSopenharmony_ci  struct {
1107c87c5fbaSopenharmony_ci    const char *cert_id;
1108c87c5fbaSopenharmony_ci    X509 *cert;
1109c87c5fbaSopenharmony_ci  } params;
1110c87c5fbaSopenharmony_ci
1111c87c5fbaSopenharmony_ci  params.cert_id = cert_id;
1112c87c5fbaSopenharmony_ci  params.cert = NULL;
1113c87c5fbaSopenharmony_ci
1114c87c5fbaSopenharmony_ci  /* There is no ENGINE_load_cert() */
1115c87c5fbaSopenharmony_ci  if (!ENGINE_ctrl_cmd(ssl_engine, "LOAD_CERT_CTRL", 0, &params, NULL, 1)) {
1116c87c5fbaSopenharmony_ci    params.cert = NULL;
1117c87c5fbaSopenharmony_ci  }
1118c87c5fbaSopenharmony_ci  return params.cert;
1119c87c5fbaSopenharmony_ci}
1120c87c5fbaSopenharmony_ci
1121c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L && COAP_SERVER_SUPPORT
1122c87c5fbaSopenharmony_cistatic int
1123c87c5fbaSopenharmony_cisetup_pki_server(SSL_CTX *ctx,
1124c87c5fbaSopenharmony_ci                 const coap_dtls_pki_t *setup_data
1125c87c5fbaSopenharmony_ci                ) {
1126c87c5fbaSopenharmony_ci  switch (setup_data->pki_key.key_type) {
1127c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM:
1128c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem.public_cert &&
1129c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.public_cert[0]) {
1130c87c5fbaSopenharmony_ci      if (!(SSL_CTX_use_certificate_file(ctx,
1131c87c5fbaSopenharmony_ci                                         setup_data->pki_key.key.pem.public_cert,
1132c87c5fbaSopenharmony_ci                                         SSL_FILETYPE_PEM))) {
1133c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1134c87c5fbaSopenharmony_ci                      "Server Certificate\n",
1135c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pem.public_cert);
1136c87c5fbaSopenharmony_ci        return 0;
1137c87c5fbaSopenharmony_ci      }
1138c87c5fbaSopenharmony_ci    } else {
1139c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1140c87c5fbaSopenharmony_ci      return 0;
1141c87c5fbaSopenharmony_ci    }
1142c87c5fbaSopenharmony_ci
1143c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem.private_key &&
1144c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.private_key[0]) {
1145c87c5fbaSopenharmony_ci      if (!(SSL_CTX_use_PrivateKey_file(ctx,
1146c87c5fbaSopenharmony_ci                                        setup_data->pki_key.key.pem.private_key,
1147c87c5fbaSopenharmony_ci                                        SSL_FILETYPE_PEM))) {
1148c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1149c87c5fbaSopenharmony_ci                      "Server Private Key\n",
1150c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pem.private_key);
1151c87c5fbaSopenharmony_ci        return 0;
1152c87c5fbaSopenharmony_ci      }
1153c87c5fbaSopenharmony_ci    } else {
1154c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1155c87c5fbaSopenharmony_ci      return 0;
1156c87c5fbaSopenharmony_ci    }
1157c87c5fbaSopenharmony_ci
1158c87c5fbaSopenharmony_ci    if (setup_data->check_common_ca && setup_data->pki_key.key.pem.ca_file &&
1159c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.ca_file[0]) {
1160c87c5fbaSopenharmony_ci      STACK_OF(X509_NAME) *cert_names;
1161c87c5fbaSopenharmony_ci      X509_STORE *st;
1162c87c5fbaSopenharmony_ci      BIO *in;
1163c87c5fbaSopenharmony_ci      X509 *x = NULL;
1164c87c5fbaSopenharmony_ci      char *rw_var = NULL;
1165c87c5fbaSopenharmony_ci      cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
1166c87c5fbaSopenharmony_ci      if (cert_names != NULL)
1167c87c5fbaSopenharmony_ci        SSL_CTX_set_client_CA_list(ctx, cert_names);
1168c87c5fbaSopenharmony_ci      else {
1169c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1170c87c5fbaSopenharmony_ci                      "client CA File\n",
1171c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pem.ca_file);
1172c87c5fbaSopenharmony_ci        return 0;
1173c87c5fbaSopenharmony_ci      }
1174c87c5fbaSopenharmony_ci
1175c87c5fbaSopenharmony_ci      /* Add CA to the trusted root CA store */
1176c87c5fbaSopenharmony_ci      st = SSL_CTX_get_cert_store(ctx);
1177c87c5fbaSopenharmony_ci      in = BIO_new(BIO_s_file());
1178c87c5fbaSopenharmony_ci      /* Need to do this to not get a compiler warning about const parameters */
1179c87c5fbaSopenharmony_ci      memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof(rw_var));
1180c87c5fbaSopenharmony_ci      if (!BIO_read_filename(in, rw_var)) {
1181c87c5fbaSopenharmony_ci        BIO_free(in);
1182c87c5fbaSopenharmony_ci        X509_free(x);
1183c87c5fbaSopenharmony_ci        break;
1184c87c5fbaSopenharmony_ci      }
1185c87c5fbaSopenharmony_ci
1186c87c5fbaSopenharmony_ci      for (;;) {
1187c87c5fbaSopenharmony_ci        if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1188c87c5fbaSopenharmony_ci          break;
1189c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x);
1190c87c5fbaSopenharmony_ci        X509_free(x);
1191c87c5fbaSopenharmony_ci      }
1192c87c5fbaSopenharmony_ci      BIO_free(in);
1193c87c5fbaSopenharmony_ci    }
1194c87c5fbaSopenharmony_ci    break;
1195c87c5fbaSopenharmony_ci
1196c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM_BUF:
1197c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.public_cert &&
1198c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.public_cert_len) {
1199c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.public_cert,
1200c87c5fbaSopenharmony_ci                                setup_data->pki_key.key.pem_buf.public_cert_len);
1201c87c5fbaSopenharmony_ci      X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1202c87c5fbaSopenharmony_ci
1203c87c5fbaSopenharmony_ci      if (!cert || !SSL_CTX_use_certificate(ctx, cert)) {
1204c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: Unable to configure "
1205c87c5fbaSopenharmony_ci                      "Server PEM Certificate\n");
1206c87c5fbaSopenharmony_ci        if (bp)
1207c87c5fbaSopenharmony_ci          BIO_free(bp);
1208c87c5fbaSopenharmony_ci        if (cert)
1209c87c5fbaSopenharmony_ci          X509_free(cert);
1210c87c5fbaSopenharmony_ci        return 0;
1211c87c5fbaSopenharmony_ci      }
1212c87c5fbaSopenharmony_ci      if (bp)
1213c87c5fbaSopenharmony_ci        BIO_free(bp);
1214c87c5fbaSopenharmony_ci      if (cert)
1215c87c5fbaSopenharmony_ci        X509_free(cert);
1216c87c5fbaSopenharmony_ci    } else {
1217c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1218c87c5fbaSopenharmony_ci      return 0;
1219c87c5fbaSopenharmony_ci    }
1220c87c5fbaSopenharmony_ci
1221c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.private_key &&
1222c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.private_key_len) {
1223c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.private_key,
1224c87c5fbaSopenharmony_ci                                setup_data->pki_key.key.pem_buf.private_key_len);
1225c87c5fbaSopenharmony_ci      EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1226c87c5fbaSopenharmony_ci
1227c87c5fbaSopenharmony_ci      if (!pkey || !SSL_CTX_use_PrivateKey(ctx, pkey)) {
1228c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: Unable to configure "
1229c87c5fbaSopenharmony_ci                      "Server PEM Private Key\n");
1230c87c5fbaSopenharmony_ci        if (bp)
1231c87c5fbaSopenharmony_ci          BIO_free(bp);
1232c87c5fbaSopenharmony_ci        if (pkey)
1233c87c5fbaSopenharmony_ci          EVP_PKEY_free(pkey);
1234c87c5fbaSopenharmony_ci        return 0;
1235c87c5fbaSopenharmony_ci      }
1236c87c5fbaSopenharmony_ci      if (bp)
1237c87c5fbaSopenharmony_ci        BIO_free(bp);
1238c87c5fbaSopenharmony_ci      if (pkey)
1239c87c5fbaSopenharmony_ci        EVP_PKEY_free(pkey);
1240c87c5fbaSopenharmony_ci    } else {
1241c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1242c87c5fbaSopenharmony_ci      return 0;
1243c87c5fbaSopenharmony_ci    }
1244c87c5fbaSopenharmony_ci
1245c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.ca_cert &&
1246c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.ca_cert_len) {
1247c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.ca_cert,
1248c87c5fbaSopenharmony_ci                                setup_data->pki_key.key.pem_buf.ca_cert_len);
1249c87c5fbaSopenharmony_ci      X509_STORE *st;
1250c87c5fbaSopenharmony_ci      X509 *x;
1251c87c5fbaSopenharmony_ci
1252c87c5fbaSopenharmony_ci      st = SSL_CTX_get_cert_store(ctx);
1253c87c5fbaSopenharmony_ci      if (bp) {
1254c87c5fbaSopenharmony_ci        for (;;) {
1255c87c5fbaSopenharmony_ci          if ((x = PEM_read_bio_X509(bp, NULL, NULL, NULL)) == NULL)
1256c87c5fbaSopenharmony_ci            break;
1257c87c5fbaSopenharmony_ci          add_ca_to_cert_store(st, x);
1258c87c5fbaSopenharmony_ci          SSL_CTX_add_client_CA(ctx, x);
1259c87c5fbaSopenharmony_ci          X509_free(x);
1260c87c5fbaSopenharmony_ci        }
1261c87c5fbaSopenharmony_ci        BIO_free(bp);
1262c87c5fbaSopenharmony_ci      }
1263c87c5fbaSopenharmony_ci    }
1264c87c5fbaSopenharmony_ci    break;
1265c87c5fbaSopenharmony_ci
1266c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_ASN1:
1267c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.public_cert &&
1268c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.public_cert_len > 0) {
1269c87c5fbaSopenharmony_ci      if (!(SSL_CTX_use_certificate_ASN1(ctx,
1270c87c5fbaSopenharmony_ci                                         setup_data->pki_key.key.asn1.public_cert_len,
1271c87c5fbaSopenharmony_ci                                         setup_data->pki_key.key.asn1.public_cert))) {
1272c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1273c87c5fbaSopenharmony_ci                      "Server Certificate\n",
1274c87c5fbaSopenharmony_ci                      "ASN1");
1275c87c5fbaSopenharmony_ci        return 0;
1276c87c5fbaSopenharmony_ci      }
1277c87c5fbaSopenharmony_ci    } else {
1278c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1279c87c5fbaSopenharmony_ci      return 0;
1280c87c5fbaSopenharmony_ci    }
1281c87c5fbaSopenharmony_ci
1282c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.private_key &&
1283c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.private_key_len > 0) {
1284c87c5fbaSopenharmony_ci      int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
1285c87c5fbaSopenharmony_ci      if (!(SSL_CTX_use_PrivateKey_ASN1(pkey_type, ctx,
1286c87c5fbaSopenharmony_ci                                        setup_data->pki_key.key.asn1.private_key,
1287c87c5fbaSopenharmony_ci                                        setup_data->pki_key.key.asn1.private_key_len))) {
1288c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1289c87c5fbaSopenharmony_ci                      "Server Private Key\n",
1290c87c5fbaSopenharmony_ci                      "ASN1");
1291c87c5fbaSopenharmony_ci        return 0;
1292c87c5fbaSopenharmony_ci      }
1293c87c5fbaSopenharmony_ci    } else {
1294c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1295c87c5fbaSopenharmony_ci      return 0;
1296c87c5fbaSopenharmony_ci    }
1297c87c5fbaSopenharmony_ci
1298c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.ca_cert &&
1299c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.ca_cert_len > 0) {
1300c87c5fbaSopenharmony_ci      /* Need to use a temp variable as it gets incremented*/
1301c87c5fbaSopenharmony_ci      const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
1302c87c5fbaSopenharmony_ci      X509 *x509 = d2i_X509(NULL, &p, setup_data->pki_key.key.asn1.ca_cert_len);
1303c87c5fbaSopenharmony_ci      X509_STORE *st;
1304c87c5fbaSopenharmony_ci      if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1305c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1306c87c5fbaSopenharmony_ci                      "client CA File\n",
1307c87c5fbaSopenharmony_ci                      "ASN1");
1308c87c5fbaSopenharmony_ci        if (x509)
1309c87c5fbaSopenharmony_ci          X509_free(x509);
1310c87c5fbaSopenharmony_ci        return 0;
1311c87c5fbaSopenharmony_ci      }
1312c87c5fbaSopenharmony_ci      st = SSL_CTX_get_cert_store(ctx);
1313c87c5fbaSopenharmony_ci      add_ca_to_cert_store(st, x509);
1314c87c5fbaSopenharmony_ci      X509_free(x509);
1315c87c5fbaSopenharmony_ci    }
1316c87c5fbaSopenharmony_ci    break;
1317c87c5fbaSopenharmony_ci
1318c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PKCS11:
1319c87c5fbaSopenharmony_ci    if (!ssl_engine) {
1320c87c5fbaSopenharmony_ci      ssl_engine = ENGINE_by_id("pkcs11");
1321c87c5fbaSopenharmony_ci      if (!ssl_engine) {
1322c87c5fbaSopenharmony_ci        coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support\nn");
1323c87c5fbaSopenharmony_ci        return 0;
1324c87c5fbaSopenharmony_ci      }
1325c87c5fbaSopenharmony_ci      if (!ENGINE_init(ssl_engine)) {
1326c87c5fbaSopenharmony_ci        /* the engine couldn't initialise, release 'ssl_engine' */
1327c87c5fbaSopenharmony_ci        ENGINE_free(ssl_engine);
1328c87c5fbaSopenharmony_ci        ssl_engine = NULL;
1329c87c5fbaSopenharmony_ci        coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1330c87c5fbaSopenharmony_ci        return 0;
1331c87c5fbaSopenharmony_ci      }
1332c87c5fbaSopenharmony_ci    }
1333c87c5fbaSopenharmony_ci
1334c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.user_pin) {
1335c87c5fbaSopenharmony_ci      /* If not set, pin may be held in pkcs11: URI */
1336c87c5fbaSopenharmony_ci      if (ENGINE_ctrl_cmd_string(ssl_engine, "PIN",
1337c87c5fbaSopenharmony_ci                                 setup_data->pki_key.key.pkcs11.user_pin, 0) == 0) {
1338c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1339c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pkcs11.user_pin);
1340c87c5fbaSopenharmony_ci        return 0;
1341c87c5fbaSopenharmony_ci      }
1342c87c5fbaSopenharmony_ci    }
1343c87c5fbaSopenharmony_ci
1344c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.private_key &&
1345c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.private_key[0]) {
1346c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.private_key,
1347c87c5fbaSopenharmony_ci                      "pkcs11:", 7) == 0) {
1348c87c5fbaSopenharmony_ci        EVP_PKEY *pkey = ENGINE_load_private_key(ssl_engine,
1349c87c5fbaSopenharmony_ci                                                 setup_data->pki_key.key.pkcs11.private_key,
1350c87c5fbaSopenharmony_ci                                                 NULL, NULL);
1351c87c5fbaSopenharmony_ci
1352c87c5fbaSopenharmony_ci        if (!pkey) {
1353c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1354c87c5fbaSopenharmony_ci                        "Server Private Key\n",
1355c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key);
1356c87c5fbaSopenharmony_ci          return 0;
1357c87c5fbaSopenharmony_ci        }
1358c87c5fbaSopenharmony_ci        if (!SSL_CTX_use_PrivateKey(ctx, pkey)) {
1359c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1360c87c5fbaSopenharmony_ci                        "Server Private Key\n",
1361c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key);
1362c87c5fbaSopenharmony_ci          EVP_PKEY_free(pkey);
1363c87c5fbaSopenharmony_ci          return 0;
1364c87c5fbaSopenharmony_ci        }
1365c87c5fbaSopenharmony_ci        EVP_PKEY_free(pkey);
1366c87c5fbaSopenharmony_ci      } else {
1367c87c5fbaSopenharmony_ci        if (!(SSL_CTX_use_PrivateKey_file(ctx,
1368c87c5fbaSopenharmony_ci                                          setup_data->pki_key.key.pkcs11.private_key,
1369c87c5fbaSopenharmony_ci                                          SSL_FILETYPE_ASN1))) {
1370c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1371c87c5fbaSopenharmony_ci                        "Server Private Key\n",
1372c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key);
1373c87c5fbaSopenharmony_ci          return 0;
1374c87c5fbaSopenharmony_ci        }
1375c87c5fbaSopenharmony_ci      }
1376c87c5fbaSopenharmony_ci    } else {
1377c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1378c87c5fbaSopenharmony_ci      return 0;
1379c87c5fbaSopenharmony_ci    }
1380c87c5fbaSopenharmony_ci
1381c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.public_cert &&
1382c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.public_cert[0]) {
1383c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.public_cert,
1384c87c5fbaSopenharmony_ci                      "pkcs11:", 7) == 0) {
1385c87c5fbaSopenharmony_ci        X509 *x509;
1386c87c5fbaSopenharmony_ci
1387c87c5fbaSopenharmony_ci        x509 = missing_ENGINE_load_cert(
1388c87c5fbaSopenharmony_ci                   setup_data->pki_key.key.pkcs11.public_cert);
1389c87c5fbaSopenharmony_ci        if (!x509) {
1390c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1391c87c5fbaSopenharmony_ci                        "Server Certificate\n",
1392c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert);
1393c87c5fbaSopenharmony_ci          return 0;
1394c87c5fbaSopenharmony_ci        }
1395c87c5fbaSopenharmony_ci        if (!SSL_CTX_use_certificate(ctx, x509)) {
1396c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1397c87c5fbaSopenharmony_ci                        "Server Certificate\n",
1398c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert);
1399c87c5fbaSopenharmony_ci          X509_free(x509);
1400c87c5fbaSopenharmony_ci          return 0;
1401c87c5fbaSopenharmony_ci        }
1402c87c5fbaSopenharmony_ci        X509_free(x509);
1403c87c5fbaSopenharmony_ci      } else {
1404c87c5fbaSopenharmony_ci        if (!(SSL_CTX_use_certificate_file(ctx,
1405c87c5fbaSopenharmony_ci                                           setup_data->pki_key.key.pkcs11.public_cert,
1406c87c5fbaSopenharmony_ci                                           SSL_FILETYPE_ASN1))) {
1407c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1408c87c5fbaSopenharmony_ci                        "Server Certificate\n",
1409c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert);
1410c87c5fbaSopenharmony_ci          return 0;
1411c87c5fbaSopenharmony_ci        }
1412c87c5fbaSopenharmony_ci      }
1413c87c5fbaSopenharmony_ci    } else {
1414c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1415c87c5fbaSopenharmony_ci      return 0;
1416c87c5fbaSopenharmony_ci    }
1417c87c5fbaSopenharmony_ci
1418c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.ca &&
1419c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.ca[0]) {
1420c87c5fbaSopenharmony_ci      X509_STORE *st;
1421c87c5fbaSopenharmony_ci
1422c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.ca, "pkcs11:", 7) == 0) {
1423c87c5fbaSopenharmony_ci        X509 *x509;
1424c87c5fbaSopenharmony_ci
1425c87c5fbaSopenharmony_ci        x509 = missing_ENGINE_load_cert(
1426c87c5fbaSopenharmony_ci                   setup_data->pki_key.key.pkcs11.ca);
1427c87c5fbaSopenharmony_ci        if (!x509) {
1428c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1429c87c5fbaSopenharmony_ci                        "Server CA Certificate\n",
1430c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca);
1431c87c5fbaSopenharmony_ci          return 0;
1432c87c5fbaSopenharmony_ci        }
1433c87c5fbaSopenharmony_ci        if (!SSL_CTX_add_client_CA(ctx, x509)) {
1434c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1435c87c5fbaSopenharmony_ci                        "Server CA File\n",
1436c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca);
1437c87c5fbaSopenharmony_ci          X509_free(x509);
1438c87c5fbaSopenharmony_ci          return 0;
1439c87c5fbaSopenharmony_ci        }
1440c87c5fbaSopenharmony_ci        st = SSL_CTX_get_cert_store(ctx);
1441c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x509);
1442c87c5fbaSopenharmony_ci        X509_free(x509);
1443c87c5fbaSopenharmony_ci      } else {
1444c87c5fbaSopenharmony_ci        FILE *fp = fopen(setup_data->pki_key.key.pkcs11.ca, "r");
1445c87c5fbaSopenharmony_ci        X509 *x509 = fp ? d2i_X509_fp(fp, NULL) : NULL;
1446c87c5fbaSopenharmony_ci
1447c87c5fbaSopenharmony_ci        if (!x509 || !SSL_CTX_add_client_CA(ctx, x509)) {
1448c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1449c87c5fbaSopenharmony_ci                        "client CA File\n",
1450c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca);
1451c87c5fbaSopenharmony_ci          if (x509)
1452c87c5fbaSopenharmony_ci            X509_free(x509);
1453c87c5fbaSopenharmony_ci          return 0;
1454c87c5fbaSopenharmony_ci        }
1455c87c5fbaSopenharmony_ci        st = SSL_CTX_get_cert_store(ctx);
1456c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x509);
1457c87c5fbaSopenharmony_ci        X509_free(x509);
1458c87c5fbaSopenharmony_ci      }
1459c87c5fbaSopenharmony_ci    }
1460c87c5fbaSopenharmony_ci    break;
1461c87c5fbaSopenharmony_ci
1462c87c5fbaSopenharmony_ci  default:
1463c87c5fbaSopenharmony_ci    coap_log_err("*** setup_pki: (D)TLS: Unknown key type %d\n",
1464c87c5fbaSopenharmony_ci                 setup_data->pki_key.key_type);
1465c87c5fbaSopenharmony_ci    return 0;
1466c87c5fbaSopenharmony_ci  }
1467c87c5fbaSopenharmony_ci
1468c87c5fbaSopenharmony_ci  return 1;
1469c87c5fbaSopenharmony_ci}
1470c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
1471c87c5fbaSopenharmony_ci
1472c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT
1473c87c5fbaSopenharmony_cistatic int
1474c87c5fbaSopenharmony_cisetup_pki_ssl(SSL *ssl,
1475c87c5fbaSopenharmony_ci              coap_dtls_pki_t *setup_data, coap_dtls_role_t role
1476c87c5fbaSopenharmony_ci             ) {
1477c87c5fbaSopenharmony_ci  if (setup_data->is_rpk_not_cert) {
1478c87c5fbaSopenharmony_ci    coap_log_err("RPK Support not available in OpenSSL\n");
1479c87c5fbaSopenharmony_ci    return 0;
1480c87c5fbaSopenharmony_ci  }
1481c87c5fbaSopenharmony_ci  switch (setup_data->pki_key.key_type) {
1482c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM:
1483c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem.public_cert &&
1484c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.public_cert[0]) {
1485c87c5fbaSopenharmony_ci      if (!(SSL_use_certificate_file(ssl,
1486c87c5fbaSopenharmony_ci                                     setup_data->pki_key.key.pem.public_cert,
1487c87c5fbaSopenharmony_ci                                     SSL_FILETYPE_PEM))) {
1488c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1489c87c5fbaSopenharmony_ci                      "%s Certificate\n",
1490c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pem.public_cert,
1491c87c5fbaSopenharmony_ci                      role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1492c87c5fbaSopenharmony_ci        return 0;
1493c87c5fbaSopenharmony_ci      }
1494c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER ||
1495c87c5fbaSopenharmony_ci               (setup_data->pki_key.key.pem.private_key &&
1496c87c5fbaSopenharmony_ci                setup_data->pki_key.key.pem.private_key[0])) {
1497c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No %s Certificate defined\n",
1498c87c5fbaSopenharmony_ci                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1499c87c5fbaSopenharmony_ci      return 0;
1500c87c5fbaSopenharmony_ci    }
1501c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem.private_key &&
1502c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.private_key[0]) {
1503c87c5fbaSopenharmony_ci      if (!(SSL_use_PrivateKey_file(ssl,
1504c87c5fbaSopenharmony_ci                                    setup_data->pki_key.key.pem.private_key,
1505c87c5fbaSopenharmony_ci                                    SSL_FILETYPE_PEM))) {
1506c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1507c87c5fbaSopenharmony_ci                      "Client Private Key\n",
1508c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pem.private_key);
1509c87c5fbaSopenharmony_ci        return 0;
1510c87c5fbaSopenharmony_ci      }
1511c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER ||
1512c87c5fbaSopenharmony_ci               (setup_data->pki_key.key.pem.public_cert &&
1513c87c5fbaSopenharmony_ci                setup_data->pki_key.key.pem.public_cert[0])) {
1514c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No %s Private Key defined\n",
1515c87c5fbaSopenharmony_ci                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1516c87c5fbaSopenharmony_ci      return 0;
1517c87c5fbaSopenharmony_ci    }
1518c87c5fbaSopenharmony_ci    if (setup_data->check_common_ca && setup_data->pki_key.key.pem.ca_file &&
1519c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem.ca_file[0]) {
1520c87c5fbaSopenharmony_ci      X509_STORE *st;
1521c87c5fbaSopenharmony_ci      BIO *in;
1522c87c5fbaSopenharmony_ci      X509 *x = NULL;
1523c87c5fbaSopenharmony_ci      char *rw_var = NULL;
1524c87c5fbaSopenharmony_ci      SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1525c87c5fbaSopenharmony_ci
1526c87c5fbaSopenharmony_ci      if (role == COAP_DTLS_ROLE_SERVER) {
1527c87c5fbaSopenharmony_ci        STACK_OF(X509_NAME) *cert_names = SSL_load_client_CA_file(setup_data->pki_key.key.pem.ca_file);
1528c87c5fbaSopenharmony_ci
1529c87c5fbaSopenharmony_ci        if (cert_names != NULL)
1530c87c5fbaSopenharmony_ci          SSL_set_client_CA_list(ssl, cert_names);
1531c87c5fbaSopenharmony_ci        else {
1532c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1533c87c5fbaSopenharmony_ci                        "%s CA File\n",
1534c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pem.ca_file,
1535c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1536c87c5fbaSopenharmony_ci          return 0;
1537c87c5fbaSopenharmony_ci        }
1538c87c5fbaSopenharmony_ci      }
1539c87c5fbaSopenharmony_ci
1540c87c5fbaSopenharmony_ci      /* Add CA to the trusted root CA store */
1541c87c5fbaSopenharmony_ci      in = BIO_new(BIO_s_file());
1542c87c5fbaSopenharmony_ci      /* Need to do this to not get a compiler warning about const parameters */
1543c87c5fbaSopenharmony_ci      memcpy(&rw_var, &setup_data->pki_key.key.pem.ca_file, sizeof(rw_var));
1544c87c5fbaSopenharmony_ci      if (!BIO_read_filename(in, rw_var)) {
1545c87c5fbaSopenharmony_ci        BIO_free(in);
1546c87c5fbaSopenharmony_ci        break;
1547c87c5fbaSopenharmony_ci      }
1548c87c5fbaSopenharmony_ci      st = SSL_CTX_get_cert_store(ctx);
1549c87c5fbaSopenharmony_ci      for (;;) {
1550c87c5fbaSopenharmony_ci        if ((x = PEM_read_bio_X509(in, NULL, NULL, NULL)) == NULL)
1551c87c5fbaSopenharmony_ci          break;
1552c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x);
1553c87c5fbaSopenharmony_ci        X509_free(x);
1554c87c5fbaSopenharmony_ci      }
1555c87c5fbaSopenharmony_ci      BIO_free(in);
1556c87c5fbaSopenharmony_ci    }
1557c87c5fbaSopenharmony_ci    break;
1558c87c5fbaSopenharmony_ci
1559c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PEM_BUF:
1560c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.public_cert &&
1561c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.public_cert_len) {
1562c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.public_cert,
1563c87c5fbaSopenharmony_ci                                (int)setup_data->pki_key.key.pem_buf.public_cert_len);
1564c87c5fbaSopenharmony_ci      X509 *cert = bp ? PEM_read_bio_X509(bp, NULL, 0, NULL) : NULL;
1565c87c5fbaSopenharmony_ci
1566c87c5fbaSopenharmony_ci      if (!cert || !SSL_use_certificate(ssl, cert)) {
1567c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: Unable to configure "
1568c87c5fbaSopenharmony_ci                      "Server PEM Certificate\n");
1569c87c5fbaSopenharmony_ci        if (bp)
1570c87c5fbaSopenharmony_ci          BIO_free(bp);
1571c87c5fbaSopenharmony_ci        if (cert)
1572c87c5fbaSopenharmony_ci          X509_free(cert);
1573c87c5fbaSopenharmony_ci        return 0;
1574c87c5fbaSopenharmony_ci      }
1575c87c5fbaSopenharmony_ci      if (bp)
1576c87c5fbaSopenharmony_ci        BIO_free(bp);
1577c87c5fbaSopenharmony_ci      if (cert)
1578c87c5fbaSopenharmony_ci        X509_free(cert);
1579c87c5fbaSopenharmony_ci    } else {
1580c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1581c87c5fbaSopenharmony_ci      return 0;
1582c87c5fbaSopenharmony_ci    }
1583c87c5fbaSopenharmony_ci
1584c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.private_key &&
1585c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.private_key_len) {
1586c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.private_key,
1587c87c5fbaSopenharmony_ci                                (int)setup_data->pki_key.key.pem_buf.private_key_len);
1588c87c5fbaSopenharmony_ci      EVP_PKEY *pkey = bp ? PEM_read_bio_PrivateKey(bp, NULL, 0, NULL) : NULL;
1589c87c5fbaSopenharmony_ci
1590c87c5fbaSopenharmony_ci      if (!pkey || !SSL_use_PrivateKey(ssl, pkey)) {
1591c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: Unable to configure "
1592c87c5fbaSopenharmony_ci                      "Server PEM Private Key\n");
1593c87c5fbaSopenharmony_ci        if (bp)
1594c87c5fbaSopenharmony_ci          BIO_free(bp);
1595c87c5fbaSopenharmony_ci        if (pkey)
1596c87c5fbaSopenharmony_ci          EVP_PKEY_free(pkey);
1597c87c5fbaSopenharmony_ci        return 0;
1598c87c5fbaSopenharmony_ci      }
1599c87c5fbaSopenharmony_ci      if (bp)
1600c87c5fbaSopenharmony_ci        BIO_free(bp);
1601c87c5fbaSopenharmony_ci      if (pkey)
1602c87c5fbaSopenharmony_ci        EVP_PKEY_free(pkey);
1603c87c5fbaSopenharmony_ci    } else {
1604c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1605c87c5fbaSopenharmony_ci      return 0;
1606c87c5fbaSopenharmony_ci    }
1607c87c5fbaSopenharmony_ci
1608c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pem_buf.ca_cert &&
1609c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pem_buf.ca_cert_len) {
1610c87c5fbaSopenharmony_ci      BIO *bp = BIO_new_mem_buf(setup_data->pki_key.key.pem_buf.ca_cert,
1611c87c5fbaSopenharmony_ci                                (int)setup_data->pki_key.key.pem_buf.ca_cert_len);
1612c87c5fbaSopenharmony_ci      SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1613c87c5fbaSopenharmony_ci      X509 *x;
1614c87c5fbaSopenharmony_ci      X509_STORE *st = SSL_CTX_get_cert_store(ctx);
1615c87c5fbaSopenharmony_ci
1616c87c5fbaSopenharmony_ci      if (bp) {
1617c87c5fbaSopenharmony_ci        for (;;) {
1618c87c5fbaSopenharmony_ci          if ((x = PEM_read_bio_X509(bp, NULL, 0, NULL)) == NULL)
1619c87c5fbaSopenharmony_ci            break;
1620c87c5fbaSopenharmony_ci          add_ca_to_cert_store(st, x);
1621c87c5fbaSopenharmony_ci          SSL_add_client_CA(ssl, x);
1622c87c5fbaSopenharmony_ci          X509_free(x);
1623c87c5fbaSopenharmony_ci        }
1624c87c5fbaSopenharmony_ci        BIO_free(bp);
1625c87c5fbaSopenharmony_ci      }
1626c87c5fbaSopenharmony_ci    }
1627c87c5fbaSopenharmony_ci    break;
1628c87c5fbaSopenharmony_ci
1629c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_ASN1:
1630c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.public_cert &&
1631c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.public_cert_len > 0) {
1632c87c5fbaSopenharmony_ci      if (!(SSL_use_certificate_ASN1(ssl,
1633c87c5fbaSopenharmony_ci                                     setup_data->pki_key.key.asn1.public_cert,
1634c87c5fbaSopenharmony_ci                                     (int)setup_data->pki_key.key.asn1.public_cert_len))) {
1635c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1636c87c5fbaSopenharmony_ci                      "%s Certificate\n",
1637c87c5fbaSopenharmony_ci                      role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
1638c87c5fbaSopenharmony_ci                      "ASN1");
1639c87c5fbaSopenharmony_ci        return 0;
1640c87c5fbaSopenharmony_ci      }
1641c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER ||
1642c87c5fbaSopenharmony_ci               (setup_data->pki_key.key.asn1.private_key &&
1643c87c5fbaSopenharmony_ci                setup_data->pki_key.key.asn1.private_key[0])) {
1644c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No %s Certificate defined\n",
1645c87c5fbaSopenharmony_ci                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1646c87c5fbaSopenharmony_ci      return 0;
1647c87c5fbaSopenharmony_ci    }
1648c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.private_key &&
1649c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.private_key_len > 0) {
1650c87c5fbaSopenharmony_ci      int pkey_type = map_key_type(setup_data->pki_key.key.asn1.private_key_type);
1651c87c5fbaSopenharmony_ci      if (!(SSL_use_PrivateKey_ASN1(pkey_type, ssl,
1652c87c5fbaSopenharmony_ci                                    setup_data->pki_key.key.asn1.private_key,
1653c87c5fbaSopenharmony_ci                                    (long)setup_data->pki_key.key.asn1.private_key_len))) {
1654c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1655c87c5fbaSopenharmony_ci                      "%s Private Key\n",
1656c87c5fbaSopenharmony_ci                      role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client",
1657c87c5fbaSopenharmony_ci                      "ASN1");
1658c87c5fbaSopenharmony_ci        return 0;
1659c87c5fbaSopenharmony_ci      }
1660c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER ||
1661c87c5fbaSopenharmony_ci               (setup_data->pki_key.key.asn1.public_cert &&
1662c87c5fbaSopenharmony_ci                setup_data->pki_key.key.asn1.public_cert_len > 0)) {
1663c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No %s Private Key defined",
1664c87c5fbaSopenharmony_ci                   role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1665c87c5fbaSopenharmony_ci      return 0;
1666c87c5fbaSopenharmony_ci    }
1667c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.asn1.ca_cert &&
1668c87c5fbaSopenharmony_ci        setup_data->pki_key.key.asn1.ca_cert_len > 0) {
1669c87c5fbaSopenharmony_ci      /* Need to use a temp variable as it gets incremented*/
1670c87c5fbaSopenharmony_ci      const uint8_t *p = setup_data->pki_key.key.asn1.ca_cert;
1671c87c5fbaSopenharmony_ci      X509 *x509 = d2i_X509(NULL, &p, (long)setup_data->pki_key.key.asn1.ca_cert_len);
1672c87c5fbaSopenharmony_ci      X509_STORE *st;
1673c87c5fbaSopenharmony_ci      SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1674c87c5fbaSopenharmony_ci
1675c87c5fbaSopenharmony_ci      if (role == COAP_DTLS_ROLE_SERVER) {
1676c87c5fbaSopenharmony_ci        if (!x509 || !SSL_add_client_CA(ssl, x509)) {
1677c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1678c87c5fbaSopenharmony_ci                        "client CA File\n",
1679c87c5fbaSopenharmony_ci                        "ASN1");
1680c87c5fbaSopenharmony_ci          X509_free(x509);
1681c87c5fbaSopenharmony_ci          return 0;
1682c87c5fbaSopenharmony_ci        }
1683c87c5fbaSopenharmony_ci      }
1684c87c5fbaSopenharmony_ci
1685c87c5fbaSopenharmony_ci      /* Add CA to the trusted root CA store */
1686c87c5fbaSopenharmony_ci      st = SSL_CTX_get_cert_store(ctx);
1687c87c5fbaSopenharmony_ci      add_ca_to_cert_store(st, x509);
1688c87c5fbaSopenharmony_ci      X509_free(x509);
1689c87c5fbaSopenharmony_ci    }
1690c87c5fbaSopenharmony_ci    break;
1691c87c5fbaSopenharmony_ci
1692c87c5fbaSopenharmony_ci  case COAP_PKI_KEY_PKCS11:
1693c87c5fbaSopenharmony_ci    if (!ssl_engine) {
1694c87c5fbaSopenharmony_ci      ssl_engine = ENGINE_by_id("pkcs11");
1695c87c5fbaSopenharmony_ci      if (!ssl_engine) {
1696c87c5fbaSopenharmony_ci        coap_log_err("*** setup_pki: (D)TLS: No PKCS11 support - need OpenSSL pkcs11 engine\n");
1697c87c5fbaSopenharmony_ci        return 0;
1698c87c5fbaSopenharmony_ci      }
1699c87c5fbaSopenharmony_ci      if (!ENGINE_init(ssl_engine)) {
1700c87c5fbaSopenharmony_ci        /* the engine couldn't initialise, release 'ssl_engine' */
1701c87c5fbaSopenharmony_ci        ENGINE_free(ssl_engine);
1702c87c5fbaSopenharmony_ci        ssl_engine = NULL;
1703c87c5fbaSopenharmony_ci        coap_log_err("*** setup_pki: (D)TLS: PKCS11 engine initialize failed\n");
1704c87c5fbaSopenharmony_ci        return 0;
1705c87c5fbaSopenharmony_ci      }
1706c87c5fbaSopenharmony_ci    }
1707c87c5fbaSopenharmony_ci
1708c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.user_pin) {
1709c87c5fbaSopenharmony_ci      /* If not set, pin may be held in pkcs11: URI */
1710c87c5fbaSopenharmony_ci      if (ENGINE_ctrl_cmd_string(ssl_engine,
1711c87c5fbaSopenharmony_ci                                 "PIN",
1712c87c5fbaSopenharmony_ci                                 setup_data->pki_key.key.pkcs11.user_pin, 0) == 0) {
1713c87c5fbaSopenharmony_ci        coap_log_warn("*** setup_pki: (D)TLS: PKCS11: %s: Unable to set pin\n",
1714c87c5fbaSopenharmony_ci                      setup_data->pki_key.key.pkcs11.user_pin);
1715c87c5fbaSopenharmony_ci        return 0;
1716c87c5fbaSopenharmony_ci      }
1717c87c5fbaSopenharmony_ci    }
1718c87c5fbaSopenharmony_ci
1719c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.private_key &&
1720c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.private_key[0]) {
1721c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.private_key,
1722c87c5fbaSopenharmony_ci                      "pkcs11:", 7) == 0) {
1723c87c5fbaSopenharmony_ci        EVP_PKEY *pkey = ENGINE_load_private_key(ssl_engine,
1724c87c5fbaSopenharmony_ci                                                 setup_data->pki_key.key.pkcs11.private_key,
1725c87c5fbaSopenharmony_ci                                                 NULL, NULL);
1726c87c5fbaSopenharmony_ci
1727c87c5fbaSopenharmony_ci        if (!pkey) {
1728c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1729c87c5fbaSopenharmony_ci                        "%s Private Key\n",
1730c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key,
1731c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1732c87c5fbaSopenharmony_ci          return 0;
1733c87c5fbaSopenharmony_ci        }
1734c87c5fbaSopenharmony_ci        if (!SSL_use_PrivateKey(ssl, pkey)) {
1735c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1736c87c5fbaSopenharmony_ci                        "%s Private Key\n",
1737c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key,
1738c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1739c87c5fbaSopenharmony_ci          EVP_PKEY_free(pkey);
1740c87c5fbaSopenharmony_ci          return 0;
1741c87c5fbaSopenharmony_ci        }
1742c87c5fbaSopenharmony_ci        EVP_PKEY_free(pkey);
1743c87c5fbaSopenharmony_ci      } else {
1744c87c5fbaSopenharmony_ci        if (!(SSL_use_PrivateKey_file(ssl,
1745c87c5fbaSopenharmony_ci                                      setup_data->pki_key.key.pkcs11.private_key,
1746c87c5fbaSopenharmony_ci                                      SSL_FILETYPE_ASN1))) {
1747c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1748c87c5fbaSopenharmony_ci                        "%s Private Key\n",
1749c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.private_key,
1750c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1751c87c5fbaSopenharmony_ci          return 0;
1752c87c5fbaSopenharmony_ci        }
1753c87c5fbaSopenharmony_ci      }
1754c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER) {
1755c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Private Key defined\n");
1756c87c5fbaSopenharmony_ci      return 0;
1757c87c5fbaSopenharmony_ci    }
1758c87c5fbaSopenharmony_ci
1759c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.public_cert &&
1760c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.public_cert[0]) {
1761c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.public_cert,
1762c87c5fbaSopenharmony_ci                      "pkcs11:", 7) == 0) {
1763c87c5fbaSopenharmony_ci        X509 *x509;
1764c87c5fbaSopenharmony_ci
1765c87c5fbaSopenharmony_ci        x509 = missing_ENGINE_load_cert(
1766c87c5fbaSopenharmony_ci                   setup_data->pki_key.key.pkcs11.public_cert);
1767c87c5fbaSopenharmony_ci        if (!x509) {
1768c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1769c87c5fbaSopenharmony_ci                        "%s Certificate\n",
1770c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert,
1771c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1772c87c5fbaSopenharmony_ci          return 0;
1773c87c5fbaSopenharmony_ci        }
1774c87c5fbaSopenharmony_ci        if (!SSL_use_certificate(ssl, x509)) {
1775c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1776c87c5fbaSopenharmony_ci                        "%s Certificate\n",
1777c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert,
1778c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1779c87c5fbaSopenharmony_ci          X509_free(x509);
1780c87c5fbaSopenharmony_ci          return 0;
1781c87c5fbaSopenharmony_ci        }
1782c87c5fbaSopenharmony_ci        X509_free(x509);
1783c87c5fbaSopenharmony_ci      } else {
1784c87c5fbaSopenharmony_ci        if (!(SSL_use_certificate_file(ssl,
1785c87c5fbaSopenharmony_ci                                       setup_data->pki_key.key.pkcs11.public_cert,
1786c87c5fbaSopenharmony_ci                                       SSL_FILETYPE_ASN1))) {
1787c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1788c87c5fbaSopenharmony_ci                        "%s Certificate\n",
1789c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.public_cert,
1790c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1791c87c5fbaSopenharmony_ci          return 0;
1792c87c5fbaSopenharmony_ci        }
1793c87c5fbaSopenharmony_ci      }
1794c87c5fbaSopenharmony_ci    } else if (role == COAP_DTLS_ROLE_SERVER) {
1795c87c5fbaSopenharmony_ci      coap_log_err("*** setup_pki: (D)TLS: No Server Certificate defined\n");
1796c87c5fbaSopenharmony_ci      return 0;
1797c87c5fbaSopenharmony_ci    }
1798c87c5fbaSopenharmony_ci
1799c87c5fbaSopenharmony_ci    if (setup_data->pki_key.key.pkcs11.ca &&
1800c87c5fbaSopenharmony_ci        setup_data->pki_key.key.pkcs11.ca[0]) {
1801c87c5fbaSopenharmony_ci      X509_STORE *st;
1802c87c5fbaSopenharmony_ci
1803c87c5fbaSopenharmony_ci      if (strncasecmp(setup_data->pki_key.key.pkcs11.ca, "pkcs11:", 7) == 0) {
1804c87c5fbaSopenharmony_ci        X509 *x509;
1805c87c5fbaSopenharmony_ci        SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1806c87c5fbaSopenharmony_ci
1807c87c5fbaSopenharmony_ci        x509 = missing_ENGINE_load_cert(
1808c87c5fbaSopenharmony_ci                   setup_data->pki_key.key.pkcs11.ca);
1809c87c5fbaSopenharmony_ci        if (!x509) {
1810c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to load "
1811c87c5fbaSopenharmony_ci                        "%s CA Certificate\n",
1812c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca,
1813c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1814c87c5fbaSopenharmony_ci          return 0;
1815c87c5fbaSopenharmony_ci        }
1816c87c5fbaSopenharmony_ci        if (!SSL_add_client_CA(ssl, x509)) {
1817c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1818c87c5fbaSopenharmony_ci                        "%s CA Certificate\n",
1819c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca,
1820c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1821c87c5fbaSopenharmony_ci          X509_free(x509);
1822c87c5fbaSopenharmony_ci          return 0;
1823c87c5fbaSopenharmony_ci        }
1824c87c5fbaSopenharmony_ci        st = SSL_CTX_get_cert_store(ctx);
1825c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x509);
1826c87c5fbaSopenharmony_ci        X509_free(x509);
1827c87c5fbaSopenharmony_ci      } else {
1828c87c5fbaSopenharmony_ci        FILE *fp = fopen(setup_data->pki_key.key.pkcs11.ca, "r");
1829c87c5fbaSopenharmony_ci        X509 *x509 = fp ? d2i_X509_fp(fp, NULL) : NULL;
1830c87c5fbaSopenharmony_ci        SSL_CTX *ctx = SSL_get_SSL_CTX(ssl);
1831c87c5fbaSopenharmony_ci
1832c87c5fbaSopenharmony_ci        if (!x509 || !SSL_add_client_CA(ssl, x509)) {
1833c87c5fbaSopenharmony_ci          coap_log_warn("*** setup_pki: (D)TLS: %s: Unable to configure "
1834c87c5fbaSopenharmony_ci                        "%s CA File\n",
1835c87c5fbaSopenharmony_ci                        setup_data->pki_key.key.pkcs11.ca,
1836c87c5fbaSopenharmony_ci                        role == COAP_DTLS_ROLE_SERVER ? "Server" : "Client");
1837c87c5fbaSopenharmony_ci          if (x509)
1838c87c5fbaSopenharmony_ci            X509_free(x509);
1839c87c5fbaSopenharmony_ci          return 0;
1840c87c5fbaSopenharmony_ci        }
1841c87c5fbaSopenharmony_ci        st = SSL_CTX_get_cert_store(ctx);
1842c87c5fbaSopenharmony_ci        add_ca_to_cert_store(st, x509);
1843c87c5fbaSopenharmony_ci        X509_free(x509);
1844c87c5fbaSopenharmony_ci      }
1845c87c5fbaSopenharmony_ci    }
1846c87c5fbaSopenharmony_ci    break;
1847c87c5fbaSopenharmony_ci
1848c87c5fbaSopenharmony_ci  default:
1849c87c5fbaSopenharmony_ci    coap_log_err("*** setup_pki: (D)TLS: Unknown key type %d\n",
1850c87c5fbaSopenharmony_ci                 setup_data->pki_key.key_type);
1851c87c5fbaSopenharmony_ci    return 0;
1852c87c5fbaSopenharmony_ci  }
1853c87c5fbaSopenharmony_ci  return 1;
1854c87c5fbaSopenharmony_ci}
1855c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L || COAP_CLIENT_SUPPORT */
1856c87c5fbaSopenharmony_ci
1857c87c5fbaSopenharmony_cistatic char *
1858c87c5fbaSopenharmony_ciget_san_or_cn_from_cert(X509 *x509) {
1859c87c5fbaSopenharmony_ci  if (x509) {
1860c87c5fbaSopenharmony_ci    char *cn;
1861c87c5fbaSopenharmony_ci    int n;
1862c87c5fbaSopenharmony_ci    STACK_OF(GENERAL_NAME) *san_list;
1863c87c5fbaSopenharmony_ci    char buffer[256];
1864c87c5fbaSopenharmony_ci
1865c87c5fbaSopenharmony_ci    san_list = X509_get_ext_d2i(x509, NID_subject_alt_name, NULL, NULL);
1866c87c5fbaSopenharmony_ci    if (san_list) {
1867c87c5fbaSopenharmony_ci      int san_count = sk_GENERAL_NAME_num(san_list);
1868c87c5fbaSopenharmony_ci
1869c87c5fbaSopenharmony_ci      for (n = 0; n < san_count; n++) {
1870c87c5fbaSopenharmony_ci        const GENERAL_NAME *name = sk_GENERAL_NAME_value(san_list, n);
1871c87c5fbaSopenharmony_ci
1872c87c5fbaSopenharmony_ci        if (name->type == GEN_DNS) {
1873c87c5fbaSopenharmony_ci          const char *dns_name = (const char *)ASN1_STRING_get0_data(name->d.dNSName);
1874c87c5fbaSopenharmony_ci
1875c87c5fbaSopenharmony_ci          /* Make sure that there is not an embedded NUL in the dns_name */
1876c87c5fbaSopenharmony_ci          if (ASN1_STRING_length(name->d.dNSName) != (int)strlen(dns_name))
1877c87c5fbaSopenharmony_ci            continue;
1878c87c5fbaSopenharmony_ci          cn = OPENSSL_strdup(dns_name);
1879c87c5fbaSopenharmony_ci          sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1880c87c5fbaSopenharmony_ci          return cn;
1881c87c5fbaSopenharmony_ci        }
1882c87c5fbaSopenharmony_ci      }
1883c87c5fbaSopenharmony_ci      sk_GENERAL_NAME_pop_free(san_list, GENERAL_NAME_free);
1884c87c5fbaSopenharmony_ci    }
1885c87c5fbaSopenharmony_ci    /* Otherwise look for the CN= field */
1886c87c5fbaSopenharmony_ci    X509_NAME_oneline(X509_get_subject_name(x509), buffer, sizeof(buffer));
1887c87c5fbaSopenharmony_ci
1888c87c5fbaSopenharmony_ci    /* Need to emulate strcasestr() here.  Looking for CN= */
1889c87c5fbaSopenharmony_ci    n = (int)strlen(buffer) - 3;
1890c87c5fbaSopenharmony_ci    cn = buffer;
1891c87c5fbaSopenharmony_ci    while (n > 0) {
1892c87c5fbaSopenharmony_ci      if (((cn[0] == 'C') || (cn[0] == 'c')) &&
1893c87c5fbaSopenharmony_ci          ((cn[1] == 'N') || (cn[1] == 'n')) &&
1894c87c5fbaSopenharmony_ci          (cn[2] == '=')) {
1895c87c5fbaSopenharmony_ci        cn += 3;
1896c87c5fbaSopenharmony_ci        break;
1897c87c5fbaSopenharmony_ci      }
1898c87c5fbaSopenharmony_ci      cn++;
1899c87c5fbaSopenharmony_ci      n--;
1900c87c5fbaSopenharmony_ci    }
1901c87c5fbaSopenharmony_ci    if (n > 0) {
1902c87c5fbaSopenharmony_ci      char *ecn = strchr(cn, '/');
1903c87c5fbaSopenharmony_ci      if (ecn) {
1904c87c5fbaSopenharmony_ci        return OPENSSL_strndup(cn, ecn-cn);
1905c87c5fbaSopenharmony_ci      } else {
1906c87c5fbaSopenharmony_ci        return OPENSSL_strdup(cn);
1907c87c5fbaSopenharmony_ci      }
1908c87c5fbaSopenharmony_ci    }
1909c87c5fbaSopenharmony_ci  }
1910c87c5fbaSopenharmony_ci  return NULL;
1911c87c5fbaSopenharmony_ci}
1912c87c5fbaSopenharmony_ci
1913c87c5fbaSopenharmony_cistatic int
1914c87c5fbaSopenharmony_citls_verify_call_back(int preverify_ok, X509_STORE_CTX *ctx) {
1915c87c5fbaSopenharmony_ci  SSL *ssl = X509_STORE_CTX_get_ex_data(ctx,
1916c87c5fbaSopenharmony_ci                                        SSL_get_ex_data_X509_STORE_CTX_idx());
1917c87c5fbaSopenharmony_ci  coap_session_t *session = SSL_get_app_data(ssl);
1918c87c5fbaSopenharmony_ci  coap_openssl_context_t *context =
1919c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)session->context->dtls_context);
1920c87c5fbaSopenharmony_ci  coap_dtls_pki_t *setup_data = &context->setup_data;
1921c87c5fbaSopenharmony_ci  int depth = X509_STORE_CTX_get_error_depth(ctx);
1922c87c5fbaSopenharmony_ci  int err = X509_STORE_CTX_get_error(ctx);
1923c87c5fbaSopenharmony_ci  X509 *x509 = X509_STORE_CTX_get_current_cert(ctx);
1924c87c5fbaSopenharmony_ci  char *cn = get_san_or_cn_from_cert(x509);
1925c87c5fbaSopenharmony_ci  int keep_preverify_ok = preverify_ok;
1926c87c5fbaSopenharmony_ci
1927c87c5fbaSopenharmony_ci  if (!preverify_ok) {
1928c87c5fbaSopenharmony_ci    switch (err) {
1929c87c5fbaSopenharmony_ci    case X509_V_ERR_CERT_NOT_YET_VALID:
1930c87c5fbaSopenharmony_ci    case X509_V_ERR_CERT_HAS_EXPIRED:
1931c87c5fbaSopenharmony_ci      if (setup_data->allow_expired_certs)
1932c87c5fbaSopenharmony_ci        preverify_ok = 1;
1933c87c5fbaSopenharmony_ci      break;
1934c87c5fbaSopenharmony_ci    case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
1935c87c5fbaSopenharmony_ci      if (setup_data->allow_self_signed && !setup_data->check_common_ca)
1936c87c5fbaSopenharmony_ci        preverify_ok = 1;
1937c87c5fbaSopenharmony_ci      break;
1938c87c5fbaSopenharmony_ci    case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN: /* Set if the CA is not known */
1939c87c5fbaSopenharmony_ci      if (!setup_data->verify_peer_cert)
1940c87c5fbaSopenharmony_ci        preverify_ok = 1;
1941c87c5fbaSopenharmony_ci      break;
1942c87c5fbaSopenharmony_ci    case X509_V_ERR_UNABLE_TO_GET_CRL:
1943c87c5fbaSopenharmony_ci      if (setup_data->allow_no_crl)
1944c87c5fbaSopenharmony_ci        preverify_ok = 1;
1945c87c5fbaSopenharmony_ci      break;
1946c87c5fbaSopenharmony_ci    case X509_V_ERR_CRL_NOT_YET_VALID:
1947c87c5fbaSopenharmony_ci    case X509_V_ERR_CRL_HAS_EXPIRED:
1948c87c5fbaSopenharmony_ci      if (setup_data->allow_expired_crl)
1949c87c5fbaSopenharmony_ci        preverify_ok = 1;
1950c87c5fbaSopenharmony_ci      break;
1951c87c5fbaSopenharmony_ci    case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
1952c87c5fbaSopenharmony_ci    case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
1953c87c5fbaSopenharmony_ci    case X509_V_ERR_AKID_SKID_MISMATCH:
1954c87c5fbaSopenharmony_ci      if (!setup_data->verify_peer_cert)
1955c87c5fbaSopenharmony_ci        preverify_ok = 1;
1956c87c5fbaSopenharmony_ci      break;
1957c87c5fbaSopenharmony_ci    default:
1958c87c5fbaSopenharmony_ci      break;
1959c87c5fbaSopenharmony_ci    }
1960c87c5fbaSopenharmony_ci    if (setup_data->cert_chain_validation &&
1961c87c5fbaSopenharmony_ci        depth > (setup_data->cert_chain_verify_depth + 1)) {
1962c87c5fbaSopenharmony_ci      preverify_ok = 0;
1963c87c5fbaSopenharmony_ci      err = X509_V_ERR_CERT_CHAIN_TOO_LONG;
1964c87c5fbaSopenharmony_ci      X509_STORE_CTX_set_error(ctx, err);
1965c87c5fbaSopenharmony_ci    }
1966c87c5fbaSopenharmony_ci    if (!preverify_ok) {
1967c87c5fbaSopenharmony_ci      if (err == X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN) {
1968c87c5fbaSopenharmony_ci        coap_log_warn("   %s: %s: '%s' depth=%d\n",
1969c87c5fbaSopenharmony_ci                      coap_session_str(session),
1970c87c5fbaSopenharmony_ci                      "Unknown CA", cn ? cn : "?", depth);
1971c87c5fbaSopenharmony_ci      } else {
1972c87c5fbaSopenharmony_ci        coap_log_warn("   %s: %s: '%s' depth=%d\n",
1973c87c5fbaSopenharmony_ci                      coap_session_str(session),
1974c87c5fbaSopenharmony_ci                      X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1975c87c5fbaSopenharmony_ci      }
1976c87c5fbaSopenharmony_ci    } else {
1977c87c5fbaSopenharmony_ci      coap_log_info("   %s: %s: overridden: '%s' depth=%d\n",
1978c87c5fbaSopenharmony_ci                    coap_session_str(session),
1979c87c5fbaSopenharmony_ci                    X509_verify_cert_error_string(err), cn ? cn : "?", depth);
1980c87c5fbaSopenharmony_ci    }
1981c87c5fbaSopenharmony_ci  }
1982c87c5fbaSopenharmony_ci  /* Certificate - depth == 0 is the Client Cert */
1983c87c5fbaSopenharmony_ci  if (setup_data->validate_cn_call_back && keep_preverify_ok) {
1984c87c5fbaSopenharmony_ci    int length = i2d_X509(x509, NULL);
1985c87c5fbaSopenharmony_ci    uint8_t *base_buf;
1986c87c5fbaSopenharmony_ci    uint8_t *base_buf2 = base_buf = OPENSSL_malloc(length);
1987c87c5fbaSopenharmony_ci
1988c87c5fbaSopenharmony_ci    /* base_buf2 gets moved to the end */
1989c87c5fbaSopenharmony_ci    i2d_X509(x509, &base_buf2);
1990c87c5fbaSopenharmony_ci    if (!setup_data->validate_cn_call_back(cn, base_buf, length, session,
1991c87c5fbaSopenharmony_ci                                           depth, preverify_ok,
1992c87c5fbaSopenharmony_ci                                           setup_data->cn_call_back_arg)) {
1993c87c5fbaSopenharmony_ci      if (depth == 0) {
1994c87c5fbaSopenharmony_ci        X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED);
1995c87c5fbaSopenharmony_ci      } else {
1996c87c5fbaSopenharmony_ci        X509_STORE_CTX_set_error(ctx, X509_V_ERR_INVALID_CA);
1997c87c5fbaSopenharmony_ci      }
1998c87c5fbaSopenharmony_ci      preverify_ok = 0;
1999c87c5fbaSopenharmony_ci    }
2000c87c5fbaSopenharmony_ci    OPENSSL_free(base_buf);
2001c87c5fbaSopenharmony_ci  }
2002c87c5fbaSopenharmony_ci  OPENSSL_free(cn);
2003c87c5fbaSopenharmony_ci  return preverify_ok;
2004c87c5fbaSopenharmony_ci}
2005c87c5fbaSopenharmony_ci
2006c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
2007c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2008c87c5fbaSopenharmony_ci/*
2009c87c5fbaSopenharmony_ci * During the SSL/TLS initial negotiations, tls_secret_call_back() is called so
2010c87c5fbaSopenharmony_ci * it is possible to determine whether this is a PKI or PSK incoming
2011c87c5fbaSopenharmony_ci * request and adjust the ciphers if necessary
2012c87c5fbaSopenharmony_ci *
2013c87c5fbaSopenharmony_ci * Set up by SSL_set_session_secret_cb() in tls_server_name_call_back()
2014c87c5fbaSopenharmony_ci */
2015c87c5fbaSopenharmony_cistatic int
2016c87c5fbaSopenharmony_citls_secret_call_back(SSL *ssl,
2017c87c5fbaSopenharmony_ci                     void *secret,
2018c87c5fbaSopenharmony_ci                     int *secretlen,
2019c87c5fbaSopenharmony_ci                     STACK_OF(SSL_CIPHER) *peer_ciphers,
2020c87c5fbaSopenharmony_ci                     const SSL_CIPHER **cipher COAP_UNUSED,
2021c87c5fbaSopenharmony_ci                     void *arg
2022c87c5fbaSopenharmony_ci                    ) {
2023c87c5fbaSopenharmony_ci  int     ii;
2024c87c5fbaSopenharmony_ci  int     psk_requested = 0;
2025c87c5fbaSopenharmony_ci  coap_session_t *session;
2026c87c5fbaSopenharmony_ci  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2027c87c5fbaSopenharmony_ci
2028c87c5fbaSopenharmony_ci  session = (coap_session_t *)SSL_get_app_data(ssl);
2029c87c5fbaSopenharmony_ci  assert(session != NULL);
2030c87c5fbaSopenharmony_ci  assert(session->context != NULL);
2031c87c5fbaSopenharmony_ci  if (session == NULL ||
2032c87c5fbaSopenharmony_ci      session->context == NULL)
2033c87c5fbaSopenharmony_ci    return 0;
2034c87c5fbaSopenharmony_ci
2035c87c5fbaSopenharmony_ci  if ((session->psk_key) ||
2036c87c5fbaSopenharmony_ci      (session->context->spsk_setup_data.psk_info.key.s &&
2037c87c5fbaSopenharmony_ci       session->context->spsk_setup_data.psk_info.key.length)) {
2038c87c5fbaSopenharmony_ci    /* Is PSK being requested - if so, we need to change algorithms */
2039c87c5fbaSopenharmony_ci    for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2040c87c5fbaSopenharmony_ci      const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2041c87c5fbaSopenharmony_ci
2042c87c5fbaSopenharmony_ci      coap_dtls_log(COAP_LOG_INFO, "Client cipher: %s\n",
2043c87c5fbaSopenharmony_ci                    SSL_CIPHER_get_name(peer_cipher));
2044c87c5fbaSopenharmony_ci      if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2045c87c5fbaSopenharmony_ci        psk_requested = 1;
2046c87c5fbaSopenharmony_ci        break;
2047c87c5fbaSopenharmony_ci      }
2048c87c5fbaSopenharmony_ci    }
2049c87c5fbaSopenharmony_ci  }
2050c87c5fbaSopenharmony_ci  if (!psk_requested) {
2051c87c5fbaSopenharmony_ci    coap_log_debug("   %s: Using PKI ciphers\n",
2052c87c5fbaSopenharmony_ci                   coap_session_str(session));
2053c87c5fbaSopenharmony_ci
2054c87c5fbaSopenharmony_ci    if (setup_data->verify_peer_cert) {
2055c87c5fbaSopenharmony_ci      SSL_set_verify(ssl,
2056c87c5fbaSopenharmony_ci                     SSL_VERIFY_PEER |
2057c87c5fbaSopenharmony_ci                     SSL_VERIFY_CLIENT_ONCE |
2058c87c5fbaSopenharmony_ci                     SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2059c87c5fbaSopenharmony_ci                     tls_verify_call_back);
2060c87c5fbaSopenharmony_ci    } else {
2061c87c5fbaSopenharmony_ci      SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2062c87c5fbaSopenharmony_ci    }
2063c87c5fbaSopenharmony_ci
2064c87c5fbaSopenharmony_ci    /* Check CA Chain */
2065c87c5fbaSopenharmony_ci    if (setup_data->cert_chain_validation)
2066c87c5fbaSopenharmony_ci      SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2067c87c5fbaSopenharmony_ci
2068c87c5fbaSopenharmony_ci    /* Certificate Revocation */
2069c87c5fbaSopenharmony_ci    if (setup_data->check_cert_revocation) {
2070c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM *param;
2071c87c5fbaSopenharmony_ci
2072c87c5fbaSopenharmony_ci      param = X509_VERIFY_PARAM_new();
2073c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2074c87c5fbaSopenharmony_ci      SSL_set1_param(ssl, param);
2075c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM_free(param);
2076c87c5fbaSopenharmony_ci    }
2077c87c5fbaSopenharmony_ci    if (setup_data->additional_tls_setup_call_back) {
2078c87c5fbaSopenharmony_ci      /* Additional application setup wanted */
2079c87c5fbaSopenharmony_ci      if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2080c87c5fbaSopenharmony_ci        return 0;
2081c87c5fbaSopenharmony_ci    }
2082c87c5fbaSopenharmony_ci  } else {
2083c87c5fbaSopenharmony_ci    if (session->psk_key) {
2084c87c5fbaSopenharmony_ci      memcpy(secret, session->psk_key->s, session->psk_key->length);
2085c87c5fbaSopenharmony_ci      *secretlen = session->psk_key->length;
2086c87c5fbaSopenharmony_ci    } else if (session->context->spsk_setup_data.psk_info.key.s &&
2087c87c5fbaSopenharmony_ci               session->context->spsk_setup_data.psk_info.key.length) {
2088c87c5fbaSopenharmony_ci      memcpy(secret, session->context->spsk_setup_data.psk_info.key.s,
2089c87c5fbaSopenharmony_ci             session->context->spsk_setup_data.psk_info.key.length);
2090c87c5fbaSopenharmony_ci      *secretlen = session->context->spsk_setup_data.psk_info.key.length;
2091c87c5fbaSopenharmony_ci    }
2092c87c5fbaSopenharmony_ci    coap_log_debug("   %s: Setting PSK ciphers\n",
2093c87c5fbaSopenharmony_ci                   coap_session_str(session));
2094c87c5fbaSopenharmony_ci    /*
2095c87c5fbaSopenharmony_ci     * Force a PSK algorithm to be used, so we do PSK
2096c87c5fbaSopenharmony_ci     */
2097c87c5fbaSopenharmony_ci    SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2098c87c5fbaSopenharmony_ci    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2099c87c5fbaSopenharmony_ci  }
2100c87c5fbaSopenharmony_ci  return 0;
2101c87c5fbaSopenharmony_ci}
2102c87c5fbaSopenharmony_ci
2103c87c5fbaSopenharmony_ci/*
2104c87c5fbaSopenharmony_ci * During the SSL/TLS initial negotiations, tls_server_name_call_back() is
2105c87c5fbaSopenharmony_ci * called so it is possible to set up an extra callback to determine whether
2106c87c5fbaSopenharmony_ci * this is a PKI or PSK incoming request and adjust the ciphers if necessary
2107c87c5fbaSopenharmony_ci *
2108c87c5fbaSopenharmony_ci * Set up by SSL_CTX_set_tlsext_servername_callback() in
2109c87c5fbaSopenharmony_ci * coap_dtls_context_set_pki()
2110c87c5fbaSopenharmony_ci */
2111c87c5fbaSopenharmony_cistatic int
2112c87c5fbaSopenharmony_citls_server_name_call_back(SSL *ssl,
2113c87c5fbaSopenharmony_ci                          int *sd COAP_UNUSED,
2114c87c5fbaSopenharmony_ci                          void *arg
2115c87c5fbaSopenharmony_ci                         ) {
2116c87c5fbaSopenharmony_ci  coap_dtls_pki_t *setup_data = (coap_dtls_pki_t *)arg;
2117c87c5fbaSopenharmony_ci
2118c87c5fbaSopenharmony_ci  if (!ssl) {
2119c87c5fbaSopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
2120c87c5fbaSopenharmony_ci  }
2121c87c5fbaSopenharmony_ci
2122c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
2123c87c5fbaSopenharmony_ci    /* SNI checking requested */
2124c87c5fbaSopenharmony_ci    coap_session_t *session = (coap_session_t *)SSL_get_app_data(ssl);
2125c87c5fbaSopenharmony_ci    coap_openssl_context_t *context =
2126c87c5fbaSopenharmony_ci        ((coap_openssl_context_t *)session->context->dtls_context);
2127c87c5fbaSopenharmony_ci    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2128c87c5fbaSopenharmony_ci    size_t i;
2129c87c5fbaSopenharmony_ci
2130c87c5fbaSopenharmony_ci    if (!sni || !sni[0]) {
2131c87c5fbaSopenharmony_ci      sni = "";
2132c87c5fbaSopenharmony_ci    }
2133c87c5fbaSopenharmony_ci    for (i = 0; i < context->sni_count; i++) {
2134c87c5fbaSopenharmony_ci      if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2135c87c5fbaSopenharmony_ci        break;
2136c87c5fbaSopenharmony_ci      }
2137c87c5fbaSopenharmony_ci    }
2138c87c5fbaSopenharmony_ci    if (i == context->sni_count) {
2139c87c5fbaSopenharmony_ci      SSL_CTX *ctx;
2140c87c5fbaSopenharmony_ci      coap_dtls_pki_t sni_setup_data;
2141c87c5fbaSopenharmony_ci      coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
2142c87c5fbaSopenharmony_ci                                   setup_data->sni_call_back_arg);
2143c87c5fbaSopenharmony_ci      if (!new_entry) {
2144c87c5fbaSopenharmony_ci        return SSL_TLSEXT_ERR_ALERT_FATAL;
2145c87c5fbaSopenharmony_ci      }
2146c87c5fbaSopenharmony_ci      /* Need to set up a new SSL_CTX to switch to */
2147c87c5fbaSopenharmony_ci      if (session->proto == COAP_PROTO_DTLS) {
2148c87c5fbaSopenharmony_ci        /* Set up DTLS context */
2149c87c5fbaSopenharmony_ci        ctx = SSL_CTX_new(DTLS_method());
2150c87c5fbaSopenharmony_ci        if (!ctx)
2151c87c5fbaSopenharmony_ci          goto error;
2152c87c5fbaSopenharmony_ci        SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2153c87c5fbaSopenharmony_ci        SSL_CTX_set_app_data(ctx, &context->dtls);
2154c87c5fbaSopenharmony_ci        SSL_CTX_set_read_ahead(ctx, 1);
2155c87c5fbaSopenharmony_ci        coap_set_user_prefs(ctx);
2156c87c5fbaSopenharmony_ci        SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2157c87c5fbaSopenharmony_ci        SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2158c87c5fbaSopenharmony_ci        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2159c87c5fbaSopenharmony_ci        SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2160c87c5fbaSopenharmony_ci      }
2161c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2162c87c5fbaSopenharmony_ci      else {
2163c87c5fbaSopenharmony_ci        /* Set up TLS context */
2164c87c5fbaSopenharmony_ci        ctx = SSL_CTX_new(TLS_method());
2165c87c5fbaSopenharmony_ci        if (!ctx)
2166c87c5fbaSopenharmony_ci          goto error;
2167c87c5fbaSopenharmony_ci        SSL_CTX_set_app_data(ctx, &context->tls);
2168c87c5fbaSopenharmony_ci        SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2169c87c5fbaSopenharmony_ci        coap_set_user_prefs(ctx);
2170c87c5fbaSopenharmony_ci        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2171c87c5fbaSopenharmony_ci        SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2172c87c5fbaSopenharmony_ci      }
2173c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2174c87c5fbaSopenharmony_ci      sni_setup_data = *setup_data;
2175c87c5fbaSopenharmony_ci      sni_setup_data.pki_key = *new_entry;
2176c87c5fbaSopenharmony_ci      setup_pki_server(ctx, &sni_setup_data);
2177c87c5fbaSopenharmony_ci
2178c87c5fbaSopenharmony_ci      context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2179c87c5fbaSopenharmony_ci                                                (context->sni_count+1)*sizeof(sni_entry));
2180c87c5fbaSopenharmony_ci      context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2181c87c5fbaSopenharmony_ci      context->sni_entry_list[context->sni_count].ctx = ctx;
2182c87c5fbaSopenharmony_ci      context->sni_count++;
2183c87c5fbaSopenharmony_ci    }
2184c87c5fbaSopenharmony_ci    SSL_set_SSL_CTX(ssl, context->sni_entry_list[i].ctx);
2185c87c5fbaSopenharmony_ci    SSL_clear_options(ssl, 0xFFFFFFFFL);
2186c87c5fbaSopenharmony_ci    SSL_set_options(ssl, SSL_CTX_get_options(context->sni_entry_list[i].ctx));
2187c87c5fbaSopenharmony_ci  }
2188c87c5fbaSopenharmony_ci
2189c87c5fbaSopenharmony_ci  /*
2190c87c5fbaSopenharmony_ci   * Have to do extra call back next to get client algorithms
2191c87c5fbaSopenharmony_ci   * SSL_get_client_ciphers() does not work this early on
2192c87c5fbaSopenharmony_ci   */
2193c87c5fbaSopenharmony_ci  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2194c87c5fbaSopenharmony_ci  return SSL_TLSEXT_ERR_OK;
2195c87c5fbaSopenharmony_ci
2196c87c5fbaSopenharmony_cierror:
2197c87c5fbaSopenharmony_ci  return SSL_TLSEXT_ERR_ALERT_WARNING;
2198c87c5fbaSopenharmony_ci}
2199c87c5fbaSopenharmony_ci
2200c87c5fbaSopenharmony_ci/*
2201c87c5fbaSopenharmony_ci * During the SSL/TLS initial negotiations, psk_tls_server_name_call_back() is
2202c87c5fbaSopenharmony_ci * called to see if SNI is being used.
2203c87c5fbaSopenharmony_ci *
2204c87c5fbaSopenharmony_ci * Set up by SSL_CTX_set_tlsext_servername_callback()
2205c87c5fbaSopenharmony_ci * in coap_dtls_context_set_spsk()
2206c87c5fbaSopenharmony_ci */
2207c87c5fbaSopenharmony_cistatic int
2208c87c5fbaSopenharmony_cipsk_tls_server_name_call_back(SSL *ssl,
2209c87c5fbaSopenharmony_ci                              int *sd COAP_UNUSED,
2210c87c5fbaSopenharmony_ci                              void *arg
2211c87c5fbaSopenharmony_ci                             ) {
2212c87c5fbaSopenharmony_ci  coap_dtls_spsk_t *setup_data = (coap_dtls_spsk_t *)arg;
2213c87c5fbaSopenharmony_ci
2214c87c5fbaSopenharmony_ci  if (!ssl) {
2215c87c5fbaSopenharmony_ci    return SSL_TLSEXT_ERR_NOACK;
2216c87c5fbaSopenharmony_ci  }
2217c87c5fbaSopenharmony_ci
2218c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
2219c87c5fbaSopenharmony_ci    /* SNI checking requested */
2220c87c5fbaSopenharmony_ci    coap_session_t *c_session = (coap_session_t *)SSL_get_app_data(ssl);
2221c87c5fbaSopenharmony_ci    coap_openssl_context_t *o_context =
2222c87c5fbaSopenharmony_ci        ((coap_openssl_context_t *)c_session->context->dtls_context);
2223c87c5fbaSopenharmony_ci    const char *sni = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name);
2224c87c5fbaSopenharmony_ci    size_t i;
2225c87c5fbaSopenharmony_ci    char lhint[COAP_DTLS_HINT_LENGTH];
2226c87c5fbaSopenharmony_ci
2227c87c5fbaSopenharmony_ci    if (!sni || !sni[0]) {
2228c87c5fbaSopenharmony_ci      sni = "";
2229c87c5fbaSopenharmony_ci    }
2230c87c5fbaSopenharmony_ci    for (i = 0; i < o_context->psk_sni_count; i++) {
2231c87c5fbaSopenharmony_ci      if (!strcasecmp(sni, (char *)o_context->psk_sni_entry_list[i].sni)) {
2232c87c5fbaSopenharmony_ci        break;
2233c87c5fbaSopenharmony_ci      }
2234c87c5fbaSopenharmony_ci    }
2235c87c5fbaSopenharmony_ci    if (i == o_context->psk_sni_count) {
2236c87c5fbaSopenharmony_ci      SSL_CTX *ctx;
2237c87c5fbaSopenharmony_ci      const coap_dtls_spsk_info_t *new_entry =
2238c87c5fbaSopenharmony_ci          setup_data->validate_sni_call_back(sni,
2239c87c5fbaSopenharmony_ci                                             c_session,
2240c87c5fbaSopenharmony_ci                                             setup_data->sni_call_back_arg);
2241c87c5fbaSopenharmony_ci      if (!new_entry) {
2242c87c5fbaSopenharmony_ci        return SSL_TLSEXT_ERR_ALERT_FATAL;
2243c87c5fbaSopenharmony_ci      }
2244c87c5fbaSopenharmony_ci      /* Need to set up a new SSL_CTX to switch to */
2245c87c5fbaSopenharmony_ci      if (c_session->proto == COAP_PROTO_DTLS) {
2246c87c5fbaSopenharmony_ci        /* Set up DTLS context */
2247c87c5fbaSopenharmony_ci        ctx = SSL_CTX_new(DTLS_method());
2248c87c5fbaSopenharmony_ci        if (!ctx)
2249c87c5fbaSopenharmony_ci          goto error;
2250c87c5fbaSopenharmony_ci        SSL_CTX_set_min_proto_version(ctx, DTLS1_2_VERSION);
2251c87c5fbaSopenharmony_ci        SSL_CTX_set_app_data(ctx, &o_context->dtls);
2252c87c5fbaSopenharmony_ci        SSL_CTX_set_read_ahead(ctx, 1);
2253c87c5fbaSopenharmony_ci        SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2254c87c5fbaSopenharmony_ci        SSL_CTX_set_cookie_generate_cb(ctx, coap_dtls_generate_cookie);
2255c87c5fbaSopenharmony_ci        SSL_CTX_set_cookie_verify_cb(ctx, coap_dtls_verify_cookie);
2256c87c5fbaSopenharmony_ci        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2257c87c5fbaSopenharmony_ci        SSL_CTX_set_options(ctx, SSL_OP_NO_QUERY_MTU);
2258c87c5fbaSopenharmony_ci      }
2259c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2260c87c5fbaSopenharmony_ci      else {
2261c87c5fbaSopenharmony_ci        /* Set up TLS context */
2262c87c5fbaSopenharmony_ci        ctx = SSL_CTX_new(TLS_method());
2263c87c5fbaSopenharmony_ci        if (!ctx)
2264c87c5fbaSopenharmony_ci          goto error;
2265c87c5fbaSopenharmony_ci        SSL_CTX_set_app_data(ctx, &o_context->tls);
2266c87c5fbaSopenharmony_ci        SSL_CTX_set_min_proto_version(ctx, TLS1_VERSION);
2267c87c5fbaSopenharmony_ci        SSL_CTX_set_cipher_list(ctx, COAP_OPENSSL_CIPHERS);
2268c87c5fbaSopenharmony_ci        SSL_CTX_set_info_callback(ctx, coap_dtls_info_callback);
2269c87c5fbaSopenharmony_ci        SSL_CTX_set_alpn_select_cb(ctx, server_alpn_callback, NULL);
2270c87c5fbaSopenharmony_ci      }
2271c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2272c87c5fbaSopenharmony_ci
2273c87c5fbaSopenharmony_ci      o_context->psk_sni_entry_list =
2274c87c5fbaSopenharmony_ci          OPENSSL_realloc(o_context->psk_sni_entry_list,
2275c87c5fbaSopenharmony_ci                          (o_context->psk_sni_count+1)*sizeof(psk_sni_entry));
2276c87c5fbaSopenharmony_ci      o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2277c87c5fbaSopenharmony_ci          OPENSSL_strdup(sni);
2278c87c5fbaSopenharmony_ci      o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2279c87c5fbaSopenharmony_ci          *new_entry;
2280c87c5fbaSopenharmony_ci      o_context->psk_sni_entry_list[o_context->psk_sni_count].ctx =
2281c87c5fbaSopenharmony_ci          ctx;
2282c87c5fbaSopenharmony_ci      o_context->psk_sni_count++;
2283c87c5fbaSopenharmony_ci    }
2284c87c5fbaSopenharmony_ci    SSL_set_SSL_CTX(ssl, o_context->psk_sni_entry_list[i].ctx);
2285c87c5fbaSopenharmony_ci    SSL_clear_options(ssl, 0xFFFFFFFFL);
2286c87c5fbaSopenharmony_ci    SSL_set_options(ssl,
2287c87c5fbaSopenharmony_ci                    SSL_CTX_get_options(o_context->psk_sni_entry_list[i].ctx));
2288c87c5fbaSopenharmony_ci    coap_session_refresh_psk_key(c_session,
2289c87c5fbaSopenharmony_ci                                 &o_context->psk_sni_entry_list[i].psk_info.key);
2290c87c5fbaSopenharmony_ci    snprintf(lhint, sizeof(lhint), "%.*s",
2291c87c5fbaSopenharmony_ci             (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2292c87c5fbaSopenharmony_ci             o_context->psk_sni_entry_list[i].psk_info.hint.s);
2293c87c5fbaSopenharmony_ci    SSL_use_psk_identity_hint(ssl, lhint);
2294c87c5fbaSopenharmony_ci  }
2295c87c5fbaSopenharmony_ci
2296c87c5fbaSopenharmony_ci  /*
2297c87c5fbaSopenharmony_ci   * Have to do extra call back next to get client algorithms
2298c87c5fbaSopenharmony_ci   * SSL_get_client_ciphers() does not work this early on
2299c87c5fbaSopenharmony_ci   */
2300c87c5fbaSopenharmony_ci  SSL_set_session_secret_cb(ssl, tls_secret_call_back, arg);
2301c87c5fbaSopenharmony_ci  return SSL_TLSEXT_ERR_OK;
2302c87c5fbaSopenharmony_ci
2303c87c5fbaSopenharmony_cierror:
2304c87c5fbaSopenharmony_ci  return SSL_TLSEXT_ERR_ALERT_WARNING;
2305c87c5fbaSopenharmony_ci}
2306c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2307c87c5fbaSopenharmony_ci/*
2308c87c5fbaSopenharmony_ci * During the SSL/TLS initial negotiations, tls_client_hello_call_back() is
2309c87c5fbaSopenharmony_ci * called early in the Client Hello processing so it is possible to determine
2310c87c5fbaSopenharmony_ci * whether this is a PKI or PSK incoming request and adjust the ciphers if
2311c87c5fbaSopenharmony_ci * necessary.
2312c87c5fbaSopenharmony_ci *
2313c87c5fbaSopenharmony_ci * Set up by SSL_CTX_set_client_hello_cb().
2314c87c5fbaSopenharmony_ci */
2315c87c5fbaSopenharmony_cistatic int
2316c87c5fbaSopenharmony_citls_client_hello_call_back(SSL *ssl,
2317c87c5fbaSopenharmony_ci                           int *al,
2318c87c5fbaSopenharmony_ci                           void *arg COAP_UNUSED
2319c87c5fbaSopenharmony_ci                          ) {
2320c87c5fbaSopenharmony_ci  coap_session_t *session;
2321c87c5fbaSopenharmony_ci  coap_openssl_context_t *dtls_context;
2322c87c5fbaSopenharmony_ci  coap_dtls_pki_t *setup_data;
2323c87c5fbaSopenharmony_ci  int psk_requested = 0;
2324c87c5fbaSopenharmony_ci  const unsigned char *out;
2325c87c5fbaSopenharmony_ci  size_t outlen;
2326c87c5fbaSopenharmony_ci
2327c87c5fbaSopenharmony_ci  if (!ssl) {
2328c87c5fbaSopenharmony_ci    *al = SSL_AD_INTERNAL_ERROR;
2329c87c5fbaSopenharmony_ci    return SSL_CLIENT_HELLO_ERROR;
2330c87c5fbaSopenharmony_ci  }
2331c87c5fbaSopenharmony_ci  session = (coap_session_t *)SSL_get_app_data(ssl);
2332c87c5fbaSopenharmony_ci  assert(session != NULL);
2333c87c5fbaSopenharmony_ci  assert(session->context != NULL);
2334c87c5fbaSopenharmony_ci  assert(session->context->dtls_context != NULL);
2335c87c5fbaSopenharmony_ci  if (session == NULL ||
2336c87c5fbaSopenharmony_ci      session->context == NULL ||
2337c87c5fbaSopenharmony_ci      session->context->dtls_context == NULL) {
2338c87c5fbaSopenharmony_ci    *al = SSL_AD_INTERNAL_ERROR;
2339c87c5fbaSopenharmony_ci    return SSL_CLIENT_HELLO_ERROR;
2340c87c5fbaSopenharmony_ci  }
2341c87c5fbaSopenharmony_ci  dtls_context = (coap_openssl_context_t *)session->context->dtls_context;
2342c87c5fbaSopenharmony_ci  setup_data = &dtls_context->setup_data;
2343c87c5fbaSopenharmony_ci
2344c87c5fbaSopenharmony_ci  /*
2345c87c5fbaSopenharmony_ci   * See if PSK being requested
2346c87c5fbaSopenharmony_ci   */
2347c87c5fbaSopenharmony_ci  if ((session->psk_key) ||
2348c87c5fbaSopenharmony_ci      (session->context->spsk_setup_data.psk_info.key.s &&
2349c87c5fbaSopenharmony_ci       session->context->spsk_setup_data.psk_info.key.length)) {
2350c87c5fbaSopenharmony_ci    size_t len = SSL_client_hello_get0_ciphers(ssl, &out);
2351c87c5fbaSopenharmony_ci    STACK_OF(SSL_CIPHER) *peer_ciphers = NULL;
2352c87c5fbaSopenharmony_ci    STACK_OF(SSL_CIPHER) *scsvc = NULL;
2353c87c5fbaSopenharmony_ci
2354c87c5fbaSopenharmony_ci    if (len && SSL_bytes_to_cipher_list(ssl, out, len,
2355c87c5fbaSopenharmony_ci                                        SSL_client_hello_isv2(ssl),
2356c87c5fbaSopenharmony_ci                                        &peer_ciphers, &scsvc)) {
2357c87c5fbaSopenharmony_ci      int ii;
2358c87c5fbaSopenharmony_ci      for (ii = 0; ii < sk_SSL_CIPHER_num(peer_ciphers); ii++) {
2359c87c5fbaSopenharmony_ci        const SSL_CIPHER *peer_cipher = sk_SSL_CIPHER_value(peer_ciphers, ii);
2360c87c5fbaSopenharmony_ci
2361c87c5fbaSopenharmony_ci        coap_dtls_log(COAP_LOG_INFO,
2362c87c5fbaSopenharmony_ci                      "Client cipher: %s (%04x)\n",
2363c87c5fbaSopenharmony_ci                      SSL_CIPHER_get_name(peer_cipher),
2364c87c5fbaSopenharmony_ci                      SSL_CIPHER_get_protocol_id(peer_cipher));
2365c87c5fbaSopenharmony_ci        if (strstr(SSL_CIPHER_get_name(peer_cipher), "PSK")) {
2366c87c5fbaSopenharmony_ci          psk_requested = 1;
2367c87c5fbaSopenharmony_ci          break;
2368c87c5fbaSopenharmony_ci        }
2369c87c5fbaSopenharmony_ci      }
2370c87c5fbaSopenharmony_ci    }
2371c87c5fbaSopenharmony_ci    sk_SSL_CIPHER_free(peer_ciphers);
2372c87c5fbaSopenharmony_ci    sk_SSL_CIPHER_free(scsvc);
2373c87c5fbaSopenharmony_ci  }
2374c87c5fbaSopenharmony_ci
2375c87c5fbaSopenharmony_ci  if (psk_requested) {
2376c87c5fbaSopenharmony_ci    /*
2377c87c5fbaSopenharmony_ci     * Client has requested PSK and it is supported
2378c87c5fbaSopenharmony_ci     */
2379c87c5fbaSopenharmony_ci    coap_log_debug("   %s: PSK request\n",
2380c87c5fbaSopenharmony_ci                   coap_session_str(session));
2381c87c5fbaSopenharmony_ci    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2382c87c5fbaSopenharmony_ci    if (setup_data->additional_tls_setup_call_back) {
2383c87c5fbaSopenharmony_ci      /* Additional application setup wanted */
2384c87c5fbaSopenharmony_ci      if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2385c87c5fbaSopenharmony_ci        return 0;
2386c87c5fbaSopenharmony_ci    }
2387c87c5fbaSopenharmony_ci    return SSL_CLIENT_HELLO_SUCCESS;
2388c87c5fbaSopenharmony_ci  }
2389c87c5fbaSopenharmony_ci
2390c87c5fbaSopenharmony_ci  /*
2391c87c5fbaSopenharmony_ci   * Handle Certificate requests
2392c87c5fbaSopenharmony_ci   */
2393c87c5fbaSopenharmony_ci
2394c87c5fbaSopenharmony_ci  /*
2395c87c5fbaSopenharmony_ci   * Determine what type of certificate is being requested
2396c87c5fbaSopenharmony_ci   */
2397c87c5fbaSopenharmony_ci  if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_client_certificate_type,
2398c87c5fbaSopenharmony_ci                                &out, &outlen)) {
2399c87c5fbaSopenharmony_ci    size_t ii;
2400c87c5fbaSopenharmony_ci    for (ii = 0; ii < outlen; ii++) {
2401c87c5fbaSopenharmony_ci      switch (out[ii]) {
2402c87c5fbaSopenharmony_ci      case 0:
2403c87c5fbaSopenharmony_ci        /* RFC6091 X.509 */
2404c87c5fbaSopenharmony_ci        if (outlen >= 2) {
2405c87c5fbaSopenharmony_ci          /* X.509 cannot be the singular entry. RFC6091 3.1. Client Hello */
2406c87c5fbaSopenharmony_ci          goto is_x509;
2407c87c5fbaSopenharmony_ci        }
2408c87c5fbaSopenharmony_ci        break;
2409c87c5fbaSopenharmony_ci      case 2:
2410c87c5fbaSopenharmony_ci        /* RFC7250 RPK - not yet supported */
2411c87c5fbaSopenharmony_ci        break;
2412c87c5fbaSopenharmony_ci      default:
2413c87c5fbaSopenharmony_ci        break;
2414c87c5fbaSopenharmony_ci      }
2415c87c5fbaSopenharmony_ci    }
2416c87c5fbaSopenharmony_ci    *al = SSL_AD_UNSUPPORTED_EXTENSION;
2417c87c5fbaSopenharmony_ci    return SSL_CLIENT_HELLO_ERROR;
2418c87c5fbaSopenharmony_ci  }
2419c87c5fbaSopenharmony_ci
2420c87c5fbaSopenharmony_ciis_x509:
2421c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
2422c87c5fbaSopenharmony_ci    /*
2423c87c5fbaSopenharmony_ci     * SNI checking requested
2424c87c5fbaSopenharmony_ci     */
2425c87c5fbaSopenharmony_ci    coap_dtls_pki_t sni_setup_data;
2426c87c5fbaSopenharmony_ci    coap_openssl_context_t *context =
2427c87c5fbaSopenharmony_ci        ((coap_openssl_context_t *)session->context->dtls_context);
2428c87c5fbaSopenharmony_ci    const char *sni = "";
2429c87c5fbaSopenharmony_ci    char *sni_tmp = NULL;
2430c87c5fbaSopenharmony_ci    size_t i;
2431c87c5fbaSopenharmony_ci
2432c87c5fbaSopenharmony_ci    if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2433c87c5fbaSopenharmony_ci        outlen > 5 &&
2434c87c5fbaSopenharmony_ci        (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2435c87c5fbaSopenharmony_ci        out[2] == TLSEXT_NAMETYPE_host_name &&
2436c87c5fbaSopenharmony_ci        (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2437c87c5fbaSopenharmony_ci      /* Skip over length, type and length */
2438c87c5fbaSopenharmony_ci      out += 5;
2439c87c5fbaSopenharmony_ci      outlen -= 5;
2440c87c5fbaSopenharmony_ci      sni_tmp = OPENSSL_malloc(outlen+1);
2441c87c5fbaSopenharmony_ci      sni_tmp[outlen] = '\000';
2442c87c5fbaSopenharmony_ci      memcpy(sni_tmp, out, outlen);
2443c87c5fbaSopenharmony_ci      sni = sni_tmp;
2444c87c5fbaSopenharmony_ci    }
2445c87c5fbaSopenharmony_ci    /* Is this a cached entry? */
2446c87c5fbaSopenharmony_ci    for (i = 0; i < context->sni_count; i++) {
2447c87c5fbaSopenharmony_ci      if (!strcasecmp(sni, context->sni_entry_list[i].sni)) {
2448c87c5fbaSopenharmony_ci        break;
2449c87c5fbaSopenharmony_ci      }
2450c87c5fbaSopenharmony_ci    }
2451c87c5fbaSopenharmony_ci    if (i == context->sni_count) {
2452c87c5fbaSopenharmony_ci      /*
2453c87c5fbaSopenharmony_ci       * New SNI request
2454c87c5fbaSopenharmony_ci       */
2455c87c5fbaSopenharmony_ci      coap_dtls_key_t *new_entry = setup_data->validate_sni_call_back(sni,
2456c87c5fbaSopenharmony_ci                                   setup_data->sni_call_back_arg);
2457c87c5fbaSopenharmony_ci      if (!new_entry) {
2458c87c5fbaSopenharmony_ci        *al = SSL_AD_UNRECOGNIZED_NAME;
2459c87c5fbaSopenharmony_ci        return SSL_CLIENT_HELLO_ERROR;
2460c87c5fbaSopenharmony_ci      }
2461c87c5fbaSopenharmony_ci
2462c87c5fbaSopenharmony_ci
2463c87c5fbaSopenharmony_ci      context->sni_entry_list = OPENSSL_realloc(context->sni_entry_list,
2464c87c5fbaSopenharmony_ci                                                (context->sni_count+1)*sizeof(sni_entry));
2465c87c5fbaSopenharmony_ci      context->sni_entry_list[context->sni_count].sni = OPENSSL_strdup(sni);
2466c87c5fbaSopenharmony_ci      context->sni_entry_list[context->sni_count].pki_key = *new_entry;
2467c87c5fbaSopenharmony_ci      context->sni_count++;
2468c87c5fbaSopenharmony_ci    }
2469c87c5fbaSopenharmony_ci    if (sni_tmp) {
2470c87c5fbaSopenharmony_ci      OPENSSL_free(sni_tmp);
2471c87c5fbaSopenharmony_ci    }
2472c87c5fbaSopenharmony_ci    sni_setup_data = *setup_data;
2473c87c5fbaSopenharmony_ci    sni_setup_data.pki_key = context->sni_entry_list[i].pki_key;
2474c87c5fbaSopenharmony_ci    setup_pki_ssl(ssl, &sni_setup_data, COAP_DTLS_ROLE_SERVER);
2475c87c5fbaSopenharmony_ci  } else {
2476c87c5fbaSopenharmony_ci    setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_SERVER);
2477c87c5fbaSopenharmony_ci  }
2478c87c5fbaSopenharmony_ci
2479c87c5fbaSopenharmony_ci  coap_log_debug("   %s: Using PKI ciphers\n",
2480c87c5fbaSopenharmony_ci                 coap_session_str(session));
2481c87c5fbaSopenharmony_ci
2482c87c5fbaSopenharmony_ci  if (setup_data->verify_peer_cert) {
2483c87c5fbaSopenharmony_ci    SSL_set_verify(ssl,
2484c87c5fbaSopenharmony_ci                   SSL_VERIFY_PEER |
2485c87c5fbaSopenharmony_ci                   SSL_VERIFY_CLIENT_ONCE |
2486c87c5fbaSopenharmony_ci                   SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2487c87c5fbaSopenharmony_ci                   tls_verify_call_back);
2488c87c5fbaSopenharmony_ci  } else {
2489c87c5fbaSopenharmony_ci    SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2490c87c5fbaSopenharmony_ci  }
2491c87c5fbaSopenharmony_ci
2492c87c5fbaSopenharmony_ci  /* Check CA Chain */
2493c87c5fbaSopenharmony_ci  if (setup_data->cert_chain_validation)
2494c87c5fbaSopenharmony_ci    SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 2);
2495c87c5fbaSopenharmony_ci
2496c87c5fbaSopenharmony_ci  /* Certificate Revocation */
2497c87c5fbaSopenharmony_ci  if (setup_data->check_cert_revocation) {
2498c87c5fbaSopenharmony_ci    X509_VERIFY_PARAM *param;
2499c87c5fbaSopenharmony_ci
2500c87c5fbaSopenharmony_ci    param = X509_VERIFY_PARAM_new();
2501c87c5fbaSopenharmony_ci    X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2502c87c5fbaSopenharmony_ci    SSL_set1_param(ssl, param);
2503c87c5fbaSopenharmony_ci    X509_VERIFY_PARAM_free(param);
2504c87c5fbaSopenharmony_ci  }
2505c87c5fbaSopenharmony_ci  if (setup_data->additional_tls_setup_call_back) {
2506c87c5fbaSopenharmony_ci    /* Additional application setup wanted */
2507c87c5fbaSopenharmony_ci    if (!setup_data->additional_tls_setup_call_back(ssl, setup_data))
2508c87c5fbaSopenharmony_ci      return 0;
2509c87c5fbaSopenharmony_ci  }
2510c87c5fbaSopenharmony_ci  return SSL_CLIENT_HELLO_SUCCESS;
2511c87c5fbaSopenharmony_ci}
2512c87c5fbaSopenharmony_ci
2513c87c5fbaSopenharmony_ci/*
2514c87c5fbaSopenharmony_ci * During the SSL/TLS initial negotiations, psk_tls_client_hello_call_back() is
2515c87c5fbaSopenharmony_ci * called early in the Client Hello processing so it is possible to determine
2516c87c5fbaSopenharmony_ci * whether SNI needs to be handled
2517c87c5fbaSopenharmony_ci *
2518c87c5fbaSopenharmony_ci * Set up by SSL_CTX_set_client_hello_cb().
2519c87c5fbaSopenharmony_ci */
2520c87c5fbaSopenharmony_cistatic int
2521c87c5fbaSopenharmony_cipsk_tls_client_hello_call_back(SSL *ssl,
2522c87c5fbaSopenharmony_ci                               int *al,
2523c87c5fbaSopenharmony_ci                               void *arg COAP_UNUSED
2524c87c5fbaSopenharmony_ci                              ) {
2525c87c5fbaSopenharmony_ci  coap_session_t *c_session;
2526c87c5fbaSopenharmony_ci  coap_openssl_context_t *o_context;
2527c87c5fbaSopenharmony_ci  coap_dtls_spsk_t *setup_data;
2528c87c5fbaSopenharmony_ci  const unsigned char *out;
2529c87c5fbaSopenharmony_ci  size_t outlen;
2530c87c5fbaSopenharmony_ci
2531c87c5fbaSopenharmony_ci  if (!ssl)
2532c87c5fbaSopenharmony_ci    goto int_err;
2533c87c5fbaSopenharmony_ci  c_session = (coap_session_t *)SSL_get_app_data(ssl);
2534c87c5fbaSopenharmony_ci  if (!c_session || !c_session->context) {
2535c87c5fbaSopenharmony_ci    goto int_err;
2536c87c5fbaSopenharmony_ci  }
2537c87c5fbaSopenharmony_ci  o_context = (coap_openssl_context_t *)c_session->context->dtls_context;
2538c87c5fbaSopenharmony_ci  if (!o_context) {
2539c87c5fbaSopenharmony_ci    goto int_err;
2540c87c5fbaSopenharmony_ci  }
2541c87c5fbaSopenharmony_ci  setup_data = &c_session->context->spsk_setup_data;
2542c87c5fbaSopenharmony_ci
2543c87c5fbaSopenharmony_ci  if (setup_data->validate_sni_call_back) {
2544c87c5fbaSopenharmony_ci    /*
2545c87c5fbaSopenharmony_ci     * SNI checking requested
2546c87c5fbaSopenharmony_ci     */
2547c87c5fbaSopenharmony_ci    const char *sni = "";
2548c87c5fbaSopenharmony_ci    char *sni_tmp = NULL;
2549c87c5fbaSopenharmony_ci    size_t i;
2550c87c5fbaSopenharmony_ci    char lhint[COAP_DTLS_HINT_LENGTH];
2551c87c5fbaSopenharmony_ci
2552c87c5fbaSopenharmony_ci    if (SSL_client_hello_get0_ext(ssl, TLSEXT_TYPE_server_name, &out, &outlen) &&
2553c87c5fbaSopenharmony_ci        outlen > 5 &&
2554c87c5fbaSopenharmony_ci        (((out[0]<<8) + out[1] +2) == (int)outlen) &&
2555c87c5fbaSopenharmony_ci        out[2] == TLSEXT_NAMETYPE_host_name &&
2556c87c5fbaSopenharmony_ci        (((out[3]<<8) + out[4] +2 +3) == (int)outlen)) {
2557c87c5fbaSopenharmony_ci      /* Skip over length, type and length */
2558c87c5fbaSopenharmony_ci      out += 5;
2559c87c5fbaSopenharmony_ci      outlen -= 5;
2560c87c5fbaSopenharmony_ci      sni_tmp = OPENSSL_malloc(outlen+1);
2561c87c5fbaSopenharmony_ci      if (sni_tmp) {
2562c87c5fbaSopenharmony_ci        sni_tmp[outlen] = '\000';
2563c87c5fbaSopenharmony_ci        memcpy(sni_tmp, out, outlen);
2564c87c5fbaSopenharmony_ci        sni = sni_tmp;
2565c87c5fbaSopenharmony_ci      }
2566c87c5fbaSopenharmony_ci    }
2567c87c5fbaSopenharmony_ci
2568c87c5fbaSopenharmony_ci    /* Is this a cached entry? */
2569c87c5fbaSopenharmony_ci    for (i = 0; i < o_context->psk_sni_count; i++) {
2570c87c5fbaSopenharmony_ci      if (strcasecmp(sni, o_context->psk_sni_entry_list[i].sni) == 0) {
2571c87c5fbaSopenharmony_ci        break;
2572c87c5fbaSopenharmony_ci      }
2573c87c5fbaSopenharmony_ci    }
2574c87c5fbaSopenharmony_ci    if (i == o_context->psk_sni_count) {
2575c87c5fbaSopenharmony_ci      /*
2576c87c5fbaSopenharmony_ci       * New SNI request
2577c87c5fbaSopenharmony_ci       */
2578c87c5fbaSopenharmony_ci      psk_sni_entry *tmp_entry;
2579c87c5fbaSopenharmony_ci      const coap_dtls_spsk_info_t *new_entry = setup_data->validate_sni_call_back(
2580c87c5fbaSopenharmony_ci                                                   sni,
2581c87c5fbaSopenharmony_ci                                                   c_session,
2582c87c5fbaSopenharmony_ci                                                   setup_data->sni_call_back_arg);
2583c87c5fbaSopenharmony_ci      if (!new_entry) {
2584c87c5fbaSopenharmony_ci        *al = SSL_AD_UNRECOGNIZED_NAME;
2585c87c5fbaSopenharmony_ci        return SSL_CLIENT_HELLO_ERROR;
2586c87c5fbaSopenharmony_ci      }
2587c87c5fbaSopenharmony_ci
2588c87c5fbaSopenharmony_ci      tmp_entry =
2589c87c5fbaSopenharmony_ci          OPENSSL_realloc(o_context->psk_sni_entry_list,
2590c87c5fbaSopenharmony_ci                          (o_context->psk_sni_count+1)*sizeof(sni_entry));
2591c87c5fbaSopenharmony_ci      if (tmp_entry) {
2592c87c5fbaSopenharmony_ci        o_context->psk_sni_entry_list = tmp_entry;
2593c87c5fbaSopenharmony_ci        o_context->psk_sni_entry_list[o_context->psk_sni_count].sni =
2594c87c5fbaSopenharmony_ci            OPENSSL_strdup(sni);
2595c87c5fbaSopenharmony_ci        if (o_context->psk_sni_entry_list[o_context->psk_sni_count].sni) {
2596c87c5fbaSopenharmony_ci          o_context->psk_sni_entry_list[o_context->psk_sni_count].psk_info =
2597c87c5fbaSopenharmony_ci              *new_entry;
2598c87c5fbaSopenharmony_ci          o_context->psk_sni_count++;
2599c87c5fbaSopenharmony_ci        }
2600c87c5fbaSopenharmony_ci      }
2601c87c5fbaSopenharmony_ci    }
2602c87c5fbaSopenharmony_ci    if (sni_tmp) {
2603c87c5fbaSopenharmony_ci      OPENSSL_free(sni_tmp);
2604c87c5fbaSopenharmony_ci    }
2605c87c5fbaSopenharmony_ci    if (coap_session_refresh_psk_hint(c_session,
2606c87c5fbaSopenharmony_ci                                      &o_context->psk_sni_entry_list[i].psk_info.hint)
2607c87c5fbaSopenharmony_ci        == 0) {
2608c87c5fbaSopenharmony_ci      goto int_err;
2609c87c5fbaSopenharmony_ci    }
2610c87c5fbaSopenharmony_ci    if (coap_session_refresh_psk_key(c_session,
2611c87c5fbaSopenharmony_ci                                     &o_context->psk_sni_entry_list[i].psk_info.key)
2612c87c5fbaSopenharmony_ci        == 0) {
2613c87c5fbaSopenharmony_ci      goto int_err;
2614c87c5fbaSopenharmony_ci    }
2615c87c5fbaSopenharmony_ci    if (o_context->psk_sni_entry_list[i].psk_info.hint.s) {
2616c87c5fbaSopenharmony_ci      snprintf(lhint, sizeof(lhint), "%.*s",
2617c87c5fbaSopenharmony_ci               (int)o_context->psk_sni_entry_list[i].psk_info.hint.length,
2618c87c5fbaSopenharmony_ci               o_context->psk_sni_entry_list[i].psk_info.hint.s);
2619c87c5fbaSopenharmony_ci      SSL_use_psk_identity_hint(ssl, lhint);
2620c87c5fbaSopenharmony_ci    }
2621c87c5fbaSopenharmony_ci  }
2622c87c5fbaSopenharmony_ci  return SSL_CLIENT_HELLO_SUCCESS;
2623c87c5fbaSopenharmony_ci
2624c87c5fbaSopenharmony_ciint_err:
2625c87c5fbaSopenharmony_ci  *al = SSL_AD_INTERNAL_ERROR;
2626c87c5fbaSopenharmony_ci  return SSL_CLIENT_HELLO_ERROR;
2627c87c5fbaSopenharmony_ci}
2628c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2629c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
2630c87c5fbaSopenharmony_ci
2631c87c5fbaSopenharmony_ciint
2632c87c5fbaSopenharmony_cicoap_dtls_context_set_pki(coap_context_t *ctx,
2633c87c5fbaSopenharmony_ci                          const coap_dtls_pki_t *setup_data,
2634c87c5fbaSopenharmony_ci                          const coap_dtls_role_t role
2635c87c5fbaSopenharmony_ci                         ) {
2636c87c5fbaSopenharmony_ci  coap_openssl_context_t *context =
2637c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)ctx->dtls_context);
2638c87c5fbaSopenharmony_ci  BIO *bio;
2639c87c5fbaSopenharmony_ci  if (!setup_data)
2640c87c5fbaSopenharmony_ci    return 0;
2641c87c5fbaSopenharmony_ci  context->setup_data = *setup_data;
2642c87c5fbaSopenharmony_ci  if (!context->setup_data.verify_peer_cert) {
2643c87c5fbaSopenharmony_ci    /* Needs to be clear so that no CA DNs are transmitted */
2644c87c5fbaSopenharmony_ci    context->setup_data.check_common_ca = 0;
2645c87c5fbaSopenharmony_ci    /* Allow all of these but warn if issue */
2646c87c5fbaSopenharmony_ci    context->setup_data.allow_self_signed = 1;
2647c87c5fbaSopenharmony_ci    context->setup_data.allow_expired_certs = 1;
2648c87c5fbaSopenharmony_ci    context->setup_data.cert_chain_validation = 1;
2649c87c5fbaSopenharmony_ci    context->setup_data.cert_chain_verify_depth = 10;
2650c87c5fbaSopenharmony_ci    context->setup_data.check_cert_revocation = 1;
2651c87c5fbaSopenharmony_ci    context->setup_data.allow_no_crl = 1;
2652c87c5fbaSopenharmony_ci    context->setup_data.allow_expired_crl = 1;
2653c87c5fbaSopenharmony_ci    context->setup_data.allow_bad_md_hash = 1;
2654c87c5fbaSopenharmony_ci    context->setup_data.allow_short_rsa_length = 1;
2655c87c5fbaSopenharmony_ci  }
2656c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
2657c87c5fbaSopenharmony_ci  if (role == COAP_DTLS_ROLE_SERVER) {
2658c87c5fbaSopenharmony_ci    if (context->dtls.ctx) {
2659c87c5fbaSopenharmony_ci      /* SERVER DTLS */
2660c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2661c87c5fbaSopenharmony_ci      if (!setup_pki_server(context->dtls.ctx, setup_data))
2662c87c5fbaSopenharmony_ci        return 0;
2663c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
2664c87c5fbaSopenharmony_ci      /* libcoap is managing TLS connection based on setup_data options */
2665c87c5fbaSopenharmony_ci      /* Need to set up logic to differentiate between a PSK or PKI session */
2666c87c5fbaSopenharmony_ci      /*
2667c87c5fbaSopenharmony_ci       * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
2668c87c5fbaSopenharmony_ci       * which is not in 1.1.0
2669c87c5fbaSopenharmony_ci       */
2670c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2671c87c5fbaSopenharmony_ci      if (SSLeay() >= 0x10101000L) {
2672c87c5fbaSopenharmony_ci        coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
2673c87c5fbaSopenharmony_ci                      "no certificate checking\n",
2674c87c5fbaSopenharmony_ci                      OPENSSL_VERSION_NUMBER, SSLeay());
2675c87c5fbaSopenharmony_ci      }
2676c87c5fbaSopenharmony_ci      SSL_CTX_set_tlsext_servername_arg(context->dtls.ctx, &context->setup_data);
2677c87c5fbaSopenharmony_ci      SSL_CTX_set_tlsext_servername_callback(context->dtls.ctx,
2678c87c5fbaSopenharmony_ci                                             tls_server_name_call_back);
2679c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2680c87c5fbaSopenharmony_ci      SSL_CTX_set_client_hello_cb(context->dtls.ctx,
2681c87c5fbaSopenharmony_ci                                  tls_client_hello_call_back,
2682c87c5fbaSopenharmony_ci                                  NULL);
2683c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2684c87c5fbaSopenharmony_ci    }
2685c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2686c87c5fbaSopenharmony_ci    if (context->tls.ctx) {
2687c87c5fbaSopenharmony_ci      /* SERVER TLS */
2688c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2689c87c5fbaSopenharmony_ci      if (!setup_pki_server(context->tls.ctx, setup_data))
2690c87c5fbaSopenharmony_ci        return 0;
2691c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
2692c87c5fbaSopenharmony_ci      /* libcoap is managing TLS connection based on setup_data options */
2693c87c5fbaSopenharmony_ci      /* Need to set up logic to differentiate between a PSK or PKI session */
2694c87c5fbaSopenharmony_ci      /*
2695c87c5fbaSopenharmony_ci       * For OpenSSL 1.1.1, we need to use SSL_CTX_set_client_hello_cb()
2696c87c5fbaSopenharmony_ci       * which is not in 1.1.0
2697c87c5fbaSopenharmony_ci       */
2698c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2699c87c5fbaSopenharmony_ci      if (SSLeay() >= 0x10101000L) {
2700c87c5fbaSopenharmony_ci        coap_log_warn("OpenSSL compiled with %lux, linked with %lux, so "
2701c87c5fbaSopenharmony_ci                      "no certificate checking\n",
2702c87c5fbaSopenharmony_ci                      OPENSSL_VERSION_NUMBER, SSLeay());
2703c87c5fbaSopenharmony_ci      }
2704c87c5fbaSopenharmony_ci      SSL_CTX_set_tlsext_servername_arg(context->tls.ctx, &context->setup_data);
2705c87c5fbaSopenharmony_ci      SSL_CTX_set_tlsext_servername_callback(context->tls.ctx,
2706c87c5fbaSopenharmony_ci                                             tls_server_name_call_back);
2707c87c5fbaSopenharmony_ci#else /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2708c87c5fbaSopenharmony_ci      SSL_CTX_set_client_hello_cb(context->tls.ctx,
2709c87c5fbaSopenharmony_ci                                  tls_client_hello_call_back,
2710c87c5fbaSopenharmony_ci                                  NULL);
2711c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER >= 0x10101000L */
2712c87c5fbaSopenharmony_ci      /* TLS Only */
2713c87c5fbaSopenharmony_ci      SSL_CTX_set_alpn_select_cb(context->tls.ctx, server_alpn_callback, NULL);
2714c87c5fbaSopenharmony_ci    }
2715c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2716c87c5fbaSopenharmony_ci  }
2717c87c5fbaSopenharmony_ci#else /* ! COAP_SERVER_SUPPORT */
2718c87c5fbaSopenharmony_ci  (void)role;
2719c87c5fbaSopenharmony_ci#endif /* ! COAP_SERVER_SUPPORT */
2720c87c5fbaSopenharmony_ci
2721c87c5fbaSopenharmony_ci  if (!context->dtls.ssl) {
2722c87c5fbaSopenharmony_ci    /* This is set up to handle new incoming sessions to a server */
2723c87c5fbaSopenharmony_ci    context->dtls.ssl = SSL_new(context->dtls.ctx);
2724c87c5fbaSopenharmony_ci    if (!context->dtls.ssl)
2725c87c5fbaSopenharmony_ci      return 0;
2726c87c5fbaSopenharmony_ci    bio = BIO_new(context->dtls.meth);
2727c87c5fbaSopenharmony_ci    if (!bio) {
2728c87c5fbaSopenharmony_ci      SSL_free(context->dtls.ssl);
2729c87c5fbaSopenharmony_ci      context->dtls.ssl = NULL;
2730c87c5fbaSopenharmony_ci      return 0;
2731c87c5fbaSopenharmony_ci    }
2732c87c5fbaSopenharmony_ci    SSL_set_bio(context->dtls.ssl, bio, bio);
2733c87c5fbaSopenharmony_ci    SSL_set_app_data(context->dtls.ssl, NULL);
2734c87c5fbaSopenharmony_ci    SSL_set_options(context->dtls.ssl, SSL_OP_COOKIE_EXCHANGE);
2735c87c5fbaSopenharmony_ci    SSL_set_mtu(context->dtls.ssl, COAP_DEFAULT_MTU);
2736c87c5fbaSopenharmony_ci  }
2737c87c5fbaSopenharmony_ci  context->psk_pki_enabled |= IS_PKI;
2738c87c5fbaSopenharmony_ci  return 1;
2739c87c5fbaSopenharmony_ci}
2740c87c5fbaSopenharmony_ci
2741c87c5fbaSopenharmony_ciint
2742c87c5fbaSopenharmony_cicoap_dtls_context_set_pki_root_cas(coap_context_t *ctx,
2743c87c5fbaSopenharmony_ci                                   const char *ca_file,
2744c87c5fbaSopenharmony_ci                                   const char *ca_dir
2745c87c5fbaSopenharmony_ci                                  ) {
2746c87c5fbaSopenharmony_ci  coap_openssl_context_t *context =
2747c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)ctx->dtls_context);
2748c87c5fbaSopenharmony_ci  if (context->dtls.ctx) {
2749c87c5fbaSopenharmony_ci    if (!SSL_CTX_load_verify_locations(context->dtls.ctx, ca_file, ca_dir)) {
2750c87c5fbaSopenharmony_ci      coap_log_warn("Unable to install root CAs (%s/%s)\n",
2751c87c5fbaSopenharmony_ci                    ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
2752c87c5fbaSopenharmony_ci      return 0;
2753c87c5fbaSopenharmony_ci    }
2754c87c5fbaSopenharmony_ci  }
2755c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2756c87c5fbaSopenharmony_ci  if (context->tls.ctx) {
2757c87c5fbaSopenharmony_ci    if (!SSL_CTX_load_verify_locations(context->tls.ctx, ca_file, ca_dir)) {
2758c87c5fbaSopenharmony_ci      coap_log_warn("Unable to install root CAs (%s/%s)\n",
2759c87c5fbaSopenharmony_ci                    ca_file ? ca_file : "NULL", ca_dir ? ca_dir : "NULL");
2760c87c5fbaSopenharmony_ci      return 0;
2761c87c5fbaSopenharmony_ci    }
2762c87c5fbaSopenharmony_ci  }
2763c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2764c87c5fbaSopenharmony_ci  return 1;
2765c87c5fbaSopenharmony_ci}
2766c87c5fbaSopenharmony_ci
2767c87c5fbaSopenharmony_ciint
2768c87c5fbaSopenharmony_cicoap_dtls_context_check_keys_enabled(coap_context_t *ctx) {
2769c87c5fbaSopenharmony_ci  coap_openssl_context_t *context =
2770c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)ctx->dtls_context);
2771c87c5fbaSopenharmony_ci  return context->psk_pki_enabled ? 1 : 0;
2772c87c5fbaSopenharmony_ci}
2773c87c5fbaSopenharmony_ci
2774c87c5fbaSopenharmony_ci
2775c87c5fbaSopenharmony_civoid
2776c87c5fbaSopenharmony_cicoap_dtls_free_context(void *handle) {
2777c87c5fbaSopenharmony_ci  size_t i;
2778c87c5fbaSopenharmony_ci  coap_openssl_context_t *context = (coap_openssl_context_t *)handle;
2779c87c5fbaSopenharmony_ci
2780c87c5fbaSopenharmony_ci  if (context->dtls.ssl)
2781c87c5fbaSopenharmony_ci    SSL_free(context->dtls.ssl);
2782c87c5fbaSopenharmony_ci  if (context->dtls.ctx)
2783c87c5fbaSopenharmony_ci    SSL_CTX_free(context->dtls.ctx);
2784c87c5fbaSopenharmony_ci  if (context->dtls.cookie_hmac)
2785c87c5fbaSopenharmony_ci    HMAC_CTX_free(context->dtls.cookie_hmac);
2786c87c5fbaSopenharmony_ci  if (context->dtls.meth)
2787c87c5fbaSopenharmony_ci    BIO_meth_free(context->dtls.meth);
2788c87c5fbaSopenharmony_ci  if (context->dtls.bio_addr)
2789c87c5fbaSopenharmony_ci    BIO_ADDR_free(context->dtls.bio_addr);
2790c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2791c87c5fbaSopenharmony_ci  if (context->tls.ctx)
2792c87c5fbaSopenharmony_ci    SSL_CTX_free(context->tls.ctx);
2793c87c5fbaSopenharmony_ci  if (context->tls.meth)
2794c87c5fbaSopenharmony_ci    BIO_meth_free(context->tls.meth);
2795c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2796c87c5fbaSopenharmony_ci  for (i = 0; i < context->sni_count; i++) {
2797c87c5fbaSopenharmony_ci    OPENSSL_free(context->sni_entry_list[i].sni);
2798c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2799c87c5fbaSopenharmony_ci    SSL_CTX_free(context->sni_entry_list[i].ctx);
2800c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
2801c87c5fbaSopenharmony_ci  }
2802c87c5fbaSopenharmony_ci  if (context->sni_count)
2803c87c5fbaSopenharmony_ci    OPENSSL_free(context->sni_entry_list);
2804c87c5fbaSopenharmony_ci  for (i = 0; i < context->psk_sni_count; i++) {
2805c87c5fbaSopenharmony_ci    OPENSSL_free((char *)context->psk_sni_entry_list[i].sni);
2806c87c5fbaSopenharmony_ci#if OPENSSL_VERSION_NUMBER < 0x10101000L
2807c87c5fbaSopenharmony_ci    SSL_CTX_free(context->psk_sni_entry_list[i].ctx);
2808c87c5fbaSopenharmony_ci#endif /* OPENSSL_VERSION_NUMBER < 0x10101000L */
2809c87c5fbaSopenharmony_ci  }
2810c87c5fbaSopenharmony_ci  if (context->psk_sni_count)
2811c87c5fbaSopenharmony_ci    OPENSSL_free(context->psk_sni_entry_list);
2812c87c5fbaSopenharmony_ci  coap_free_type(COAP_STRING, context);
2813c87c5fbaSopenharmony_ci}
2814c87c5fbaSopenharmony_ci
2815c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
2816c87c5fbaSopenharmony_civoid *
2817c87c5fbaSopenharmony_cicoap_dtls_new_server_session(coap_session_t *session) {
2818c87c5fbaSopenharmony_ci  BIO *nbio = NULL;
2819c87c5fbaSopenharmony_ci  SSL *nssl = NULL, *ssl = NULL;
2820c87c5fbaSopenharmony_ci  coap_ssl_data *data;
2821c87c5fbaSopenharmony_ci  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
2822c87c5fbaSopenharmony_ci  int r;
2823c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_hint;
2824c87c5fbaSopenharmony_ci
2825c87c5fbaSopenharmony_ci  nssl = SSL_new(dtls->ctx);
2826c87c5fbaSopenharmony_ci  if (!nssl)
2827c87c5fbaSopenharmony_ci    goto error;
2828c87c5fbaSopenharmony_ci  nbio = BIO_new(dtls->meth);
2829c87c5fbaSopenharmony_ci  if (!nbio)
2830c87c5fbaSopenharmony_ci    goto error;
2831c87c5fbaSopenharmony_ci  SSL_set_bio(nssl, nbio, nbio);
2832c87c5fbaSopenharmony_ci  SSL_set_app_data(nssl, NULL);
2833c87c5fbaSopenharmony_ci  SSL_set_options(nssl, SSL_OP_COOKIE_EXCHANGE);
2834c87c5fbaSopenharmony_ci  SSL_set_mtu(nssl, (long)session->mtu);
2835c87c5fbaSopenharmony_ci  ssl = dtls->ssl;
2836c87c5fbaSopenharmony_ci  dtls->ssl = nssl;
2837c87c5fbaSopenharmony_ci  nssl = NULL;
2838c87c5fbaSopenharmony_ci  SSL_set_app_data(ssl, session);
2839c87c5fbaSopenharmony_ci
2840c87c5fbaSopenharmony_ci  data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
2841c87c5fbaSopenharmony_ci  data->session = session;
2842c87c5fbaSopenharmony_ci
2843c87c5fbaSopenharmony_ci  /* hint may get updated if/when handling SNI callback */
2844c87c5fbaSopenharmony_ci  psk_hint = coap_get_session_server_psk_hint(session);
2845c87c5fbaSopenharmony_ci  if (psk_hint != NULL && psk_hint->length) {
2846c87c5fbaSopenharmony_ci    char *hint = OPENSSL_malloc(psk_hint->length + 1);
2847c87c5fbaSopenharmony_ci
2848c87c5fbaSopenharmony_ci    if (hint) {
2849c87c5fbaSopenharmony_ci      memcpy(hint, psk_hint->s, psk_hint->length);
2850c87c5fbaSopenharmony_ci      hint[psk_hint->length] = '\000';
2851c87c5fbaSopenharmony_ci      SSL_use_psk_identity_hint(ssl, hint);
2852c87c5fbaSopenharmony_ci      OPENSSL_free(hint);
2853c87c5fbaSopenharmony_ci    } else {
2854c87c5fbaSopenharmony_ci      coap_log_warn("hint malloc failure\n");
2855c87c5fbaSopenharmony_ci    }
2856c87c5fbaSopenharmony_ci  }
2857c87c5fbaSopenharmony_ci
2858c87c5fbaSopenharmony_ci  r = SSL_accept(ssl);
2859c87c5fbaSopenharmony_ci  if (r == -1) {
2860c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
2861c87c5fbaSopenharmony_ci    if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
2862c87c5fbaSopenharmony_ci      r = 0;
2863c87c5fbaSopenharmony_ci  }
2864c87c5fbaSopenharmony_ci
2865c87c5fbaSopenharmony_ci  if (r == 0) {
2866c87c5fbaSopenharmony_ci    SSL_free(ssl);
2867c87c5fbaSopenharmony_ci    return NULL;
2868c87c5fbaSopenharmony_ci  }
2869c87c5fbaSopenharmony_ci
2870c87c5fbaSopenharmony_ci  return ssl;
2871c87c5fbaSopenharmony_ci
2872c87c5fbaSopenharmony_cierror:
2873c87c5fbaSopenharmony_ci  if (nssl)
2874c87c5fbaSopenharmony_ci    SSL_free(nssl);
2875c87c5fbaSopenharmony_ci  return NULL;
2876c87c5fbaSopenharmony_ci}
2877c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
2878c87c5fbaSopenharmony_ci
2879c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
2880c87c5fbaSopenharmony_cistatic int
2881c87c5fbaSopenharmony_cisetup_client_ssl_session(coap_session_t *session, SSL *ssl
2882c87c5fbaSopenharmony_ci                        ) {
2883c87c5fbaSopenharmony_ci  coap_openssl_context_t *context =
2884c87c5fbaSopenharmony_ci      ((coap_openssl_context_t *)session->context->dtls_context);
2885c87c5fbaSopenharmony_ci
2886c87c5fbaSopenharmony_ci  if (context->psk_pki_enabled & IS_PSK) {
2887c87c5fbaSopenharmony_ci    coap_dtls_cpsk_t *setup_data = &session->cpsk_setup_data;
2888c87c5fbaSopenharmony_ci
2889c87c5fbaSopenharmony_ci    /* Issue SNI if requested */
2890c87c5fbaSopenharmony_ci    if (setup_data->client_sni &&
2891c87c5fbaSopenharmony_ci        SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
2892c87c5fbaSopenharmony_ci      coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
2893c87c5fbaSopenharmony_ci                    setup_data->client_sni);
2894c87c5fbaSopenharmony_ci    }
2895c87c5fbaSopenharmony_ci    SSL_set_psk_client_callback(ssl, coap_dtls_psk_client_callback);
2896c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
2897c87c5fbaSopenharmony_ci    SSL_set_psk_server_callback(ssl, coap_dtls_psk_server_callback);
2898c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
2899c87c5fbaSopenharmony_ci    SSL_set_cipher_list(ssl, COAP_OPENSSL_PSK_CIPHERS);
2900c87c5fbaSopenharmony_ci    if (setup_data->validate_ih_call_back) {
2901c87c5fbaSopenharmony_ci      if (session->proto == COAP_PROTO_DTLS) {
2902c87c5fbaSopenharmony_ci        SSL_set_max_proto_version(ssl, DTLS1_2_VERSION);
2903c87c5fbaSopenharmony_ci      }
2904c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2905c87c5fbaSopenharmony_ci      else {
2906c87c5fbaSopenharmony_ci        SSL_set_max_proto_version(ssl, TLS1_2_VERSION);
2907c87c5fbaSopenharmony_ci      }
2908c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2909c87c5fbaSopenharmony_ci      coap_log_debug("CoAP Client restricted to (D)TLS1.2 with Identity Hint callback\n");
2910c87c5fbaSopenharmony_ci    }
2911c87c5fbaSopenharmony_ci  }
2912c87c5fbaSopenharmony_ci  if (context->psk_pki_enabled & IS_PKI) {
2913c87c5fbaSopenharmony_ci    coap_dtls_pki_t *setup_data = &context->setup_data;
2914c87c5fbaSopenharmony_ci    if (!setup_pki_ssl(ssl, setup_data, COAP_DTLS_ROLE_CLIENT))
2915c87c5fbaSopenharmony_ci      return 0;
2916c87c5fbaSopenharmony_ci    /* libcoap is managing (D)TLS connection based on setup_data options */
2917c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
2918c87c5fbaSopenharmony_ci    if (session->proto == COAP_PROTO_TLS)
2919c87c5fbaSopenharmony_ci      SSL_set_alpn_protos(ssl, coap_alpn, sizeof(coap_alpn));
2920c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
2921c87c5fbaSopenharmony_ci
2922c87c5fbaSopenharmony_ci    /* Issue SNI if requested */
2923c87c5fbaSopenharmony_ci    if (setup_data->client_sni &&
2924c87c5fbaSopenharmony_ci        SSL_set_tlsext_host_name(ssl, setup_data->client_sni) != 1) {
2925c87c5fbaSopenharmony_ci      coap_log_warn("SSL_set_tlsext_host_name: set '%s' failed",
2926c87c5fbaSopenharmony_ci                    setup_data->client_sni);
2927c87c5fbaSopenharmony_ci    }
2928c87c5fbaSopenharmony_ci    /* Certificate Revocation */
2929c87c5fbaSopenharmony_ci    if (setup_data->check_cert_revocation) {
2930c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM *param;
2931c87c5fbaSopenharmony_ci
2932c87c5fbaSopenharmony_ci      param = X509_VERIFY_PARAM_new();
2933c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM_set_flags(param, X509_V_FLAG_CRL_CHECK);
2934c87c5fbaSopenharmony_ci      SSL_set1_param(ssl, param);
2935c87c5fbaSopenharmony_ci      X509_VERIFY_PARAM_free(param);
2936c87c5fbaSopenharmony_ci    }
2937c87c5fbaSopenharmony_ci
2938c87c5fbaSopenharmony_ci    /* Verify Peer */
2939c87c5fbaSopenharmony_ci    if (setup_data->verify_peer_cert)
2940c87c5fbaSopenharmony_ci      SSL_set_verify(ssl,
2941c87c5fbaSopenharmony_ci                     SSL_VERIFY_PEER |
2942c87c5fbaSopenharmony_ci                     SSL_VERIFY_CLIENT_ONCE |
2943c87c5fbaSopenharmony_ci                     SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
2944c87c5fbaSopenharmony_ci                     tls_verify_call_back);
2945c87c5fbaSopenharmony_ci    else
2946c87c5fbaSopenharmony_ci      SSL_set_verify(ssl, SSL_VERIFY_NONE, tls_verify_call_back);
2947c87c5fbaSopenharmony_ci
2948c87c5fbaSopenharmony_ci    /* Check CA Chain */
2949c87c5fbaSopenharmony_ci    if (setup_data->cert_chain_validation)
2950c87c5fbaSopenharmony_ci      SSL_set_verify_depth(ssl, setup_data->cert_chain_verify_depth + 1);
2951c87c5fbaSopenharmony_ci
2952c87c5fbaSopenharmony_ci  }
2953c87c5fbaSopenharmony_ci  return 1;
2954c87c5fbaSopenharmony_ci}
2955c87c5fbaSopenharmony_ci
2956c87c5fbaSopenharmony_civoid *
2957c87c5fbaSopenharmony_cicoap_dtls_new_client_session(coap_session_t *session) {
2958c87c5fbaSopenharmony_ci  BIO *bio = NULL;
2959c87c5fbaSopenharmony_ci  SSL *ssl = NULL;
2960c87c5fbaSopenharmony_ci  coap_ssl_data *data;
2961c87c5fbaSopenharmony_ci  int r;
2962c87c5fbaSopenharmony_ci  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
2963c87c5fbaSopenharmony_ci  coap_dtls_context_t *dtls = &context->dtls;
2964c87c5fbaSopenharmony_ci
2965c87c5fbaSopenharmony_ci  ssl = SSL_new(dtls->ctx);
2966c87c5fbaSopenharmony_ci  if (!ssl)
2967c87c5fbaSopenharmony_ci    goto error;
2968c87c5fbaSopenharmony_ci  bio = BIO_new(dtls->meth);
2969c87c5fbaSopenharmony_ci  if (!bio)
2970c87c5fbaSopenharmony_ci    goto error;
2971c87c5fbaSopenharmony_ci  data = (coap_ssl_data *)BIO_get_data(bio);
2972c87c5fbaSopenharmony_ci  data->session = session;
2973c87c5fbaSopenharmony_ci  SSL_set_bio(ssl, bio, bio);
2974c87c5fbaSopenharmony_ci  SSL_set_app_data(ssl, session);
2975c87c5fbaSopenharmony_ci  SSL_set_options(ssl, SSL_OP_COOKIE_EXCHANGE);
2976c87c5fbaSopenharmony_ci  SSL_set_mtu(ssl, (long)session->mtu);
2977c87c5fbaSopenharmony_ci
2978c87c5fbaSopenharmony_ci  if (!setup_client_ssl_session(session, ssl))
2979c87c5fbaSopenharmony_ci    goto error;
2980c87c5fbaSopenharmony_ci
2981c87c5fbaSopenharmony_ci  session->dtls_timeout_count = 0;
2982c87c5fbaSopenharmony_ci
2983c87c5fbaSopenharmony_ci  r = SSL_connect(ssl);
2984c87c5fbaSopenharmony_ci  if (r == -1) {
2985c87c5fbaSopenharmony_ci    int ret = SSL_get_error(ssl, r);
2986c87c5fbaSopenharmony_ci    if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
2987c87c5fbaSopenharmony_ci      r = 0;
2988c87c5fbaSopenharmony_ci  }
2989c87c5fbaSopenharmony_ci
2990c87c5fbaSopenharmony_ci  if (r == 0)
2991c87c5fbaSopenharmony_ci    goto error;
2992c87c5fbaSopenharmony_ci
2993c87c5fbaSopenharmony_ci  session->tls = ssl;
2994c87c5fbaSopenharmony_ci  return ssl;
2995c87c5fbaSopenharmony_ci
2996c87c5fbaSopenharmony_cierror:
2997c87c5fbaSopenharmony_ci  if (ssl)
2998c87c5fbaSopenharmony_ci    SSL_free(ssl);
2999c87c5fbaSopenharmony_ci  return NULL;
3000c87c5fbaSopenharmony_ci}
3001c87c5fbaSopenharmony_ci
3002c87c5fbaSopenharmony_civoid
3003c87c5fbaSopenharmony_cicoap_dtls_session_update_mtu(coap_session_t *session) {
3004c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3005c87c5fbaSopenharmony_ci  if (ssl)
3006c87c5fbaSopenharmony_ci    SSL_set_mtu(ssl, (long)session->mtu);
3007c87c5fbaSopenharmony_ci}
3008c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
3009c87c5fbaSopenharmony_ci
3010c87c5fbaSopenharmony_civoid
3011c87c5fbaSopenharmony_cicoap_dtls_free_session(coap_session_t *session) {
3012c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3013c87c5fbaSopenharmony_ci  if (ssl) {
3014c87c5fbaSopenharmony_ci    if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3015c87c5fbaSopenharmony_ci      int r = SSL_shutdown(ssl);
3016c87c5fbaSopenharmony_ci      if (r == 0)
3017c87c5fbaSopenharmony_ci        r = SSL_shutdown(ssl);
3018c87c5fbaSopenharmony_ci    }
3019c87c5fbaSopenharmony_ci    SSL_free(ssl);
3020c87c5fbaSopenharmony_ci    session->tls = NULL;
3021c87c5fbaSopenharmony_ci    if (session->context)
3022c87c5fbaSopenharmony_ci      coap_handle_event(session->context, COAP_EVENT_DTLS_CLOSED, session);
3023c87c5fbaSopenharmony_ci  }
3024c87c5fbaSopenharmony_ci}
3025c87c5fbaSopenharmony_ci
3026c87c5fbaSopenharmony_cissize_t
3027c87c5fbaSopenharmony_cicoap_dtls_send(coap_session_t *session,
3028c87c5fbaSopenharmony_ci               const uint8_t *data, size_t data_len) {
3029c87c5fbaSopenharmony_ci  int r;
3030c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3031c87c5fbaSopenharmony_ci
3032c87c5fbaSopenharmony_ci  assert(ssl != NULL);
3033c87c5fbaSopenharmony_ci
3034c87c5fbaSopenharmony_ci  session->dtls_event = -1;
3035c87c5fbaSopenharmony_ci  r = SSL_write(ssl, data, (int)data_len);
3036c87c5fbaSopenharmony_ci
3037c87c5fbaSopenharmony_ci  if (r <= 0) {
3038c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
3039c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3040c87c5fbaSopenharmony_ci      r = 0;
3041c87c5fbaSopenharmony_ci    } else {
3042c87c5fbaSopenharmony_ci      coap_log_warn("coap_dtls_send: cannot send PDU\n");
3043c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_ZERO_RETURN)
3044c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3045c87c5fbaSopenharmony_ci      else if (err == SSL_ERROR_SSL)
3046c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3047c87c5fbaSopenharmony_ci      r = -1;
3048c87c5fbaSopenharmony_ci    }
3049c87c5fbaSopenharmony_ci  }
3050c87c5fbaSopenharmony_ci
3051c87c5fbaSopenharmony_ci  if (session->dtls_event >= 0) {
3052c87c5fbaSopenharmony_ci    /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
3053c87c5fbaSopenharmony_ci    if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3054c87c5fbaSopenharmony_ci      coap_handle_event(session->context, session->dtls_event, session);
3055c87c5fbaSopenharmony_ci    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3056c87c5fbaSopenharmony_ci        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3057c87c5fbaSopenharmony_ci      coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
3058c87c5fbaSopenharmony_ci      r = -1;
3059c87c5fbaSopenharmony_ci    }
3060c87c5fbaSopenharmony_ci  }
3061c87c5fbaSopenharmony_ci
3062c87c5fbaSopenharmony_ci  if (r > 0) {
3063c87c5fbaSopenharmony_ci    if (r == (ssize_t)data_len)
3064c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: dtls:  sent %4d bytes\n",
3065c87c5fbaSopenharmony_ci                     coap_session_str(session), r);
3066c87c5fbaSopenharmony_ci    else
3067c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: dtls:  sent %4d of %4zd bytes\n",
3068c87c5fbaSopenharmony_ci                     coap_session_str(session), r, data_len);
3069c87c5fbaSopenharmony_ci  }
3070c87c5fbaSopenharmony_ci  return r;
3071c87c5fbaSopenharmony_ci}
3072c87c5fbaSopenharmony_ci
3073c87c5fbaSopenharmony_ciint
3074c87c5fbaSopenharmony_cicoap_dtls_is_context_timeout(void) {
3075c87c5fbaSopenharmony_ci  return 0;
3076c87c5fbaSopenharmony_ci}
3077c87c5fbaSopenharmony_ci
3078c87c5fbaSopenharmony_cicoap_tick_t
3079c87c5fbaSopenharmony_cicoap_dtls_get_context_timeout(void *dtls_context) {
3080c87c5fbaSopenharmony_ci  (void)dtls_context;
3081c87c5fbaSopenharmony_ci  return 0;
3082c87c5fbaSopenharmony_ci}
3083c87c5fbaSopenharmony_ci
3084c87c5fbaSopenharmony_cicoap_tick_t
3085c87c5fbaSopenharmony_cicoap_dtls_get_timeout(coap_session_t *session, coap_tick_t now COAP_UNUSED) {
3086c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3087c87c5fbaSopenharmony_ci  coap_ssl_data *ssl_data;
3088c87c5fbaSopenharmony_ci
3089c87c5fbaSopenharmony_ci  assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3090c87c5fbaSopenharmony_ci  ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3091c87c5fbaSopenharmony_ci  return ssl_data->timeout;
3092c87c5fbaSopenharmony_ci}
3093c87c5fbaSopenharmony_ci
3094c87c5fbaSopenharmony_ci/*
3095c87c5fbaSopenharmony_ci * return 1 timed out
3096c87c5fbaSopenharmony_ci *        0 still timing out
3097c87c5fbaSopenharmony_ci */
3098c87c5fbaSopenharmony_ciint
3099c87c5fbaSopenharmony_cicoap_dtls_handle_timeout(coap_session_t *session) {
3100c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3101c87c5fbaSopenharmony_ci
3102c87c5fbaSopenharmony_ci  assert(ssl != NULL && session->state == COAP_SESSION_STATE_HANDSHAKE);
3103c87c5fbaSopenharmony_ci  if ((++session->dtls_timeout_count > session->max_retransmit) ||
3104c87c5fbaSopenharmony_ci      (DTLSv1_handle_timeout(ssl) < 0)) {
3105c87c5fbaSopenharmony_ci    /* Too many retries */
3106c87c5fbaSopenharmony_ci    coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
3107c87c5fbaSopenharmony_ci    return 1;
3108c87c5fbaSopenharmony_ci  }
3109c87c5fbaSopenharmony_ci  return 0;
3110c87c5fbaSopenharmony_ci}
3111c87c5fbaSopenharmony_ci
3112c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
3113c87c5fbaSopenharmony_ciint
3114c87c5fbaSopenharmony_cicoap_dtls_hello(coap_session_t *session,
3115c87c5fbaSopenharmony_ci                const uint8_t *data, size_t data_len) {
3116c87c5fbaSopenharmony_ci  coap_dtls_context_t *dtls = &((coap_openssl_context_t *)session->context->dtls_context)->dtls;
3117c87c5fbaSopenharmony_ci  coap_ssl_data *ssl_data;
3118c87c5fbaSopenharmony_ci  int r;
3119c87c5fbaSopenharmony_ci
3120c87c5fbaSopenharmony_ci  SSL_set_mtu(dtls->ssl, (long)session->mtu);
3121c87c5fbaSopenharmony_ci  ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(dtls->ssl));
3122c87c5fbaSopenharmony_ci  assert(ssl_data != NULL);
3123c87c5fbaSopenharmony_ci  if (ssl_data->pdu_len) {
3124c87c5fbaSopenharmony_ci    coap_log_err("** %s: Previous data not read %u bytes\n",
3125c87c5fbaSopenharmony_ci                 coap_session_str(session), ssl_data->pdu_len);
3126c87c5fbaSopenharmony_ci  }
3127c87c5fbaSopenharmony_ci  ssl_data->session = session;
3128c87c5fbaSopenharmony_ci  ssl_data->pdu = data;
3129c87c5fbaSopenharmony_ci  ssl_data->pdu_len = (unsigned)data_len;
3130c87c5fbaSopenharmony_ci  r = DTLSv1_listen(dtls->ssl, dtls->bio_addr);
3131c87c5fbaSopenharmony_ci  if (r <= 0) {
3132c87c5fbaSopenharmony_ci    int err = SSL_get_error(dtls->ssl, r);
3133c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3134c87c5fbaSopenharmony_ci      /* Got a ClientHello, sent-out a VerifyRequest */
3135c87c5fbaSopenharmony_ci      r = 0;
3136c87c5fbaSopenharmony_ci    }
3137c87c5fbaSopenharmony_ci  } else {
3138c87c5fbaSopenharmony_ci    /* Got a valid answer to a VerifyRequest */
3139c87c5fbaSopenharmony_ci    r = 1;
3140c87c5fbaSopenharmony_ci  }
3141c87c5fbaSopenharmony_ci
3142c87c5fbaSopenharmony_ci  /*
3143c87c5fbaSopenharmony_ci   * Cannot check if data is left on the stack in error as DTLSv1_listen()
3144c87c5fbaSopenharmony_ci   * only does a 'peek' read of the incoming data.
3145c87c5fbaSopenharmony_ci   *
3146c87c5fbaSopenharmony_ci   */
3147c87c5fbaSopenharmony_ci  return r;
3148c87c5fbaSopenharmony_ci}
3149c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
3150c87c5fbaSopenharmony_ci
3151c87c5fbaSopenharmony_ciint
3152c87c5fbaSopenharmony_cicoap_dtls_receive(coap_session_t *session, const uint8_t *data, size_t data_len) {
3153c87c5fbaSopenharmony_ci  coap_ssl_data *ssl_data;
3154c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3155c87c5fbaSopenharmony_ci  int r;
3156c87c5fbaSopenharmony_ci
3157c87c5fbaSopenharmony_ci  assert(ssl != NULL);
3158c87c5fbaSopenharmony_ci
3159c87c5fbaSopenharmony_ci  int in_init = SSL_in_init(ssl);
3160c87c5fbaSopenharmony_ci  uint8_t pdu[COAP_RXBUFFER_SIZE];
3161c87c5fbaSopenharmony_ci  ssl_data = (coap_ssl_data *)BIO_get_data(SSL_get_rbio(ssl));
3162c87c5fbaSopenharmony_ci  assert(ssl_data != NULL);
3163c87c5fbaSopenharmony_ci
3164c87c5fbaSopenharmony_ci  if (ssl_data->pdu_len) {
3165c87c5fbaSopenharmony_ci    coap_log_err("** %s: Previous data not read %u bytes\n",
3166c87c5fbaSopenharmony_ci                 coap_session_str(session), ssl_data->pdu_len);
3167c87c5fbaSopenharmony_ci  }
3168c87c5fbaSopenharmony_ci  ssl_data->pdu = data;
3169c87c5fbaSopenharmony_ci  ssl_data->pdu_len = (unsigned)data_len;
3170c87c5fbaSopenharmony_ci
3171c87c5fbaSopenharmony_ci  session->dtls_event = -1;
3172c87c5fbaSopenharmony_ci  r = SSL_read(ssl, pdu, (int)sizeof(pdu));
3173c87c5fbaSopenharmony_ci  if (r > 0) {
3174c87c5fbaSopenharmony_ci    r =  coap_handle_dgram(session->context, session, pdu, (size_t)r);
3175c87c5fbaSopenharmony_ci    goto finished;
3176c87c5fbaSopenharmony_ci  } else {
3177c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
3178c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3179c87c5fbaSopenharmony_ci      if (in_init && SSL_is_init_finished(ssl)) {
3180c87c5fbaSopenharmony_ci        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3181c87c5fbaSopenharmony_ci                      coap_session_str(session), SSL_get_cipher_name(ssl));
3182c87c5fbaSopenharmony_ci        coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3183c87c5fbaSopenharmony_ci        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3184c87c5fbaSopenharmony_ci      }
3185c87c5fbaSopenharmony_ci      r = 0;
3186c87c5fbaSopenharmony_ci    } else {
3187c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_ZERO_RETURN)        /* Got a close notify alert from the remote side */
3188c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3189c87c5fbaSopenharmony_ci      else if (err == SSL_ERROR_SSL)
3190c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3191c87c5fbaSopenharmony_ci      r = -1;
3192c87c5fbaSopenharmony_ci    }
3193c87c5fbaSopenharmony_ci    if (session->dtls_event >= 0) {
3194c87c5fbaSopenharmony_ci      /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
3195c87c5fbaSopenharmony_ci      if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3196c87c5fbaSopenharmony_ci        coap_handle_event(session->context, session->dtls_event, session);
3197c87c5fbaSopenharmony_ci      if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3198c87c5fbaSopenharmony_ci          session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3199c87c5fbaSopenharmony_ci        coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
3200c87c5fbaSopenharmony_ci        ssl_data = NULL;
3201c87c5fbaSopenharmony_ci        r = -1;
3202c87c5fbaSopenharmony_ci      }
3203c87c5fbaSopenharmony_ci    }
3204c87c5fbaSopenharmony_ci  }
3205c87c5fbaSopenharmony_ci
3206c87c5fbaSopenharmony_cifinished:
3207c87c5fbaSopenharmony_ci  if (ssl_data && ssl_data->pdu_len) {
3208c87c5fbaSopenharmony_ci    /* pdu data is held on stack which will not stay there */
3209c87c5fbaSopenharmony_ci    coap_log_debug("coap_dtls_receive: ret %d: remaining data %u\n", r, ssl_data->pdu_len);
3210c87c5fbaSopenharmony_ci    ssl_data->pdu_len = 0;
3211c87c5fbaSopenharmony_ci    ssl_data->pdu = NULL;
3212c87c5fbaSopenharmony_ci  }
3213c87c5fbaSopenharmony_ci  if (r > 0) {
3214c87c5fbaSopenharmony_ci    coap_log_debug("*  %s: dtls:  recv %4d bytes\n",
3215c87c5fbaSopenharmony_ci                   coap_session_str(session), r);
3216c87c5fbaSopenharmony_ci  }
3217c87c5fbaSopenharmony_ci  return r;
3218c87c5fbaSopenharmony_ci}
3219c87c5fbaSopenharmony_ci
3220c87c5fbaSopenharmony_ciunsigned int
3221c87c5fbaSopenharmony_cicoap_dtls_get_overhead(coap_session_t *session) {
3222c87c5fbaSopenharmony_ci  unsigned int overhead = 37;
3223c87c5fbaSopenharmony_ci  const SSL_CIPHER *s_ciph = NULL;
3224c87c5fbaSopenharmony_ci  if (session->tls != NULL)
3225c87c5fbaSopenharmony_ci    s_ciph = SSL_get_current_cipher(session->tls);
3226c87c5fbaSopenharmony_ci  if (s_ciph) {
3227c87c5fbaSopenharmony_ci    unsigned int ivlen, maclen, blocksize = 1, pad = 0;
3228c87c5fbaSopenharmony_ci
3229c87c5fbaSopenharmony_ci    const EVP_CIPHER *e_ciph;
3230c87c5fbaSopenharmony_ci    const EVP_MD *e_md;
3231c87c5fbaSopenharmony_ci    char cipher[128];
3232c87c5fbaSopenharmony_ci
3233c87c5fbaSopenharmony_ci    e_ciph = EVP_get_cipherbynid(SSL_CIPHER_get_cipher_nid(s_ciph));
3234c87c5fbaSopenharmony_ci
3235c87c5fbaSopenharmony_ci    switch (EVP_CIPHER_mode(e_ciph)) {
3236c87c5fbaSopenharmony_ci    case EVP_CIPH_GCM_MODE:
3237c87c5fbaSopenharmony_ci      ivlen = EVP_GCM_TLS_EXPLICIT_IV_LEN;
3238c87c5fbaSopenharmony_ci      maclen = EVP_GCM_TLS_TAG_LEN;
3239c87c5fbaSopenharmony_ci      break;
3240c87c5fbaSopenharmony_ci
3241c87c5fbaSopenharmony_ci    case EVP_CIPH_CCM_MODE:
3242c87c5fbaSopenharmony_ci      ivlen = EVP_CCM_TLS_EXPLICIT_IV_LEN;
3243c87c5fbaSopenharmony_ci      SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3244c87c5fbaSopenharmony_ci      if (strstr(cipher, "CCM8"))
3245c87c5fbaSopenharmony_ci        maclen = 8;
3246c87c5fbaSopenharmony_ci      else
3247c87c5fbaSopenharmony_ci        maclen = 16;
3248c87c5fbaSopenharmony_ci      break;
3249c87c5fbaSopenharmony_ci
3250c87c5fbaSopenharmony_ci    case EVP_CIPH_CBC_MODE:
3251c87c5fbaSopenharmony_ci      e_md = EVP_get_digestbynid(SSL_CIPHER_get_digest_nid(s_ciph));
3252c87c5fbaSopenharmony_ci      blocksize = EVP_CIPHER_block_size(e_ciph);
3253c87c5fbaSopenharmony_ci      ivlen = EVP_CIPHER_iv_length(e_ciph);
3254c87c5fbaSopenharmony_ci      pad = 1;
3255c87c5fbaSopenharmony_ci      maclen = EVP_MD_size(e_md);
3256c87c5fbaSopenharmony_ci      break;
3257c87c5fbaSopenharmony_ci
3258c87c5fbaSopenharmony_ci    case EVP_CIPH_STREAM_CIPHER:
3259c87c5fbaSopenharmony_ci      /* Seen with PSK-CHACHA20-POLY1305 */
3260c87c5fbaSopenharmony_ci      ivlen = 8;
3261c87c5fbaSopenharmony_ci      maclen = 8;
3262c87c5fbaSopenharmony_ci      break;
3263c87c5fbaSopenharmony_ci
3264c87c5fbaSopenharmony_ci    default:
3265c87c5fbaSopenharmony_ci      SSL_CIPHER_description(s_ciph, cipher, sizeof(cipher));
3266c87c5fbaSopenharmony_ci      coap_log_warn("Unknown overhead for DTLS with cipher %s\n",
3267c87c5fbaSopenharmony_ci                    cipher);
3268c87c5fbaSopenharmony_ci      ivlen = 8;
3269c87c5fbaSopenharmony_ci      maclen = 16;
3270c87c5fbaSopenharmony_ci      break;
3271c87c5fbaSopenharmony_ci    }
3272c87c5fbaSopenharmony_ci    overhead = DTLS1_RT_HEADER_LENGTH + ivlen + maclen + blocksize - 1 + pad;
3273c87c5fbaSopenharmony_ci  }
3274c87c5fbaSopenharmony_ci  return overhead;
3275c87c5fbaSopenharmony_ci}
3276c87c5fbaSopenharmony_ci
3277c87c5fbaSopenharmony_ci#if !COAP_DISABLE_TCP
3278c87c5fbaSopenharmony_ci#if COAP_CLIENT_SUPPORT
3279c87c5fbaSopenharmony_civoid *
3280c87c5fbaSopenharmony_cicoap_tls_new_client_session(coap_session_t *session) {
3281c87c5fbaSopenharmony_ci  BIO *bio = NULL;
3282c87c5fbaSopenharmony_ci  SSL *ssl = NULL;
3283c87c5fbaSopenharmony_ci  int r;
3284c87c5fbaSopenharmony_ci  coap_openssl_context_t *context = ((coap_openssl_context_t *)session->context->dtls_context);
3285c87c5fbaSopenharmony_ci  coap_tls_context_t *tls = &context->tls;
3286c87c5fbaSopenharmony_ci
3287c87c5fbaSopenharmony_ci  ssl = SSL_new(tls->ctx);
3288c87c5fbaSopenharmony_ci  if (!ssl)
3289c87c5fbaSopenharmony_ci    goto error;
3290c87c5fbaSopenharmony_ci  bio = BIO_new(tls->meth);
3291c87c5fbaSopenharmony_ci  if (!bio)
3292c87c5fbaSopenharmony_ci    goto error;
3293c87c5fbaSopenharmony_ci  BIO_set_data(bio, session);
3294c87c5fbaSopenharmony_ci  SSL_set_bio(ssl, bio, bio);
3295c87c5fbaSopenharmony_ci  SSL_set_app_data(ssl, session);
3296c87c5fbaSopenharmony_ci
3297c87c5fbaSopenharmony_ci  if (!setup_client_ssl_session(session, ssl))
3298c87c5fbaSopenharmony_ci    return 0;
3299c87c5fbaSopenharmony_ci
3300c87c5fbaSopenharmony_ci  r = SSL_connect(ssl);
3301c87c5fbaSopenharmony_ci  if (r == -1) {
3302c87c5fbaSopenharmony_ci    int ret = SSL_get_error(ssl, r);
3303c87c5fbaSopenharmony_ci    if (ret != SSL_ERROR_WANT_READ && ret != SSL_ERROR_WANT_WRITE)
3304c87c5fbaSopenharmony_ci      r = 0;
3305c87c5fbaSopenharmony_ci    if (ret == SSL_ERROR_WANT_READ)
3306c87c5fbaSopenharmony_ci      session->sock.flags |= COAP_SOCKET_WANT_READ;
3307c87c5fbaSopenharmony_ci    if (ret == SSL_ERROR_WANT_WRITE) {
3308c87c5fbaSopenharmony_ci      session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3309c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT
3310c87c5fbaSopenharmony_ci      coap_epoll_ctl_mod(&session->sock,
3311c87c5fbaSopenharmony_ci                         EPOLLOUT |
3312c87c5fbaSopenharmony_ci                         ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3313c87c5fbaSopenharmony_ci                          EPOLLIN : 0),
3314c87c5fbaSopenharmony_ci                         __func__);
3315c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */
3316c87c5fbaSopenharmony_ci    }
3317c87c5fbaSopenharmony_ci  }
3318c87c5fbaSopenharmony_ci
3319c87c5fbaSopenharmony_ci  if (r == 0)
3320c87c5fbaSopenharmony_ci    goto error;
3321c87c5fbaSopenharmony_ci
3322c87c5fbaSopenharmony_ci  session->tls = ssl;
3323c87c5fbaSopenharmony_ci  if (SSL_is_init_finished(ssl)) {
3324c87c5fbaSopenharmony_ci    coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3325c87c5fbaSopenharmony_ci    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3326c87c5fbaSopenharmony_ci  }
3327c87c5fbaSopenharmony_ci
3328c87c5fbaSopenharmony_ci  return ssl;
3329c87c5fbaSopenharmony_ci
3330c87c5fbaSopenharmony_cierror:
3331c87c5fbaSopenharmony_ci  if (ssl)
3332c87c5fbaSopenharmony_ci    SSL_free(ssl);
3333c87c5fbaSopenharmony_ci  return NULL;
3334c87c5fbaSopenharmony_ci}
3335c87c5fbaSopenharmony_ci#endif /* COAP_CLIENT_SUPPORT */
3336c87c5fbaSopenharmony_ci
3337c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
3338c87c5fbaSopenharmony_civoid *
3339c87c5fbaSopenharmony_cicoap_tls_new_server_session(coap_session_t *session) {
3340c87c5fbaSopenharmony_ci  BIO *bio = NULL;
3341c87c5fbaSopenharmony_ci  SSL *ssl = NULL;
3342c87c5fbaSopenharmony_ci  coap_tls_context_t *tls = &((coap_openssl_context_t *)session->context->dtls_context)->tls;
3343c87c5fbaSopenharmony_ci  int r;
3344c87c5fbaSopenharmony_ci  const coap_bin_const_t *psk_hint;
3345c87c5fbaSopenharmony_ci
3346c87c5fbaSopenharmony_ci  ssl = SSL_new(tls->ctx);
3347c87c5fbaSopenharmony_ci  if (!ssl)
3348c87c5fbaSopenharmony_ci    goto error;
3349c87c5fbaSopenharmony_ci  bio = BIO_new(tls->meth);
3350c87c5fbaSopenharmony_ci  if (!bio)
3351c87c5fbaSopenharmony_ci    goto error;
3352c87c5fbaSopenharmony_ci  BIO_set_data(bio, session);
3353c87c5fbaSopenharmony_ci  SSL_set_bio(ssl, bio, bio);
3354c87c5fbaSopenharmony_ci  SSL_set_app_data(ssl, session);
3355c87c5fbaSopenharmony_ci
3356c87c5fbaSopenharmony_ci  psk_hint = coap_get_session_server_psk_hint(session);
3357c87c5fbaSopenharmony_ci  if (psk_hint != NULL && psk_hint->length) {
3358c87c5fbaSopenharmony_ci    char *hint = OPENSSL_malloc(psk_hint->length + 1);
3359c87c5fbaSopenharmony_ci
3360c87c5fbaSopenharmony_ci    if (hint) {
3361c87c5fbaSopenharmony_ci      memcpy(hint, psk_hint->s, psk_hint->length);
3362c87c5fbaSopenharmony_ci      hint[psk_hint->length] = '\000';
3363c87c5fbaSopenharmony_ci      SSL_use_psk_identity_hint(ssl, hint);
3364c87c5fbaSopenharmony_ci      OPENSSL_free(hint);
3365c87c5fbaSopenharmony_ci    } else {
3366c87c5fbaSopenharmony_ci      coap_log_warn("hint malloc failure\n");
3367c87c5fbaSopenharmony_ci    }
3368c87c5fbaSopenharmony_ci  }
3369c87c5fbaSopenharmony_ci
3370c87c5fbaSopenharmony_ci  r = SSL_accept(ssl);
3371c87c5fbaSopenharmony_ci  if (r == -1) {
3372c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
3373c87c5fbaSopenharmony_ci    if (err != SSL_ERROR_WANT_READ && err != SSL_ERROR_WANT_WRITE)
3374c87c5fbaSopenharmony_ci      r = 0;
3375c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ)
3376c87c5fbaSopenharmony_ci      session->sock.flags |= COAP_SOCKET_WANT_READ;
3377c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_WRITE) {
3378c87c5fbaSopenharmony_ci      session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3379c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT
3380c87c5fbaSopenharmony_ci      coap_epoll_ctl_mod(&session->sock,
3381c87c5fbaSopenharmony_ci                         EPOLLOUT |
3382c87c5fbaSopenharmony_ci                         ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3383c87c5fbaSopenharmony_ci                          EPOLLIN : 0),
3384c87c5fbaSopenharmony_ci                         __func__);
3385c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */
3386c87c5fbaSopenharmony_ci    }
3387c87c5fbaSopenharmony_ci  }
3388c87c5fbaSopenharmony_ci
3389c87c5fbaSopenharmony_ci  if (r == 0)
3390c87c5fbaSopenharmony_ci    goto error;
3391c87c5fbaSopenharmony_ci
3392c87c5fbaSopenharmony_ci  session->tls = ssl;
3393c87c5fbaSopenharmony_ci  if (SSL_is_init_finished(ssl)) {
3394c87c5fbaSopenharmony_ci    coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3395c87c5fbaSopenharmony_ci    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3396c87c5fbaSopenharmony_ci  }
3397c87c5fbaSopenharmony_ci
3398c87c5fbaSopenharmony_ci  return ssl;
3399c87c5fbaSopenharmony_ci
3400c87c5fbaSopenharmony_cierror:
3401c87c5fbaSopenharmony_ci  if (ssl)
3402c87c5fbaSopenharmony_ci    SSL_free(ssl);
3403c87c5fbaSopenharmony_ci  return NULL;
3404c87c5fbaSopenharmony_ci}
3405c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
3406c87c5fbaSopenharmony_ci
3407c87c5fbaSopenharmony_civoid
3408c87c5fbaSopenharmony_cicoap_tls_free_session(coap_session_t *session) {
3409c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3410c87c5fbaSopenharmony_ci  if (ssl) {
3411c87c5fbaSopenharmony_ci    if (!SSL_in_init(ssl) && !(SSL_get_shutdown(ssl) & SSL_SENT_SHUTDOWN)) {
3412c87c5fbaSopenharmony_ci      int r = SSL_shutdown(ssl);
3413c87c5fbaSopenharmony_ci      if (r == 0)
3414c87c5fbaSopenharmony_ci        r = SSL_shutdown(ssl);
3415c87c5fbaSopenharmony_ci    }
3416c87c5fbaSopenharmony_ci    SSL_free(ssl);
3417c87c5fbaSopenharmony_ci    session->tls = NULL;
3418c87c5fbaSopenharmony_ci    if (session->context)
3419c87c5fbaSopenharmony_ci      coap_handle_event(session->context, COAP_EVENT_DTLS_CLOSED, session);
3420c87c5fbaSopenharmony_ci  }
3421c87c5fbaSopenharmony_ci}
3422c87c5fbaSopenharmony_ci
3423c87c5fbaSopenharmony_ci/*
3424c87c5fbaSopenharmony_ci * strm
3425c87c5fbaSopenharmony_ci * return +ve Number of bytes written.
3426c87c5fbaSopenharmony_ci *         -1 Error (error in errno).
3427c87c5fbaSopenharmony_ci */
3428c87c5fbaSopenharmony_cissize_t
3429c87c5fbaSopenharmony_cicoap_tls_write(coap_session_t *session, const uint8_t *data, size_t data_len) {
3430c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3431c87c5fbaSopenharmony_ci  int r, in_init;
3432c87c5fbaSopenharmony_ci
3433c87c5fbaSopenharmony_ci  if (ssl == NULL)
3434c87c5fbaSopenharmony_ci    return -1;
3435c87c5fbaSopenharmony_ci
3436c87c5fbaSopenharmony_ci  in_init = !SSL_is_init_finished(ssl);
3437c87c5fbaSopenharmony_ci  session->dtls_event = -1;
3438c87c5fbaSopenharmony_ci  r = SSL_write(ssl, data, (int)data_len);
3439c87c5fbaSopenharmony_ci
3440c87c5fbaSopenharmony_ci  if (r <= 0) {
3441c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
3442c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3443c87c5fbaSopenharmony_ci      if (in_init && SSL_is_init_finished(ssl)) {
3444c87c5fbaSopenharmony_ci        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3445c87c5fbaSopenharmony_ci                      coap_session_str(session), SSL_get_cipher_name(ssl));
3446c87c5fbaSopenharmony_ci        coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3447c87c5fbaSopenharmony_ci        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3448c87c5fbaSopenharmony_ci      }
3449c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_WANT_READ)
3450c87c5fbaSopenharmony_ci        session->sock.flags |= COAP_SOCKET_WANT_READ;
3451c87c5fbaSopenharmony_ci      else if (err == SSL_ERROR_WANT_WRITE) {
3452c87c5fbaSopenharmony_ci        session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3453c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT
3454c87c5fbaSopenharmony_ci        coap_epoll_ctl_mod(&session->sock,
3455c87c5fbaSopenharmony_ci                           EPOLLOUT |
3456c87c5fbaSopenharmony_ci                           ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3457c87c5fbaSopenharmony_ci                            EPOLLIN : 0),
3458c87c5fbaSopenharmony_ci                           __func__);
3459c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */
3460c87c5fbaSopenharmony_ci      }
3461c87c5fbaSopenharmony_ci      r = 0;
3462c87c5fbaSopenharmony_ci    } else {
3463c87c5fbaSopenharmony_ci      coap_log_info("***%s: coap_tls_write: cannot send PDU\n",
3464c87c5fbaSopenharmony_ci                    coap_session_str(session));
3465c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_ZERO_RETURN)
3466c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3467c87c5fbaSopenharmony_ci      else if (err == SSL_ERROR_SSL)
3468c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3469c87c5fbaSopenharmony_ci      r = -1;
3470c87c5fbaSopenharmony_ci    }
3471c87c5fbaSopenharmony_ci  } else if (in_init && SSL_is_init_finished(ssl)) {
3472c87c5fbaSopenharmony_ci    coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3473c87c5fbaSopenharmony_ci                  coap_session_str(session), SSL_get_cipher_name(ssl));
3474c87c5fbaSopenharmony_ci    coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3475c87c5fbaSopenharmony_ci    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3476c87c5fbaSopenharmony_ci  }
3477c87c5fbaSopenharmony_ci
3478c87c5fbaSopenharmony_ci  if (session->dtls_event >= 0) {
3479c87c5fbaSopenharmony_ci    /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
3480c87c5fbaSopenharmony_ci    if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3481c87c5fbaSopenharmony_ci      coap_handle_event(session->context, session->dtls_event, session);
3482c87c5fbaSopenharmony_ci    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3483c87c5fbaSopenharmony_ci        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3484c87c5fbaSopenharmony_ci      coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
3485c87c5fbaSopenharmony_ci      r = -1;
3486c87c5fbaSopenharmony_ci    }
3487c87c5fbaSopenharmony_ci  }
3488c87c5fbaSopenharmony_ci
3489c87c5fbaSopenharmony_ci  if (r >= 0) {
3490c87c5fbaSopenharmony_ci    if (r == (ssize_t)data_len)
3491c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: tls:   sent %4d bytes\n",
3492c87c5fbaSopenharmony_ci                     coap_session_str(session), r);
3493c87c5fbaSopenharmony_ci    else
3494c87c5fbaSopenharmony_ci      coap_log_debug("*  %s: tls:   sent %4d of %4zd bytes\n",
3495c87c5fbaSopenharmony_ci                     coap_session_str(session), r, data_len);
3496c87c5fbaSopenharmony_ci  }
3497c87c5fbaSopenharmony_ci  return r;
3498c87c5fbaSopenharmony_ci}
3499c87c5fbaSopenharmony_ci
3500c87c5fbaSopenharmony_ci/*
3501c87c5fbaSopenharmony_ci * strm
3502c87c5fbaSopenharmony_ci * return >=0 Number of bytes read.
3503c87c5fbaSopenharmony_ci *         -1 Error (error in errno).
3504c87c5fbaSopenharmony_ci */
3505c87c5fbaSopenharmony_cissize_t
3506c87c5fbaSopenharmony_cicoap_tls_read(coap_session_t *session, uint8_t *data, size_t data_len) {
3507c87c5fbaSopenharmony_ci  SSL *ssl = (SSL *)session->tls;
3508c87c5fbaSopenharmony_ci  int r, in_init;
3509c87c5fbaSopenharmony_ci
3510c87c5fbaSopenharmony_ci  if (ssl == NULL) {
3511c87c5fbaSopenharmony_ci    errno = ENXIO;
3512c87c5fbaSopenharmony_ci    return -1;
3513c87c5fbaSopenharmony_ci  }
3514c87c5fbaSopenharmony_ci
3515c87c5fbaSopenharmony_ci  in_init = !SSL_is_init_finished(ssl);
3516c87c5fbaSopenharmony_ci  session->dtls_event = -1;
3517c87c5fbaSopenharmony_ci  r = SSL_read(ssl, data, (int)data_len);
3518c87c5fbaSopenharmony_ci  if (r <= 0) {
3519c87c5fbaSopenharmony_ci    int err = SSL_get_error(ssl, r);
3520c87c5fbaSopenharmony_ci    if (err == SSL_ERROR_WANT_READ || err == SSL_ERROR_WANT_WRITE) {
3521c87c5fbaSopenharmony_ci      if (in_init && SSL_is_init_finished(ssl)) {
3522c87c5fbaSopenharmony_ci        coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3523c87c5fbaSopenharmony_ci                      coap_session_str(session), SSL_get_cipher_name(ssl));
3524c87c5fbaSopenharmony_ci        coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3525c87c5fbaSopenharmony_ci        session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3526c87c5fbaSopenharmony_ci      }
3527c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_WANT_READ)
3528c87c5fbaSopenharmony_ci        session->sock.flags |= COAP_SOCKET_WANT_READ;
3529c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_WANT_WRITE) {
3530c87c5fbaSopenharmony_ci        session->sock.flags |= COAP_SOCKET_WANT_WRITE;
3531c87c5fbaSopenharmony_ci#ifdef COAP_EPOLL_SUPPORT
3532c87c5fbaSopenharmony_ci        coap_epoll_ctl_mod(&session->sock,
3533c87c5fbaSopenharmony_ci                           EPOLLOUT |
3534c87c5fbaSopenharmony_ci                           ((session->sock.flags & COAP_SOCKET_WANT_READ) ?
3535c87c5fbaSopenharmony_ci                            EPOLLIN : 0),
3536c87c5fbaSopenharmony_ci                           __func__);
3537c87c5fbaSopenharmony_ci#endif /* COAP_EPOLL_SUPPORT */
3538c87c5fbaSopenharmony_ci      }
3539c87c5fbaSopenharmony_ci      r = 0;
3540c87c5fbaSopenharmony_ci    } else {
3541c87c5fbaSopenharmony_ci      if (err == SSL_ERROR_ZERO_RETURN)        /* Got a close notify alert from the remote side */
3542c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_CLOSED;
3543c87c5fbaSopenharmony_ci      else if (err == SSL_ERROR_SSL)
3544c87c5fbaSopenharmony_ci        session->dtls_event = COAP_EVENT_DTLS_ERROR;
3545c87c5fbaSopenharmony_ci      r = -1;
3546c87c5fbaSopenharmony_ci    }
3547c87c5fbaSopenharmony_ci  } else if (in_init && SSL_is_init_finished(ssl)) {
3548c87c5fbaSopenharmony_ci    coap_dtls_log(COAP_LOG_INFO, "*  %s: Using cipher: %s\n",
3549c87c5fbaSopenharmony_ci                  coap_session_str(session), SSL_get_cipher_name(ssl));
3550c87c5fbaSopenharmony_ci    coap_handle_event(session->context, COAP_EVENT_DTLS_CONNECTED, session);
3551c87c5fbaSopenharmony_ci    session->sock.lfunc[COAP_LAYER_TLS].l_establish(session);
3552c87c5fbaSopenharmony_ci  }
3553c87c5fbaSopenharmony_ci
3554c87c5fbaSopenharmony_ci  if (session->dtls_event >= 0) {
3555c87c5fbaSopenharmony_ci    /* COAP_EVENT_DTLS_CLOSED event reported in coap_session_disconnected() */
3556c87c5fbaSopenharmony_ci    if (session->dtls_event != COAP_EVENT_DTLS_CLOSED)
3557c87c5fbaSopenharmony_ci      coap_handle_event(session->context, session->dtls_event, session);
3558c87c5fbaSopenharmony_ci    if (session->dtls_event == COAP_EVENT_DTLS_ERROR ||
3559c87c5fbaSopenharmony_ci        session->dtls_event == COAP_EVENT_DTLS_CLOSED) {
3560c87c5fbaSopenharmony_ci      coap_session_disconnected(session, COAP_NACK_TLS_FAILED);
3561c87c5fbaSopenharmony_ci      r = -1;
3562c87c5fbaSopenharmony_ci    }
3563c87c5fbaSopenharmony_ci  }
3564c87c5fbaSopenharmony_ci
3565c87c5fbaSopenharmony_ci  if (r > 0) {
3566c87c5fbaSopenharmony_ci    coap_log_debug("*  %s: tls:   recv %4d bytes\n",
3567c87c5fbaSopenharmony_ci                   coap_session_str(session), r);
3568c87c5fbaSopenharmony_ci  }
3569c87c5fbaSopenharmony_ci  return r;
3570c87c5fbaSopenharmony_ci}
3571c87c5fbaSopenharmony_ci#endif /* !COAP_DISABLE_TCP */
3572c87c5fbaSopenharmony_ci
3573c87c5fbaSopenharmony_ci#if COAP_SERVER_SUPPORT
3574c87c5fbaSopenharmony_cicoap_digest_ctx_t *
3575c87c5fbaSopenharmony_cicoap_digest_setup(void) {
3576c87c5fbaSopenharmony_ci  EVP_MD_CTX *digest_ctx = EVP_MD_CTX_new();
3577c87c5fbaSopenharmony_ci
3578c87c5fbaSopenharmony_ci  if (digest_ctx) {
3579c87c5fbaSopenharmony_ci    EVP_DigestInit_ex(digest_ctx, EVP_sha256(), NULL);
3580c87c5fbaSopenharmony_ci  }
3581c87c5fbaSopenharmony_ci  return digest_ctx;
3582c87c5fbaSopenharmony_ci}
3583c87c5fbaSopenharmony_ci
3584c87c5fbaSopenharmony_civoid
3585c87c5fbaSopenharmony_cicoap_digest_free(coap_digest_ctx_t *digest_ctx) {
3586c87c5fbaSopenharmony_ci  EVP_MD_CTX_free(digest_ctx);
3587c87c5fbaSopenharmony_ci}
3588c87c5fbaSopenharmony_ci
3589c87c5fbaSopenharmony_ciint
3590c87c5fbaSopenharmony_cicoap_digest_update(coap_digest_ctx_t *digest_ctx,
3591c87c5fbaSopenharmony_ci                   const uint8_t *data,
3592c87c5fbaSopenharmony_ci                   size_t data_len) {
3593c87c5fbaSopenharmony_ci  return EVP_DigestUpdate(digest_ctx, data, data_len);
3594c87c5fbaSopenharmony_ci}
3595c87c5fbaSopenharmony_ci
3596c87c5fbaSopenharmony_ciint
3597c87c5fbaSopenharmony_cicoap_digest_final(coap_digest_ctx_t *digest_ctx,
3598c87c5fbaSopenharmony_ci                  coap_digest_t *digest_buffer) {
3599c87c5fbaSopenharmony_ci  unsigned int size = sizeof(coap_digest_t);
3600c87c5fbaSopenharmony_ci  int ret = EVP_DigestFinal_ex(digest_ctx, (uint8_t *)digest_buffer, &size);
3601c87c5fbaSopenharmony_ci
3602c87c5fbaSopenharmony_ci  coap_digest_free(digest_ctx);
3603c87c5fbaSopenharmony_ci  return ret;
3604c87c5fbaSopenharmony_ci}
3605c87c5fbaSopenharmony_ci#endif /* COAP_SERVER_SUPPORT */
3606c87c5fbaSopenharmony_ci
3607c87c5fbaSopenharmony_ci#if COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT
3608c87c5fbaSopenharmony_cistatic void
3609c87c5fbaSopenharmony_cicoap_crypto_output_errors(const char *prefix) {
3610c87c5fbaSopenharmony_ci#if COAP_MAX_LOGGING_LEVEL < _COAP_LOG_WARN
3611c87c5fbaSopenharmony_ci  (void)prefix;
3612c87c5fbaSopenharmony_ci#else /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
3613c87c5fbaSopenharmony_ci  unsigned long e;
3614c87c5fbaSopenharmony_ci
3615c87c5fbaSopenharmony_ci  while ((e = ERR_get_error()))
3616c87c5fbaSopenharmony_ci    coap_log_warn("%s: %s%s\n",
3617c87c5fbaSopenharmony_ci                  prefix,
3618c87c5fbaSopenharmony_ci                  ERR_reason_error_string(e),
3619c87c5fbaSopenharmony_ci                  ssl_function_definition(e));
3620c87c5fbaSopenharmony_ci#endif /* COAP_MAX_LOGGING_LEVEL >= _COAP_LOG_WARN */
3621c87c5fbaSopenharmony_ci}
3622c87c5fbaSopenharmony_ci#endif /* COAP_WS_SUPPORT || COAP_OSCORE_SUPPORT */
3623c87c5fbaSopenharmony_ci
3624c87c5fbaSopenharmony_ci#if COAP_WS_SUPPORT
3625c87c5fbaSopenharmony_ci/*
3626c87c5fbaSopenharmony_ci * The struct hash_algs and the function get_hash_alg() are used to
3627c87c5fbaSopenharmony_ci * determine which hash type to use for creating the required hash object.
3628c87c5fbaSopenharmony_ci */
3629c87c5fbaSopenharmony_cistatic struct hash_algs {
3630c87c5fbaSopenharmony_ci  cose_alg_t alg;
3631c87c5fbaSopenharmony_ci  const EVP_MD *(*get_hash)(void);
3632c87c5fbaSopenharmony_ci  size_t length; /* in bytes */
3633c87c5fbaSopenharmony_ci} hashs[] = {
3634c87c5fbaSopenharmony_ci  {COSE_ALGORITHM_SHA_1, EVP_sha1, 20},
3635c87c5fbaSopenharmony_ci  {COSE_ALGORITHM_SHA_256_64, EVP_sha256, 8},
3636c87c5fbaSopenharmony_ci  {COSE_ALGORITHM_SHA_256_256, EVP_sha256, 32},
3637c87c5fbaSopenharmony_ci  {COSE_ALGORITHM_SHA_512, EVP_sha512, 64},
3638c87c5fbaSopenharmony_ci};
3639c87c5fbaSopenharmony_ci
3640c87c5fbaSopenharmony_cistatic const EVP_MD *
3641c87c5fbaSopenharmony_ciget_hash_alg(cose_alg_t alg, size_t *length) {
3642c87c5fbaSopenharmony_ci  size_t idx;
3643c87c5fbaSopenharmony_ci
3644c87c5fbaSopenharmony_ci  for (idx = 0; idx < sizeof(hashs) / sizeof(struct hash_algs); idx++) {
3645c87c5fbaSopenharmony_ci    if (hashs[idx].alg == alg) {
3646c87c5fbaSopenharmony_ci      *length = hashs[idx].length;
3647c87c5fbaSopenharmony_ci      return hashs[idx].get_hash();
3648c87c5fbaSopenharmony_ci    }
3649c87c5fbaSopenharmony_ci  }
3650c87c5fbaSopenharmony_ci  coap_log_debug("get_hash_alg: COSE hash %d not supported\n", alg);
3651c87c5fbaSopenharmony_ci  return NULL;
3652c87c5fbaSopenharmony_ci}
3653c87c5fbaSopenharmony_ci
3654c87c5fbaSopenharmony_ciint
3655c87c5fbaSopenharmony_cicoap_crypto_hash(cose_alg_t alg,
3656c87c5fbaSopenharmony_ci                 const coap_bin_const_t *data,
3657c87c5fbaSopenharmony_ci                 coap_bin_const_t **hash) {
3658c87c5fbaSopenharmony_ci  unsigned int length;
3659c87c5fbaSopenharmony_ci  const EVP_MD *evp_md;
3660c87c5fbaSopenharmony_ci  EVP_MD_CTX *evp_ctx = NULL;
3661c87c5fbaSopenharmony_ci  coap_binary_t *dummy = NULL;
3662c87c5fbaSopenharmony_ci  size_t hash_length;
3663c87c5fbaSopenharmony_ci
3664c87c5fbaSopenharmony_ci  if ((evp_md = get_hash_alg(alg, &hash_length)) == NULL) {
3665c87c5fbaSopenharmony_ci    coap_log_debug("coap_crypto_hash: algorithm %d not supported\n", alg);
3666c87c5fbaSopenharmony_ci    return 0;
3667c87c5fbaSopenharmony_ci  }
3668c87c5fbaSopenharmony_ci  evp_ctx = EVP_MD_CTX_new();
3669c87c5fbaSopenharmony_ci  if (evp_ctx == NULL)
3670c87c5fbaSopenharmony_ci    goto error;
3671c87c5fbaSopenharmony_ci  if (EVP_DigestInit_ex(evp_ctx, evp_md, NULL) == 0)
3672c87c5fbaSopenharmony_ci    goto error;
3673c87c5fbaSopenharmony_ci  ;
3674c87c5fbaSopenharmony_ci  if (EVP_DigestUpdate(evp_ctx, data->s, data->length) == 0)
3675c87c5fbaSopenharmony_ci    goto error;
3676c87c5fbaSopenharmony_ci  ;
3677c87c5fbaSopenharmony_ci  dummy = coap_new_binary(EVP_MAX_MD_SIZE);
3678c87c5fbaSopenharmony_ci  if (dummy == NULL)
3679c87c5fbaSopenharmony_ci    goto error;
3680c87c5fbaSopenharmony_ci  if (EVP_DigestFinal_ex(evp_ctx, dummy->s, &length) == 0)
3681c87c5fbaSopenharmony_ci    goto error;
3682c87c5fbaSopenharmony_ci  dummy->length = length;
3683c87c5fbaSopenharmony_ci  if (hash_length < dummy->length)
3684c87c5fbaSopenharmony_ci    dummy->length = hash_length;
3685c87c5fbaSopenharmony_ci  *hash = (coap_bin_const_t *)(dummy);
3686c87c5fbaSopenharmony_ci  EVP_MD_CTX_free(evp_ctx);
3687c87c5fbaSopenharmony_ci  return 1;
3688c87c5fbaSopenharmony_ci
3689c87c5fbaSopenharmony_cierror:
3690c87c5fbaSopenharmony_ci  coap_crypto_output_errors("coap_crypto_hash");
3691c87c5fbaSopenharmony_ci  coap_delete_binary(dummy);
3692c87c5fbaSopenharmony_ci  if (evp_ctx)
3693c87c5fbaSopenharmony_ci    EVP_MD_CTX_free(evp_ctx);
3694c87c5fbaSopenharmony_ci  return 0;
3695c87c5fbaSopenharmony_ci}
3696c87c5fbaSopenharmony_ci#endif /* COAP_WS_SUPPORT */
3697c87c5fbaSopenharmony_ci
3698c87c5fbaSopenharmony_ci#if COAP_OSCORE_SUPPORT
3699c87c5fbaSopenharmony_ciint
3700c87c5fbaSopenharmony_cicoap_oscore_is_supported(void) {
3701c87c5fbaSopenharmony_ci  return 1;
3702c87c5fbaSopenharmony_ci}
3703c87c5fbaSopenharmony_ci
3704c87c5fbaSopenharmony_ci#include <openssl/evp.h>
3705c87c5fbaSopenharmony_ci#include <openssl/hmac.h>
3706c87c5fbaSopenharmony_ci
3707c87c5fbaSopenharmony_ci/*
3708c87c5fbaSopenharmony_ci * The struct cipher_algs and the function get_cipher_alg() are used to
3709c87c5fbaSopenharmony_ci * determine which cipher type to use for creating the required cipher
3710c87c5fbaSopenharmony_ci * suite object.
3711c87c5fbaSopenharmony_ci */
3712c87c5fbaSopenharmony_cistatic struct cipher_algs {
3713c87c5fbaSopenharmony_ci  cose_alg_t alg;
3714c87c5fbaSopenharmony_ci  const EVP_CIPHER *(*get_cipher)(void);
3715c87c5fbaSopenharmony_ci} ciphers[] = {{COSE_ALGORITHM_AES_CCM_16_64_128, EVP_aes_128_ccm},
3716c87c5fbaSopenharmony_ci  {COSE_ALGORITHM_AES_CCM_16_64_256, EVP_aes_256_ccm}
3717c87c5fbaSopenharmony_ci};
3718c87c5fbaSopenharmony_ci
3719c87c5fbaSopenharmony_cistatic const EVP_CIPHER *
3720c87c5fbaSopenharmony_ciget_cipher_alg(cose_alg_t alg) {
3721c87c5fbaSopenharmony_ci  size_t idx;
3722c87c5fbaSopenharmony_ci
3723c87c5fbaSopenharmony_ci  for (idx = 0; idx < sizeof(ciphers) / sizeof(struct cipher_algs); idx++) {
3724c87c5fbaSopenharmony_ci    if (ciphers[idx].alg == alg)
3725c87c5fbaSopenharmony_ci      return ciphers[idx].get_cipher();
3726c87c5fbaSopenharmony_ci  }
3727c87c5fbaSopenharmony_ci  coap_log_debug("get_cipher_alg: COSE cipher %d not supported\n", alg);
3728c87c5fbaSopenharmony_ci  return NULL;
3729c87c5fbaSopenharmony_ci}
3730c87c5fbaSopenharmony_ci
3731c87c5fbaSopenharmony_ci/*
3732c87c5fbaSopenharmony_ci * The struct hmac_algs and the function get_hmac_alg() are used to
3733c87c5fbaSopenharmony_ci * determine which hmac type to use for creating the required hmac
3734c87c5fbaSopenharmony_ci * suite object.
3735c87c5fbaSopenharmony_ci */
3736c87c5fbaSopenharmony_cistatic struct hmac_algs {
3737c87c5fbaSopenharmony_ci  cose_hmac_alg_t hmac_alg;
3738c87c5fbaSopenharmony_ci  const EVP_MD *(*get_hmac)(void);
3739c87c5fbaSopenharmony_ci} hmacs[] = {
3740c87c5fbaSopenharmony_ci  {COSE_HMAC_ALG_HMAC256_256, EVP_sha256},
3741c87c5fbaSopenharmony_ci  {COSE_HMAC_ALG_HMAC384_384, EVP_sha384},
3742c87c5fbaSopenharmony_ci  {COSE_HMAC_ALG_HMAC512_512, EVP_sha512},
3743c87c5fbaSopenharmony_ci};
3744c87c5fbaSopenharmony_ci
3745c87c5fbaSopenharmony_cistatic const EVP_MD *
3746c87c5fbaSopenharmony_ciget_hmac_alg(cose_hmac_alg_t hmac_alg) {
3747c87c5fbaSopenharmony_ci  size_t idx;
3748c87c5fbaSopenharmony_ci
3749c87c5fbaSopenharmony_ci  for (idx = 0; idx < sizeof(hmacs) / sizeof(struct hmac_algs); idx++) {
3750c87c5fbaSopenharmony_ci    if (hmacs[idx].hmac_alg == hmac_alg)
3751c87c5fbaSopenharmony_ci      return hmacs[idx].get_hmac();
3752c87c5fbaSopenharmony_ci  }
3753c87c5fbaSopenharmony_ci  coap_log_debug("get_hmac_alg: COSE HMAC %d not supported\n", hmac_alg);
3754c87c5fbaSopenharmony_ci  return NULL;
3755c87c5fbaSopenharmony_ci}
3756c87c5fbaSopenharmony_ci
3757c87c5fbaSopenharmony_ciint
3758c87c5fbaSopenharmony_cicoap_crypto_check_cipher_alg(cose_alg_t alg) {
3759c87c5fbaSopenharmony_ci  return get_cipher_alg(alg) != NULL;
3760c87c5fbaSopenharmony_ci}
3761c87c5fbaSopenharmony_ci
3762c87c5fbaSopenharmony_ciint
3763c87c5fbaSopenharmony_cicoap_crypto_check_hkdf_alg(cose_hkdf_alg_t hkdf_alg) {
3764c87c5fbaSopenharmony_ci  cose_hmac_alg_t hmac_alg;
3765c87c5fbaSopenharmony_ci
3766c87c5fbaSopenharmony_ci  if (!cose_get_hmac_alg_for_hkdf(hkdf_alg, &hmac_alg))
3767c87c5fbaSopenharmony_ci    return 0;
3768c87c5fbaSopenharmony_ci  return get_hmac_alg(hmac_alg) != NULL;
3769c87c5fbaSopenharmony_ci}
3770c87c5fbaSopenharmony_ci
3771c87c5fbaSopenharmony_ci#define C(Func)                                                                \
3772c87c5fbaSopenharmony_ci  if (1 != (Func)) {                                                           \
3773c87c5fbaSopenharmony_ci    goto error;                                                                \
3774c87c5fbaSopenharmony_ci  }
3775c87c5fbaSopenharmony_ci
3776c87c5fbaSopenharmony_ciint
3777c87c5fbaSopenharmony_cicoap_crypto_aead_encrypt(const coap_crypto_param_t *params,
3778c87c5fbaSopenharmony_ci                         coap_bin_const_t *data,
3779c87c5fbaSopenharmony_ci                         coap_bin_const_t *aad,
3780c87c5fbaSopenharmony_ci                         uint8_t *result,
3781c87c5fbaSopenharmony_ci                         size_t *max_result_len) {
3782c87c5fbaSopenharmony_ci  const EVP_CIPHER *cipher;
3783c87c5fbaSopenharmony_ci  const coap_crypto_aes_ccm_t *ccm;
3784c87c5fbaSopenharmony_ci  int tmp;
3785c87c5fbaSopenharmony_ci  int result_len = (int)(*max_result_len & INT_MAX);
3786c87c5fbaSopenharmony_ci
3787c87c5fbaSopenharmony_ci  if (data == NULL)
3788c87c5fbaSopenharmony_ci    return 0;
3789c87c5fbaSopenharmony_ci
3790c87c5fbaSopenharmony_ci  assert(params != NULL);
3791c87c5fbaSopenharmony_ci  if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
3792c87c5fbaSopenharmony_ci    return 0;
3793c87c5fbaSopenharmony_ci  }
3794c87c5fbaSopenharmony_ci
3795c87c5fbaSopenharmony_ci  /* TODO: set evp_md depending on params->alg */
3796c87c5fbaSopenharmony_ci  ccm = &params->params.aes;
3797c87c5fbaSopenharmony_ci
3798c87c5fbaSopenharmony_ci  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
3799c87c5fbaSopenharmony_ci
3800c87c5fbaSopenharmony_ci  /* EVP_CIPHER_CTX_init(ctx); */
3801c87c5fbaSopenharmony_ci  C(EVP_EncryptInit_ex(ctx, cipher, NULL, NULL, NULL));
3802c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
3803c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx,
3804c87c5fbaSopenharmony_ci                        EVP_CTRL_AEAD_SET_IVLEN,
3805c87c5fbaSopenharmony_ci                        (int)(15 - ccm->l),
3806c87c5fbaSopenharmony_ci                        NULL));
3807c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, NULL));
3808c87c5fbaSopenharmony_ci  C(EVP_EncryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
3809c87c5fbaSopenharmony_ci  /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
3810c87c5fbaSopenharmony_ci
3811c87c5fbaSopenharmony_ci  C(EVP_EncryptUpdate(ctx, NULL, &result_len, NULL, (int)data->length));
3812c87c5fbaSopenharmony_ci  if (aad && aad->s && (aad->length > 0)) {
3813c87c5fbaSopenharmony_ci    C(EVP_EncryptUpdate(ctx, NULL, &result_len, aad->s, (int)aad->length));
3814c87c5fbaSopenharmony_ci  }
3815c87c5fbaSopenharmony_ci  C(EVP_EncryptUpdate(ctx, result, &result_len, data->s, (int)data->length));
3816c87c5fbaSopenharmony_ci  /* C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp)); */
3817c87c5fbaSopenharmony_ci  tmp = result_len;
3818c87c5fbaSopenharmony_ci  C(EVP_EncryptFinal_ex(ctx, result + result_len, &tmp));
3819c87c5fbaSopenharmony_ci  result_len += tmp;
3820c87c5fbaSopenharmony_ci
3821c87c5fbaSopenharmony_ci  /* retrieve the tag */
3822c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx,
3823c87c5fbaSopenharmony_ci                        EVP_CTRL_CCM_GET_TAG,
3824c87c5fbaSopenharmony_ci                        (int)ccm->tag_len,
3825c87c5fbaSopenharmony_ci                        result + result_len));
3826c87c5fbaSopenharmony_ci
3827c87c5fbaSopenharmony_ci  *max_result_len = result_len + ccm->tag_len;
3828c87c5fbaSopenharmony_ci  EVP_CIPHER_CTX_free(ctx);
3829c87c5fbaSopenharmony_ci  return 1;
3830c87c5fbaSopenharmony_ci
3831c87c5fbaSopenharmony_cierror:
3832c87c5fbaSopenharmony_ci  coap_crypto_output_errors("coap_crypto_aead_encrypt");
3833c87c5fbaSopenharmony_ci  return 0;
3834c87c5fbaSopenharmony_ci}
3835c87c5fbaSopenharmony_ci
3836c87c5fbaSopenharmony_ciint
3837c87c5fbaSopenharmony_cicoap_crypto_aead_decrypt(const coap_crypto_param_t *params,
3838c87c5fbaSopenharmony_ci                         coap_bin_const_t *data,
3839c87c5fbaSopenharmony_ci                         coap_bin_const_t *aad,
3840c87c5fbaSopenharmony_ci                         uint8_t *result,
3841c87c5fbaSopenharmony_ci                         size_t *max_result_len) {
3842c87c5fbaSopenharmony_ci  const EVP_CIPHER *cipher;
3843c87c5fbaSopenharmony_ci  const coap_crypto_aes_ccm_t *ccm;
3844c87c5fbaSopenharmony_ci  int tmp;
3845c87c5fbaSopenharmony_ci  int len;
3846c87c5fbaSopenharmony_ci  const uint8_t *tag;
3847c87c5fbaSopenharmony_ci  uint8_t *rwtag;
3848c87c5fbaSopenharmony_ci
3849c87c5fbaSopenharmony_ci  if (data == NULL)
3850c87c5fbaSopenharmony_ci    return 0;
3851c87c5fbaSopenharmony_ci
3852c87c5fbaSopenharmony_ci  assert(params != NULL);
3853c87c5fbaSopenharmony_ci  if (!params || ((cipher = get_cipher_alg(params->alg)) == NULL)) {
3854c87c5fbaSopenharmony_ci    return 0;
3855c87c5fbaSopenharmony_ci  }
3856c87c5fbaSopenharmony_ci
3857c87c5fbaSopenharmony_ci  ccm = &params->params.aes;
3858c87c5fbaSopenharmony_ci
3859c87c5fbaSopenharmony_ci  if (data->length < ccm->tag_len) {
3860c87c5fbaSopenharmony_ci    return 0;
3861c87c5fbaSopenharmony_ci  } else {
3862c87c5fbaSopenharmony_ci    tag = data->s + data->length - ccm->tag_len;
3863c87c5fbaSopenharmony_ci    data->length -= ccm->tag_len;
3864c87c5fbaSopenharmony_ci    /* Kludge to stop compiler warning */
3865c87c5fbaSopenharmony_ci    memcpy(&rwtag, &tag, sizeof(rwtag));
3866c87c5fbaSopenharmony_ci  }
3867c87c5fbaSopenharmony_ci
3868c87c5fbaSopenharmony_ci  EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
3869c87c5fbaSopenharmony_ci
3870c87c5fbaSopenharmony_ci  C(EVP_DecryptInit_ex(ctx, cipher, NULL, NULL, NULL));
3871c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx,
3872c87c5fbaSopenharmony_ci                        EVP_CTRL_AEAD_SET_IVLEN,
3873c87c5fbaSopenharmony_ci                        (int)(15 - ccm->l),
3874c87c5fbaSopenharmony_ci                        NULL));
3875c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, (int)ccm->tag_len, rwtag));
3876c87c5fbaSopenharmony_ci  C(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_CCM_SET_L, (int)ccm->l, NULL));
3877c87c5fbaSopenharmony_ci  /* C(EVP_CIPHER_CTX_set_padding(ctx, 0)); */
3878c87c5fbaSopenharmony_ci  C(EVP_DecryptInit_ex(ctx, NULL, NULL, ccm->key.s, ccm->nonce));
3879c87c5fbaSopenharmony_ci
3880c87c5fbaSopenharmony_ci  C(EVP_DecryptUpdate(ctx, NULL, &len, NULL, (int)data->length));
3881c87c5fbaSopenharmony_ci  if (aad && aad->s && (aad->length > 0)) {
3882c87c5fbaSopenharmony_ci    C(EVP_DecryptUpdate(ctx, NULL, &len, aad->s, (int)aad->length));
3883c87c5fbaSopenharmony_ci  }
3884c87c5fbaSopenharmony_ci  tmp = EVP_DecryptUpdate(ctx, result, &len, data->s, (int)data->length);
3885c87c5fbaSopenharmony_ci  EVP_CIPHER_CTX_free(ctx);
3886c87c5fbaSopenharmony_ci  if (tmp <= 0) {
3887c87c5fbaSopenharmony_ci    *max_result_len = 0;
3888c87c5fbaSopenharmony_ci    return 0;
3889c87c5fbaSopenharmony_ci  }
3890c87c5fbaSopenharmony_ci  *max_result_len = len;
3891c87c5fbaSopenharmony_ci  return 1;
3892c87c5fbaSopenharmony_ci
3893c87c5fbaSopenharmony_cierror:
3894c87c5fbaSopenharmony_ci  coap_crypto_output_errors("coap_crypto_aead_decrypt");
3895c87c5fbaSopenharmony_ci  return 0;
3896c87c5fbaSopenharmony_ci}
3897c87c5fbaSopenharmony_ci
3898c87c5fbaSopenharmony_ciint
3899c87c5fbaSopenharmony_cicoap_crypto_hmac(cose_hmac_alg_t hmac_alg,
3900c87c5fbaSopenharmony_ci                 coap_bin_const_t *key,
3901c87c5fbaSopenharmony_ci                 coap_bin_const_t *data,
3902c87c5fbaSopenharmony_ci                 coap_bin_const_t **hmac) {
3903c87c5fbaSopenharmony_ci  unsigned int result_len;
3904c87c5fbaSopenharmony_ci  const EVP_MD *evp_md;
3905c87c5fbaSopenharmony_ci  coap_binary_t *dummy = NULL;
3906c87c5fbaSopenharmony_ci
3907c87c5fbaSopenharmony_ci  assert(key);
3908c87c5fbaSopenharmony_ci  assert(data);
3909c87c5fbaSopenharmony_ci  assert(hmac);
3910c87c5fbaSopenharmony_ci
3911c87c5fbaSopenharmony_ci  if ((evp_md = get_hmac_alg(hmac_alg)) == 0) {
3912c87c5fbaSopenharmony_ci    coap_log_debug("coap_crypto_hmac: algorithm %d not supported\n", hmac_alg);
3913c87c5fbaSopenharmony_ci    return 0;
3914c87c5fbaSopenharmony_ci  }
3915c87c5fbaSopenharmony_ci  dummy = coap_new_binary(EVP_MAX_MD_SIZE);
3916c87c5fbaSopenharmony_ci  if (dummy == NULL)
3917c87c5fbaSopenharmony_ci    return 0;
3918c87c5fbaSopenharmony_ci  result_len = (unsigned int)dummy->length;
3919c87c5fbaSopenharmony_ci  if (HMAC(evp_md,
3920c87c5fbaSopenharmony_ci           key->s,
3921c87c5fbaSopenharmony_ci           (int)key->length,
3922c87c5fbaSopenharmony_ci           data->s,
3923c87c5fbaSopenharmony_ci           (int)data->length,
3924c87c5fbaSopenharmony_ci           dummy->s,
3925c87c5fbaSopenharmony_ci           &result_len)) {
3926c87c5fbaSopenharmony_ci    dummy->length = result_len;
3927c87c5fbaSopenharmony_ci    *hmac = (coap_bin_const_t *)dummy;
3928c87c5fbaSopenharmony_ci    return 1;
3929c87c5fbaSopenharmony_ci  }
3930c87c5fbaSopenharmony_ci
3931c87c5fbaSopenharmony_ci  coap_crypto_output_errors("coap_crypto_hmac");
3932c87c5fbaSopenharmony_ci  return 0;
3933c87c5fbaSopenharmony_ci}
3934c87c5fbaSopenharmony_ci
3935c87c5fbaSopenharmony_ci#endif /* COAP_OSCORE_SUPPORT */
3936c87c5fbaSopenharmony_ci
3937c87c5fbaSopenharmony_ci#else /* !COAP_WITH_LIBOPENSSL */
3938c87c5fbaSopenharmony_ci
3939c87c5fbaSopenharmony_ci#ifdef __clang__
3940c87c5fbaSopenharmony_ci/* Make compilers happy that do not like empty modules. As this function is
3941c87c5fbaSopenharmony_ci * never used, we ignore -Wunused-function at the end of compiling this file
3942c87c5fbaSopenharmony_ci */
3943c87c5fbaSopenharmony_ci#pragma GCC diagnostic ignored "-Wunused-function"
3944c87c5fbaSopenharmony_ci#endif
3945c87c5fbaSopenharmony_cistatic inline void
3946c87c5fbaSopenharmony_cidummy(void) {
3947c87c5fbaSopenharmony_ci}
3948c87c5fbaSopenharmony_ci
3949c87c5fbaSopenharmony_ci#endif /* COAP_WITH_LIBOPENSSL */
3950