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, ¶ms, 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 = ¶ms->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 = ¶ms->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