113498266Sopenharmony_ci/*************************************************************************** 213498266Sopenharmony_ci * _ _ ____ _ 313498266Sopenharmony_ci * Project ___| | | | _ \| | 413498266Sopenharmony_ci * / __| | | | |_) | | 513498266Sopenharmony_ci * | (__| |_| | _ <| |___ 613498266Sopenharmony_ci * \___|\___/|_| \_\_____| 713498266Sopenharmony_ci * 813498266Sopenharmony_ci * Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al. 913498266Sopenharmony_ci * Copyright (C) Hoi-Ho Chan, <hoiho.chan@gmail.com> 1013498266Sopenharmony_ci * 1113498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1213498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1313498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1413498266Sopenharmony_ci * 1513498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1613498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1713498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1813498266Sopenharmony_ci * 1913498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 2013498266Sopenharmony_ci * KIND, either express or implied. 2113498266Sopenharmony_ci * 2213498266Sopenharmony_ci * SPDX-License-Identifier: curl 2313498266Sopenharmony_ci * 2413498266Sopenharmony_ci ***************************************************************************/ 2513498266Sopenharmony_ci 2613498266Sopenharmony_ci/* 2713498266Sopenharmony_ci * Source file for all mbedTLS-specific code for the TLS/SSL layer. No code 2813498266Sopenharmony_ci * but vtls.c should ever call or use these functions. 2913498266Sopenharmony_ci * 3013498266Sopenharmony_ci */ 3113498266Sopenharmony_ci 3213498266Sopenharmony_ci#include "curl_setup.h" 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci#ifdef USE_MBEDTLS 3513498266Sopenharmony_ci 3613498266Sopenharmony_ci/* Define this to enable lots of debugging for mbedTLS */ 3713498266Sopenharmony_ci/* #define MBEDTLS_DEBUG */ 3813498266Sopenharmony_ci 3913498266Sopenharmony_ci#ifdef __GNUC__ 4013498266Sopenharmony_ci#pragma GCC diagnostic push 4113498266Sopenharmony_ci/* mbedTLS (as of v3.5.1) has a duplicate function declaration 4213498266Sopenharmony_ci in its public headers. Disable the warning that detects it. */ 4313498266Sopenharmony_ci#pragma GCC diagnostic ignored "-Wredundant-decls" 4413498266Sopenharmony_ci#endif 4513498266Sopenharmony_ci 4613498266Sopenharmony_ci#include <mbedtls/version.h> 4713498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x02040000 4813498266Sopenharmony_ci#include <mbedtls/net_sockets.h> 4913498266Sopenharmony_ci#else 5013498266Sopenharmony_ci#include <mbedtls/net.h> 5113498266Sopenharmony_ci#endif 5213498266Sopenharmony_ci#include <mbedtls/ssl.h> 5313498266Sopenharmony_ci#include <mbedtls/x509.h> 5413498266Sopenharmony_ci 5513498266Sopenharmony_ci#include <mbedtls/error.h> 5613498266Sopenharmony_ci#include <mbedtls/entropy.h> 5713498266Sopenharmony_ci#include <mbedtls/ctr_drbg.h> 5813498266Sopenharmony_ci#include <mbedtls/sha256.h> 5913498266Sopenharmony_ci 6013498266Sopenharmony_ci#if MBEDTLS_VERSION_MAJOR >= 2 6113498266Sopenharmony_ci# ifdef MBEDTLS_DEBUG 6213498266Sopenharmony_ci# include <mbedtls/debug.h> 6313498266Sopenharmony_ci# endif 6413498266Sopenharmony_ci#endif 6513498266Sopenharmony_ci 6613498266Sopenharmony_ci#ifdef __GNUC__ 6713498266Sopenharmony_ci#pragma GCC diagnostic pop 6813498266Sopenharmony_ci#endif 6913498266Sopenharmony_ci 7013498266Sopenharmony_ci#include "urldata.h" 7113498266Sopenharmony_ci#include "sendf.h" 7213498266Sopenharmony_ci#include "inet_pton.h" 7313498266Sopenharmony_ci#include "mbedtls.h" 7413498266Sopenharmony_ci#include "vtls.h" 7513498266Sopenharmony_ci#include "vtls_int.h" 7613498266Sopenharmony_ci#include "parsedate.h" 7713498266Sopenharmony_ci#include "connect.h" /* for the connect timeout */ 7813498266Sopenharmony_ci#include "select.h" 7913498266Sopenharmony_ci#include "multiif.h" 8013498266Sopenharmony_ci#include "mbedtls_threadlock.h" 8113498266Sopenharmony_ci#include "strdup.h" 8213498266Sopenharmony_ci 8313498266Sopenharmony_ci/* The last 3 #include files should be in this order */ 8413498266Sopenharmony_ci#include "curl_printf.h" 8513498266Sopenharmony_ci#include "curl_memory.h" 8613498266Sopenharmony_ci#include "memdebug.h" 8713498266Sopenharmony_ci 8813498266Sopenharmony_ci/* ALPN for http2 */ 8913498266Sopenharmony_ci#ifdef USE_HTTP2 9013498266Sopenharmony_ci# undef HAS_ALPN 9113498266Sopenharmony_ci# ifdef MBEDTLS_SSL_ALPN 9213498266Sopenharmony_ci# define HAS_ALPN 9313498266Sopenharmony_ci# endif 9413498266Sopenharmony_ci#endif 9513498266Sopenharmony_ci 9613498266Sopenharmony_cistruct mbed_ssl_backend_data { 9713498266Sopenharmony_ci mbedtls_ctr_drbg_context ctr_drbg; 9813498266Sopenharmony_ci mbedtls_entropy_context entropy; 9913498266Sopenharmony_ci mbedtls_ssl_context ssl; 10013498266Sopenharmony_ci mbedtls_x509_crt cacert; 10113498266Sopenharmony_ci mbedtls_x509_crt clicert; 10213498266Sopenharmony_ci#ifdef MBEDTLS_X509_CRL_PARSE_C 10313498266Sopenharmony_ci mbedtls_x509_crl crl; 10413498266Sopenharmony_ci#endif 10513498266Sopenharmony_ci mbedtls_pk_context pk; 10613498266Sopenharmony_ci mbedtls_ssl_config config; 10713498266Sopenharmony_ci#ifdef HAS_ALPN 10813498266Sopenharmony_ci const char *protocols[3]; 10913498266Sopenharmony_ci#endif 11013498266Sopenharmony_ci}; 11113498266Sopenharmony_ci 11213498266Sopenharmony_ci/* apply threading? */ 11313498266Sopenharmony_ci#if defined(USE_THREADS_POSIX) || defined(USE_THREADS_WIN32) 11413498266Sopenharmony_ci#define THREADING_SUPPORT 11513498266Sopenharmony_ci#endif 11613498266Sopenharmony_ci 11713498266Sopenharmony_ci#ifndef MBEDTLS_ERROR_C 11813498266Sopenharmony_ci#define mbedtls_strerror(a,b,c) b[0] = 0 11913498266Sopenharmony_ci#endif 12013498266Sopenharmony_ci 12113498266Sopenharmony_ci#if defined(THREADING_SUPPORT) 12213498266Sopenharmony_cistatic mbedtls_entropy_context ts_entropy; 12313498266Sopenharmony_ci 12413498266Sopenharmony_cistatic int entropy_init_initialized = 0; 12513498266Sopenharmony_ci 12613498266Sopenharmony_ci/* start of entropy_init_mutex() */ 12713498266Sopenharmony_cistatic void entropy_init_mutex(mbedtls_entropy_context *ctx) 12813498266Sopenharmony_ci{ 12913498266Sopenharmony_ci /* lock 0 = entropy_init_mutex() */ 13013498266Sopenharmony_ci Curl_mbedtlsthreadlock_lock_function(0); 13113498266Sopenharmony_ci if(entropy_init_initialized == 0) { 13213498266Sopenharmony_ci mbedtls_entropy_init(ctx); 13313498266Sopenharmony_ci entropy_init_initialized = 1; 13413498266Sopenharmony_ci } 13513498266Sopenharmony_ci Curl_mbedtlsthreadlock_unlock_function(0); 13613498266Sopenharmony_ci} 13713498266Sopenharmony_ci/* end of entropy_init_mutex() */ 13813498266Sopenharmony_ci 13913498266Sopenharmony_ci/* start of entropy_func_mutex() */ 14013498266Sopenharmony_cistatic int entropy_func_mutex(void *data, unsigned char *output, size_t len) 14113498266Sopenharmony_ci{ 14213498266Sopenharmony_ci int ret; 14313498266Sopenharmony_ci /* lock 1 = entropy_func_mutex() */ 14413498266Sopenharmony_ci Curl_mbedtlsthreadlock_lock_function(1); 14513498266Sopenharmony_ci ret = mbedtls_entropy_func(data, output, len); 14613498266Sopenharmony_ci Curl_mbedtlsthreadlock_unlock_function(1); 14713498266Sopenharmony_ci 14813498266Sopenharmony_ci return ret; 14913498266Sopenharmony_ci} 15013498266Sopenharmony_ci/* end of entropy_func_mutex() */ 15113498266Sopenharmony_ci 15213498266Sopenharmony_ci#endif /* THREADING_SUPPORT */ 15313498266Sopenharmony_ci 15413498266Sopenharmony_ci#ifdef MBEDTLS_DEBUG 15513498266Sopenharmony_cistatic void mbed_debug(void *context, int level, const char *f_name, 15613498266Sopenharmony_ci int line_nb, const char *line) 15713498266Sopenharmony_ci{ 15813498266Sopenharmony_ci struct Curl_easy *data = NULL; 15913498266Sopenharmony_ci 16013498266Sopenharmony_ci if(!context) 16113498266Sopenharmony_ci return; 16213498266Sopenharmony_ci 16313498266Sopenharmony_ci data = (struct Curl_easy *)context; 16413498266Sopenharmony_ci 16513498266Sopenharmony_ci infof(data, "%s", line); 16613498266Sopenharmony_ci (void) level; 16713498266Sopenharmony_ci} 16813498266Sopenharmony_ci#endif 16913498266Sopenharmony_ci 17013498266Sopenharmony_cistatic int mbedtls_bio_cf_write(void *bio, 17113498266Sopenharmony_ci const unsigned char *buf, size_t blen) 17213498266Sopenharmony_ci{ 17313498266Sopenharmony_ci struct Curl_cfilter *cf = bio; 17413498266Sopenharmony_ci struct Curl_easy *data = CF_DATA_CURRENT(cf); 17513498266Sopenharmony_ci ssize_t nwritten; 17613498266Sopenharmony_ci CURLcode result; 17713498266Sopenharmony_ci 17813498266Sopenharmony_ci DEBUGASSERT(data); 17913498266Sopenharmony_ci if(!data) 18013498266Sopenharmony_ci return 0; 18113498266Sopenharmony_ci 18213498266Sopenharmony_ci nwritten = Curl_conn_cf_send(cf->next, data, (char *)buf, blen, &result); 18313498266Sopenharmony_ci CURL_TRC_CF(data, cf, "mbedtls_bio_cf_out_write(len=%zu) -> %zd, err=%d", 18413498266Sopenharmony_ci blen, nwritten, result); 18513498266Sopenharmony_ci if(nwritten < 0 && CURLE_AGAIN == result) { 18613498266Sopenharmony_ci nwritten = MBEDTLS_ERR_SSL_WANT_WRITE; 18713498266Sopenharmony_ci } 18813498266Sopenharmony_ci return (int)nwritten; 18913498266Sopenharmony_ci} 19013498266Sopenharmony_ci 19113498266Sopenharmony_cistatic int mbedtls_bio_cf_read(void *bio, unsigned char *buf, size_t blen) 19213498266Sopenharmony_ci{ 19313498266Sopenharmony_ci struct Curl_cfilter *cf = bio; 19413498266Sopenharmony_ci struct Curl_easy *data = CF_DATA_CURRENT(cf); 19513498266Sopenharmony_ci ssize_t nread; 19613498266Sopenharmony_ci CURLcode result; 19713498266Sopenharmony_ci 19813498266Sopenharmony_ci DEBUGASSERT(data); 19913498266Sopenharmony_ci if(!data) 20013498266Sopenharmony_ci return 0; 20113498266Sopenharmony_ci /* OpenSSL catches this case, so should we. */ 20213498266Sopenharmony_ci if(!buf) 20313498266Sopenharmony_ci return 0; 20413498266Sopenharmony_ci 20513498266Sopenharmony_ci nread = Curl_conn_cf_recv(cf->next, data, (char *)buf, blen, &result); 20613498266Sopenharmony_ci CURL_TRC_CF(data, cf, "mbedtls_bio_cf_in_read(len=%zu) -> %zd, err=%d", 20713498266Sopenharmony_ci blen, nread, result); 20813498266Sopenharmony_ci if(nread < 0 && CURLE_AGAIN == result) { 20913498266Sopenharmony_ci nread = MBEDTLS_ERR_SSL_WANT_READ; 21013498266Sopenharmony_ci } 21113498266Sopenharmony_ci return (int)nread; 21213498266Sopenharmony_ci} 21313498266Sopenharmony_ci 21413498266Sopenharmony_ci/* 21513498266Sopenharmony_ci * profile 21613498266Sopenharmony_ci */ 21713498266Sopenharmony_cistatic const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_fr = 21813498266Sopenharmony_ci{ 21913498266Sopenharmony_ci /* Hashes from SHA-1 and above */ 22013498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA1) | 22113498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_RIPEMD160) | 22213498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA224) | 22313498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA256) | 22413498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA384) | 22513498266Sopenharmony_ci MBEDTLS_X509_ID_FLAG(MBEDTLS_MD_SHA512), 22613498266Sopenharmony_ci 0xFFFFFFF, /* Any PK alg */ 22713498266Sopenharmony_ci 0xFFFFFFF, /* Any curve */ 22813498266Sopenharmony_ci 1024, /* RSA min key len */ 22913498266Sopenharmony_ci}; 23013498266Sopenharmony_ci 23113498266Sopenharmony_ci/* See https://tls.mbed.org/discussions/generic/ 23213498266Sopenharmony_ci howto-determine-exact-buffer-len-for-mbedtls_pk_write_pubkey_der 23313498266Sopenharmony_ci*/ 23413498266Sopenharmony_ci#define RSA_PUB_DER_MAX_BYTES (38 + 2 * MBEDTLS_MPI_MAX_SIZE) 23513498266Sopenharmony_ci#define ECP_PUB_DER_MAX_BYTES (30 + 2 * MBEDTLS_ECP_MAX_BYTES) 23613498266Sopenharmony_ci 23713498266Sopenharmony_ci#define PUB_DER_MAX_BYTES (RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ 23813498266Sopenharmony_ci RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES) 23913498266Sopenharmony_ci 24013498266Sopenharmony_cistatic CURLcode mbedtls_version_from_curl(int *mbedver, long version) 24113498266Sopenharmony_ci{ 24213498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x03000000 24313498266Sopenharmony_ci switch(version) { 24413498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 24513498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 24613498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 24713498266Sopenharmony_ci *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; 24813498266Sopenharmony_ci return CURLE_OK; 24913498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 25013498266Sopenharmony_ci break; 25113498266Sopenharmony_ci } 25213498266Sopenharmony_ci#else 25313498266Sopenharmony_ci switch(version) { 25413498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 25513498266Sopenharmony_ci *mbedver = MBEDTLS_SSL_MINOR_VERSION_1; 25613498266Sopenharmony_ci return CURLE_OK; 25713498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 25813498266Sopenharmony_ci *mbedver = MBEDTLS_SSL_MINOR_VERSION_2; 25913498266Sopenharmony_ci return CURLE_OK; 26013498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 26113498266Sopenharmony_ci *mbedver = MBEDTLS_SSL_MINOR_VERSION_3; 26213498266Sopenharmony_ci return CURLE_OK; 26313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 26413498266Sopenharmony_ci break; 26513498266Sopenharmony_ci } 26613498266Sopenharmony_ci#endif 26713498266Sopenharmony_ci 26813498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 26913498266Sopenharmony_ci} 27013498266Sopenharmony_ci 27113498266Sopenharmony_cistatic CURLcode 27213498266Sopenharmony_ciset_ssl_version_min_max(struct Curl_cfilter *cf, struct Curl_easy *data) 27313498266Sopenharmony_ci{ 27413498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 27513498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 27613498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 27713498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 27813498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x03000000 27913498266Sopenharmony_ci int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_3; 28013498266Sopenharmony_ci int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_3; 28113498266Sopenharmony_ci#else 28213498266Sopenharmony_ci int mbedtls_ver_min = MBEDTLS_SSL_MINOR_VERSION_1; 28313498266Sopenharmony_ci int mbedtls_ver_max = MBEDTLS_SSL_MINOR_VERSION_1; 28413498266Sopenharmony_ci#endif 28513498266Sopenharmony_ci long ssl_version = conn_config->version; 28613498266Sopenharmony_ci long ssl_version_max = conn_config->version_max; 28713498266Sopenharmony_ci CURLcode result = CURLE_OK; 28813498266Sopenharmony_ci 28913498266Sopenharmony_ci DEBUGASSERT(backend); 29013498266Sopenharmony_ci 29113498266Sopenharmony_ci switch(ssl_version) { 29213498266Sopenharmony_ci case CURL_SSLVERSION_DEFAULT: 29313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: 29413498266Sopenharmony_ci ssl_version = CURL_SSLVERSION_TLSv1_0; 29513498266Sopenharmony_ci break; 29613498266Sopenharmony_ci } 29713498266Sopenharmony_ci 29813498266Sopenharmony_ci switch(ssl_version_max) { 29913498266Sopenharmony_ci case CURL_SSLVERSION_MAX_NONE: 30013498266Sopenharmony_ci case CURL_SSLVERSION_MAX_DEFAULT: 30113498266Sopenharmony_ci ssl_version_max = CURL_SSLVERSION_MAX_TLSv1_2; 30213498266Sopenharmony_ci break; 30313498266Sopenharmony_ci } 30413498266Sopenharmony_ci 30513498266Sopenharmony_ci result = mbedtls_version_from_curl(&mbedtls_ver_min, ssl_version); 30613498266Sopenharmony_ci if(result) { 30713498266Sopenharmony_ci failf(data, "unsupported min version passed via CURLOPT_SSLVERSION"); 30813498266Sopenharmony_ci return result; 30913498266Sopenharmony_ci } 31013498266Sopenharmony_ci result = mbedtls_version_from_curl(&mbedtls_ver_max, ssl_version_max >> 16); 31113498266Sopenharmony_ci if(result) { 31213498266Sopenharmony_ci failf(data, "unsupported max version passed via CURLOPT_SSLVERSION"); 31313498266Sopenharmony_ci return result; 31413498266Sopenharmony_ci } 31513498266Sopenharmony_ci 31613498266Sopenharmony_ci mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 31713498266Sopenharmony_ci mbedtls_ver_min); 31813498266Sopenharmony_ci mbedtls_ssl_conf_max_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 31913498266Sopenharmony_ci mbedtls_ver_max); 32013498266Sopenharmony_ci 32113498266Sopenharmony_ci return result; 32213498266Sopenharmony_ci} 32313498266Sopenharmony_ci 32413498266Sopenharmony_cistatic CURLcode 32513498266Sopenharmony_cimbed_connect_step1(struct Curl_cfilter *cf, struct Curl_easy *data) 32613498266Sopenharmony_ci{ 32713498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 32813498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 32913498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 33013498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 33113498266Sopenharmony_ci const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 33213498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 33313498266Sopenharmony_ci const char * const ssl_cafile = 33413498266Sopenharmony_ci /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ 33513498266Sopenharmony_ci (ca_info_blob ? NULL : conn_config->CAfile); 33613498266Sopenharmony_ci const bool verifypeer = conn_config->verifypeer; 33713498266Sopenharmony_ci const char * const ssl_capath = conn_config->CApath; 33813498266Sopenharmony_ci char * const ssl_cert = ssl_config->primary.clientcert; 33913498266Sopenharmony_ci const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; 34013498266Sopenharmony_ci const char * const ssl_crlfile = ssl_config->primary.CRLfile; 34113498266Sopenharmony_ci const char *hostname = connssl->peer.hostname; 34213498266Sopenharmony_ci int ret = -1; 34313498266Sopenharmony_ci char errorbuf[128]; 34413498266Sopenharmony_ci 34513498266Sopenharmony_ci DEBUGASSERT(backend); 34613498266Sopenharmony_ci 34713498266Sopenharmony_ci if((conn_config->version == CURL_SSLVERSION_SSLv2) || 34813498266Sopenharmony_ci (conn_config->version == CURL_SSLVERSION_SSLv3)) { 34913498266Sopenharmony_ci failf(data, "Not supported SSL version"); 35013498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 35113498266Sopenharmony_ci } 35213498266Sopenharmony_ci 35313498266Sopenharmony_ci#ifdef THREADING_SUPPORT 35413498266Sopenharmony_ci entropy_init_mutex(&ts_entropy); 35513498266Sopenharmony_ci mbedtls_ctr_drbg_init(&backend->ctr_drbg); 35613498266Sopenharmony_ci 35713498266Sopenharmony_ci ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, entropy_func_mutex, 35813498266Sopenharmony_ci &ts_entropy, NULL, 0); 35913498266Sopenharmony_ci if(ret) { 36013498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 36113498266Sopenharmony_ci failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 36213498266Sopenharmony_ci -ret, errorbuf); 36313498266Sopenharmony_ci return CURLE_FAILED_INIT; 36413498266Sopenharmony_ci } 36513498266Sopenharmony_ci#else 36613498266Sopenharmony_ci mbedtls_entropy_init(&backend->entropy); 36713498266Sopenharmony_ci mbedtls_ctr_drbg_init(&backend->ctr_drbg); 36813498266Sopenharmony_ci 36913498266Sopenharmony_ci ret = mbedtls_ctr_drbg_seed(&backend->ctr_drbg, mbedtls_entropy_func, 37013498266Sopenharmony_ci &backend->entropy, NULL, 0); 37113498266Sopenharmony_ci if(ret) { 37213498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 37313498266Sopenharmony_ci failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 37413498266Sopenharmony_ci -ret, errorbuf); 37513498266Sopenharmony_ci return CURLE_FAILED_INIT; 37613498266Sopenharmony_ci } 37713498266Sopenharmony_ci#endif /* THREADING_SUPPORT */ 37813498266Sopenharmony_ci 37913498266Sopenharmony_ci /* Load the trusted CA */ 38013498266Sopenharmony_ci mbedtls_x509_crt_init(&backend->cacert); 38113498266Sopenharmony_ci 38213498266Sopenharmony_ci if(ca_info_blob && verifypeer) { 38313498266Sopenharmony_ci /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null 38413498266Sopenharmony_ci terminated even when provided the exact length, forcing us to waste 38513498266Sopenharmony_ci extra memory here. */ 38613498266Sopenharmony_ci unsigned char *newblob = Curl_memdup0(ca_info_blob->data, 38713498266Sopenharmony_ci ca_info_blob->len); 38813498266Sopenharmony_ci if(!newblob) 38913498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 39013498266Sopenharmony_ci ret = mbedtls_x509_crt_parse(&backend->cacert, newblob, 39113498266Sopenharmony_ci ca_info_blob->len + 1); 39213498266Sopenharmony_ci free(newblob); 39313498266Sopenharmony_ci if(ret<0) { 39413498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 39513498266Sopenharmony_ci failf(data, "Error importing ca cert blob - mbedTLS: (-0x%04X) %s", 39613498266Sopenharmony_ci -ret, errorbuf); 39713498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 39813498266Sopenharmony_ci } 39913498266Sopenharmony_ci } 40013498266Sopenharmony_ci 40113498266Sopenharmony_ci if(ssl_cafile && verifypeer) { 40213498266Sopenharmony_ci#ifdef MBEDTLS_FS_IO 40313498266Sopenharmony_ci ret = mbedtls_x509_crt_parse_file(&backend->cacert, ssl_cafile); 40413498266Sopenharmony_ci 40513498266Sopenharmony_ci if(ret<0) { 40613498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 40713498266Sopenharmony_ci failf(data, "Error reading ca cert file %s - mbedTLS: (-0x%04X) %s", 40813498266Sopenharmony_ci ssl_cafile, -ret, errorbuf); 40913498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 41013498266Sopenharmony_ci } 41113498266Sopenharmony_ci#else 41213498266Sopenharmony_ci failf(data, "mbedtls: functions that use the filesystem not built in"); 41313498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 41413498266Sopenharmony_ci#endif 41513498266Sopenharmony_ci } 41613498266Sopenharmony_ci 41713498266Sopenharmony_ci if(ssl_capath) { 41813498266Sopenharmony_ci#ifdef MBEDTLS_FS_IO 41913498266Sopenharmony_ci ret = mbedtls_x509_crt_parse_path(&backend->cacert, ssl_capath); 42013498266Sopenharmony_ci 42113498266Sopenharmony_ci if(ret<0) { 42213498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 42313498266Sopenharmony_ci failf(data, "Error reading ca cert path %s - mbedTLS: (-0x%04X) %s", 42413498266Sopenharmony_ci ssl_capath, -ret, errorbuf); 42513498266Sopenharmony_ci 42613498266Sopenharmony_ci if(verifypeer) 42713498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 42813498266Sopenharmony_ci } 42913498266Sopenharmony_ci#else 43013498266Sopenharmony_ci failf(data, "mbedtls: functions that use the filesystem not built in"); 43113498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 43213498266Sopenharmony_ci#endif 43313498266Sopenharmony_ci } 43413498266Sopenharmony_ci 43513498266Sopenharmony_ci /* Load the client certificate */ 43613498266Sopenharmony_ci mbedtls_x509_crt_init(&backend->clicert); 43713498266Sopenharmony_ci 43813498266Sopenharmony_ci if(ssl_cert) { 43913498266Sopenharmony_ci#ifdef MBEDTLS_FS_IO 44013498266Sopenharmony_ci ret = mbedtls_x509_crt_parse_file(&backend->clicert, ssl_cert); 44113498266Sopenharmony_ci 44213498266Sopenharmony_ci if(ret) { 44313498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 44413498266Sopenharmony_ci failf(data, "Error reading client cert file %s - mbedTLS: (-0x%04X) %s", 44513498266Sopenharmony_ci ssl_cert, -ret, errorbuf); 44613498266Sopenharmony_ci 44713498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 44813498266Sopenharmony_ci } 44913498266Sopenharmony_ci#else 45013498266Sopenharmony_ci failf(data, "mbedtls: functions that use the filesystem not built in"); 45113498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 45213498266Sopenharmony_ci#endif 45313498266Sopenharmony_ci } 45413498266Sopenharmony_ci 45513498266Sopenharmony_ci if(ssl_cert_blob) { 45613498266Sopenharmony_ci /* Unfortunately, mbedtls_x509_crt_parse() requires the data to be null 45713498266Sopenharmony_ci terminated even when provided the exact length, forcing us to waste 45813498266Sopenharmony_ci extra memory here. */ 45913498266Sopenharmony_ci unsigned char *newblob = Curl_memdup0(ssl_cert_blob->data, 46013498266Sopenharmony_ci ssl_cert_blob->len); 46113498266Sopenharmony_ci if(!newblob) 46213498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 46313498266Sopenharmony_ci ret = mbedtls_x509_crt_parse(&backend->clicert, newblob, 46413498266Sopenharmony_ci ssl_cert_blob->len + 1); 46513498266Sopenharmony_ci free(newblob); 46613498266Sopenharmony_ci 46713498266Sopenharmony_ci if(ret) { 46813498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 46913498266Sopenharmony_ci failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", 47013498266Sopenharmony_ci ssl_config->key, -ret, errorbuf); 47113498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 47213498266Sopenharmony_ci } 47313498266Sopenharmony_ci } 47413498266Sopenharmony_ci 47513498266Sopenharmony_ci /* Load the client private key */ 47613498266Sopenharmony_ci mbedtls_pk_init(&backend->pk); 47713498266Sopenharmony_ci 47813498266Sopenharmony_ci if(ssl_config->key || ssl_config->key_blob) { 47913498266Sopenharmony_ci if(ssl_config->key) { 48013498266Sopenharmony_ci#ifdef MBEDTLS_FS_IO 48113498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x03000000 48213498266Sopenharmony_ci ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, 48313498266Sopenharmony_ci ssl_config->key_passwd, 48413498266Sopenharmony_ci mbedtls_ctr_drbg_random, 48513498266Sopenharmony_ci &backend->ctr_drbg); 48613498266Sopenharmony_ci#else 48713498266Sopenharmony_ci ret = mbedtls_pk_parse_keyfile(&backend->pk, ssl_config->key, 48813498266Sopenharmony_ci ssl_config->key_passwd); 48913498266Sopenharmony_ci#endif 49013498266Sopenharmony_ci 49113498266Sopenharmony_ci if(ret) { 49213498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 49313498266Sopenharmony_ci failf(data, "Error reading private key %s - mbedTLS: (-0x%04X) %s", 49413498266Sopenharmony_ci ssl_config->key, -ret, errorbuf); 49513498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 49613498266Sopenharmony_ci } 49713498266Sopenharmony_ci#else 49813498266Sopenharmony_ci failf(data, "mbedtls: functions that use the filesystem not built in"); 49913498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 50013498266Sopenharmony_ci#endif 50113498266Sopenharmony_ci } 50213498266Sopenharmony_ci else { 50313498266Sopenharmony_ci const struct curl_blob *ssl_key_blob = ssl_config->key_blob; 50413498266Sopenharmony_ci const unsigned char *key_data = 50513498266Sopenharmony_ci (const unsigned char *)ssl_key_blob->data; 50613498266Sopenharmony_ci const char *passwd = ssl_config->key_passwd; 50713498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x03000000 50813498266Sopenharmony_ci ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, 50913498266Sopenharmony_ci (const unsigned char *)passwd, 51013498266Sopenharmony_ci passwd ? strlen(passwd) : 0, 51113498266Sopenharmony_ci mbedtls_ctr_drbg_random, 51213498266Sopenharmony_ci &backend->ctr_drbg); 51313498266Sopenharmony_ci#else 51413498266Sopenharmony_ci ret = mbedtls_pk_parse_key(&backend->pk, key_data, ssl_key_blob->len, 51513498266Sopenharmony_ci (const unsigned char *)passwd, 51613498266Sopenharmony_ci passwd ? strlen(passwd) : 0); 51713498266Sopenharmony_ci#endif 51813498266Sopenharmony_ci 51913498266Sopenharmony_ci if(ret) { 52013498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 52113498266Sopenharmony_ci failf(data, "Error parsing private key - mbedTLS: (-0x%04X) %s", 52213498266Sopenharmony_ci -ret, errorbuf); 52313498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 52413498266Sopenharmony_ci } 52513498266Sopenharmony_ci } 52613498266Sopenharmony_ci 52713498266Sopenharmony_ci if(ret == 0 && !(mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_RSA) || 52813498266Sopenharmony_ci mbedtls_pk_can_do(&backend->pk, MBEDTLS_PK_ECKEY))) 52913498266Sopenharmony_ci ret = MBEDTLS_ERR_PK_TYPE_MISMATCH; 53013498266Sopenharmony_ci } 53113498266Sopenharmony_ci 53213498266Sopenharmony_ci /* Load the CRL */ 53313498266Sopenharmony_ci#ifdef MBEDTLS_X509_CRL_PARSE_C 53413498266Sopenharmony_ci mbedtls_x509_crl_init(&backend->crl); 53513498266Sopenharmony_ci 53613498266Sopenharmony_ci if(ssl_crlfile) { 53713498266Sopenharmony_ci#ifdef MBEDTLS_FS_IO 53813498266Sopenharmony_ci ret = mbedtls_x509_crl_parse_file(&backend->crl, ssl_crlfile); 53913498266Sopenharmony_ci 54013498266Sopenharmony_ci if(ret) { 54113498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 54213498266Sopenharmony_ci failf(data, "Error reading CRL file %s - mbedTLS: (-0x%04X) %s", 54313498266Sopenharmony_ci ssl_crlfile, -ret, errorbuf); 54413498266Sopenharmony_ci 54513498266Sopenharmony_ci return CURLE_SSL_CRL_BADFILE; 54613498266Sopenharmony_ci } 54713498266Sopenharmony_ci#else 54813498266Sopenharmony_ci failf(data, "mbedtls: functions that use the filesystem not built in"); 54913498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 55013498266Sopenharmony_ci#endif 55113498266Sopenharmony_ci } 55213498266Sopenharmony_ci#else 55313498266Sopenharmony_ci if(ssl_crlfile) { 55413498266Sopenharmony_ci failf(data, "mbedtls: crl support not built in"); 55513498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 55613498266Sopenharmony_ci } 55713498266Sopenharmony_ci#endif 55813498266Sopenharmony_ci 55913498266Sopenharmony_ci infof(data, "mbedTLS: Connecting to %s:%d", hostname, connssl->port); 56013498266Sopenharmony_ci 56113498266Sopenharmony_ci mbedtls_ssl_config_init(&backend->config); 56213498266Sopenharmony_ci ret = mbedtls_ssl_config_defaults(&backend->config, 56313498266Sopenharmony_ci MBEDTLS_SSL_IS_CLIENT, 56413498266Sopenharmony_ci MBEDTLS_SSL_TRANSPORT_STREAM, 56513498266Sopenharmony_ci MBEDTLS_SSL_PRESET_DEFAULT); 56613498266Sopenharmony_ci if(ret) { 56713498266Sopenharmony_ci failf(data, "mbedTLS: ssl_config failed"); 56813498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 56913498266Sopenharmony_ci } 57013498266Sopenharmony_ci 57113498266Sopenharmony_ci mbedtls_ssl_init(&backend->ssl); 57213498266Sopenharmony_ci if(mbedtls_ssl_setup(&backend->ssl, &backend->config)) { 57313498266Sopenharmony_ci failf(data, "mbedTLS: ssl_init failed"); 57413498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 57513498266Sopenharmony_ci } 57613498266Sopenharmony_ci 57713498266Sopenharmony_ci /* new profile with RSA min key len = 1024 ... */ 57813498266Sopenharmony_ci mbedtls_ssl_conf_cert_profile(&backend->config, 57913498266Sopenharmony_ci &mbedtls_x509_crt_profile_fr); 58013498266Sopenharmony_ci 58113498266Sopenharmony_ci switch(conn_config->version) { 58213498266Sopenharmony_ci case CURL_SSLVERSION_DEFAULT: 58313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: 58413498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER < 0x03000000 58513498266Sopenharmony_ci mbedtls_ssl_conf_min_version(&backend->config, MBEDTLS_SSL_MAJOR_VERSION_3, 58613498266Sopenharmony_ci MBEDTLS_SSL_MINOR_VERSION_1); 58713498266Sopenharmony_ci infof(data, "mbedTLS: Set min SSL version to TLS 1.0"); 58813498266Sopenharmony_ci break; 58913498266Sopenharmony_ci#endif 59013498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 59113498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 59213498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 59313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 59413498266Sopenharmony_ci { 59513498266Sopenharmony_ci CURLcode result = set_ssl_version_min_max(cf, data); 59613498266Sopenharmony_ci if(result != CURLE_OK) 59713498266Sopenharmony_ci return result; 59813498266Sopenharmony_ci break; 59913498266Sopenharmony_ci } 60013498266Sopenharmony_ci default: 60113498266Sopenharmony_ci failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 60213498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 60313498266Sopenharmony_ci } 60413498266Sopenharmony_ci 60513498266Sopenharmony_ci mbedtls_ssl_conf_authmode(&backend->config, MBEDTLS_SSL_VERIFY_OPTIONAL); 60613498266Sopenharmony_ci 60713498266Sopenharmony_ci mbedtls_ssl_conf_rng(&backend->config, mbedtls_ctr_drbg_random, 60813498266Sopenharmony_ci &backend->ctr_drbg); 60913498266Sopenharmony_ci mbedtls_ssl_set_bio(&backend->ssl, cf, 61013498266Sopenharmony_ci mbedtls_bio_cf_write, 61113498266Sopenharmony_ci mbedtls_bio_cf_read, 61213498266Sopenharmony_ci NULL /* rev_timeout() */); 61313498266Sopenharmony_ci 61413498266Sopenharmony_ci mbedtls_ssl_conf_ciphersuites(&backend->config, 61513498266Sopenharmony_ci mbedtls_ssl_list_ciphersuites()); 61613498266Sopenharmony_ci 61713498266Sopenharmony_ci#if defined(MBEDTLS_SSL_RENEGOTIATION) 61813498266Sopenharmony_ci mbedtls_ssl_conf_renegotiation(&backend->config, 61913498266Sopenharmony_ci MBEDTLS_SSL_RENEGOTIATION_ENABLED); 62013498266Sopenharmony_ci#endif 62113498266Sopenharmony_ci 62213498266Sopenharmony_ci#if defined(MBEDTLS_SSL_SESSION_TICKETS) 62313498266Sopenharmony_ci mbedtls_ssl_conf_session_tickets(&backend->config, 62413498266Sopenharmony_ci MBEDTLS_SSL_SESSION_TICKETS_DISABLED); 62513498266Sopenharmony_ci#endif 62613498266Sopenharmony_ci 62713498266Sopenharmony_ci /* Check if there's a cached ID we can/should use here! */ 62813498266Sopenharmony_ci if(ssl_config->primary.sessionid) { 62913498266Sopenharmony_ci void *old_session = NULL; 63013498266Sopenharmony_ci 63113498266Sopenharmony_ci Curl_ssl_sessionid_lock(data); 63213498266Sopenharmony_ci if(!Curl_ssl_getsessionid(cf, data, &old_session, NULL)) { 63313498266Sopenharmony_ci ret = mbedtls_ssl_set_session(&backend->ssl, old_session); 63413498266Sopenharmony_ci if(ret) { 63513498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 63613498266Sopenharmony_ci failf(data, "mbedtls_ssl_set_session returned -0x%x", -ret); 63713498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 63813498266Sopenharmony_ci } 63913498266Sopenharmony_ci infof(data, "mbedTLS reusing session"); 64013498266Sopenharmony_ci } 64113498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 64213498266Sopenharmony_ci } 64313498266Sopenharmony_ci 64413498266Sopenharmony_ci mbedtls_ssl_conf_ca_chain(&backend->config, 64513498266Sopenharmony_ci &backend->cacert, 64613498266Sopenharmony_ci#ifdef MBEDTLS_X509_CRL_PARSE_C 64713498266Sopenharmony_ci &backend->crl); 64813498266Sopenharmony_ci#else 64913498266Sopenharmony_ci NULL); 65013498266Sopenharmony_ci#endif 65113498266Sopenharmony_ci 65213498266Sopenharmony_ci if(ssl_config->key || ssl_config->key_blob) { 65313498266Sopenharmony_ci mbedtls_ssl_conf_own_cert(&backend->config, 65413498266Sopenharmony_ci &backend->clicert, &backend->pk); 65513498266Sopenharmony_ci } 65613498266Sopenharmony_ci 65713498266Sopenharmony_ci if(mbedtls_ssl_set_hostname(&backend->ssl, connssl->peer.sni? 65813498266Sopenharmony_ci connssl->peer.sni : connssl->peer.hostname)) { 65913498266Sopenharmony_ci /* mbedtls_ssl_set_hostname() sets the name to use in CN/SAN checks and 66013498266Sopenharmony_ci the name to set in the SNI extension. So even if curl connects to a 66113498266Sopenharmony_ci host specified as an IP address, this function must be used. */ 66213498266Sopenharmony_ci failf(data, "Failed to set SNI"); 66313498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 66413498266Sopenharmony_ci } 66513498266Sopenharmony_ci 66613498266Sopenharmony_ci#ifdef HAS_ALPN 66713498266Sopenharmony_ci if(connssl->alpn) { 66813498266Sopenharmony_ci struct alpn_proto_buf proto; 66913498266Sopenharmony_ci size_t i; 67013498266Sopenharmony_ci 67113498266Sopenharmony_ci for(i = 0; i < connssl->alpn->count; ++i) { 67213498266Sopenharmony_ci backend->protocols[i] = connssl->alpn->entries[i]; 67313498266Sopenharmony_ci } 67413498266Sopenharmony_ci /* this function doesn't clone the protocols array, which is why we need 67513498266Sopenharmony_ci to keep it around */ 67613498266Sopenharmony_ci if(mbedtls_ssl_conf_alpn_protocols(&backend->config, 67713498266Sopenharmony_ci &backend->protocols[0])) { 67813498266Sopenharmony_ci failf(data, "Failed setting ALPN protocols"); 67913498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 68013498266Sopenharmony_ci } 68113498266Sopenharmony_ci Curl_alpn_to_proto_str(&proto, connssl->alpn); 68213498266Sopenharmony_ci infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 68313498266Sopenharmony_ci } 68413498266Sopenharmony_ci#endif 68513498266Sopenharmony_ci 68613498266Sopenharmony_ci#ifdef MBEDTLS_DEBUG 68713498266Sopenharmony_ci /* In order to make that work in mbedtls MBEDTLS_DEBUG_C must be defined. */ 68813498266Sopenharmony_ci mbedtls_ssl_conf_dbg(&backend->config, mbed_debug, data); 68913498266Sopenharmony_ci /* - 0 No debug 69013498266Sopenharmony_ci * - 1 Error 69113498266Sopenharmony_ci * - 2 State change 69213498266Sopenharmony_ci * - 3 Informational 69313498266Sopenharmony_ci * - 4 Verbose 69413498266Sopenharmony_ci */ 69513498266Sopenharmony_ci mbedtls_debug_set_threshold(4); 69613498266Sopenharmony_ci#endif 69713498266Sopenharmony_ci 69813498266Sopenharmony_ci /* give application a chance to interfere with mbedTLS set up. */ 69913498266Sopenharmony_ci if(data->set.ssl.fsslctx) { 70013498266Sopenharmony_ci ret = (*data->set.ssl.fsslctx)(data, &backend->config, 70113498266Sopenharmony_ci data->set.ssl.fsslctxp); 70213498266Sopenharmony_ci if(ret) { 70313498266Sopenharmony_ci failf(data, "error signaled by ssl ctx callback"); 70413498266Sopenharmony_ci return ret; 70513498266Sopenharmony_ci } 70613498266Sopenharmony_ci } 70713498266Sopenharmony_ci 70813498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2; 70913498266Sopenharmony_ci 71013498266Sopenharmony_ci return CURLE_OK; 71113498266Sopenharmony_ci} 71213498266Sopenharmony_ci 71313498266Sopenharmony_cistatic CURLcode 71413498266Sopenharmony_cimbed_connect_step2(struct Curl_cfilter *cf, struct Curl_easy *data) 71513498266Sopenharmony_ci{ 71613498266Sopenharmony_ci int ret; 71713498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 71813498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 71913498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 72013498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 72113498266Sopenharmony_ci const mbedtls_x509_crt *peercert; 72213498266Sopenharmony_ci const char * const pinnedpubkey = Curl_ssl_cf_is_proxy(cf)? 72313498266Sopenharmony_ci data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: 72413498266Sopenharmony_ci data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 72513498266Sopenharmony_ci 72613498266Sopenharmony_ci DEBUGASSERT(backend); 72713498266Sopenharmony_ci 72813498266Sopenharmony_ci ret = mbedtls_ssl_handshake(&backend->ssl); 72913498266Sopenharmony_ci 73013498266Sopenharmony_ci if(ret == MBEDTLS_ERR_SSL_WANT_READ) { 73113498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2_reading; 73213498266Sopenharmony_ci return CURLE_OK; 73313498266Sopenharmony_ci } 73413498266Sopenharmony_ci else if(ret == MBEDTLS_ERR_SSL_WANT_WRITE) { 73513498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2_writing; 73613498266Sopenharmony_ci return CURLE_OK; 73713498266Sopenharmony_ci } 73813498266Sopenharmony_ci else if(ret) { 73913498266Sopenharmony_ci char errorbuf[128]; 74013498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 74113498266Sopenharmony_ci failf(data, "ssl_handshake returned - mbedTLS: (-0x%04X) %s", 74213498266Sopenharmony_ci -ret, errorbuf); 74313498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 74413498266Sopenharmony_ci } 74513498266Sopenharmony_ci 74613498266Sopenharmony_ci infof(data, "mbedTLS: Handshake complete, cipher is %s", 74713498266Sopenharmony_ci mbedtls_ssl_get_ciphersuite(&backend->ssl)); 74813498266Sopenharmony_ci 74913498266Sopenharmony_ci ret = mbedtls_ssl_get_verify_result(&backend->ssl); 75013498266Sopenharmony_ci 75113498266Sopenharmony_ci if(!conn_config->verifyhost) 75213498266Sopenharmony_ci /* Ignore hostname errors if verifyhost is disabled */ 75313498266Sopenharmony_ci ret &= ~MBEDTLS_X509_BADCERT_CN_MISMATCH; 75413498266Sopenharmony_ci 75513498266Sopenharmony_ci if(ret && conn_config->verifypeer) { 75613498266Sopenharmony_ci if(ret & MBEDTLS_X509_BADCERT_EXPIRED) 75713498266Sopenharmony_ci failf(data, "Cert verify failed: BADCERT_EXPIRED"); 75813498266Sopenharmony_ci 75913498266Sopenharmony_ci else if(ret & MBEDTLS_X509_BADCERT_REVOKED) 76013498266Sopenharmony_ci failf(data, "Cert verify failed: BADCERT_REVOKED"); 76113498266Sopenharmony_ci 76213498266Sopenharmony_ci else if(ret & MBEDTLS_X509_BADCERT_CN_MISMATCH) 76313498266Sopenharmony_ci failf(data, "Cert verify failed: BADCERT_CN_MISMATCH"); 76413498266Sopenharmony_ci 76513498266Sopenharmony_ci else if(ret & MBEDTLS_X509_BADCERT_NOT_TRUSTED) 76613498266Sopenharmony_ci failf(data, "Cert verify failed: BADCERT_NOT_TRUSTED"); 76713498266Sopenharmony_ci 76813498266Sopenharmony_ci else if(ret & MBEDTLS_X509_BADCERT_FUTURE) 76913498266Sopenharmony_ci failf(data, "Cert verify failed: BADCERT_FUTURE"); 77013498266Sopenharmony_ci 77113498266Sopenharmony_ci return CURLE_PEER_FAILED_VERIFICATION; 77213498266Sopenharmony_ci } 77313498266Sopenharmony_ci 77413498266Sopenharmony_ci peercert = mbedtls_ssl_get_peer_cert(&backend->ssl); 77513498266Sopenharmony_ci 77613498266Sopenharmony_ci if(peercert && data->set.verbose) { 77713498266Sopenharmony_ci const size_t bufsize = 16384; 77813498266Sopenharmony_ci char *buffer = malloc(bufsize); 77913498266Sopenharmony_ci 78013498266Sopenharmony_ci if(!buffer) 78113498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 78213498266Sopenharmony_ci 78313498266Sopenharmony_ci if(mbedtls_x509_crt_info(buffer, bufsize, "* ", peercert) > 0) 78413498266Sopenharmony_ci infof(data, "Dumping cert info: %s", buffer); 78513498266Sopenharmony_ci else 78613498266Sopenharmony_ci infof(data, "Unable to dump certificate information"); 78713498266Sopenharmony_ci 78813498266Sopenharmony_ci free(buffer); 78913498266Sopenharmony_ci } 79013498266Sopenharmony_ci 79113498266Sopenharmony_ci if(pinnedpubkey) { 79213498266Sopenharmony_ci int size; 79313498266Sopenharmony_ci CURLcode result; 79413498266Sopenharmony_ci mbedtls_x509_crt *p = NULL; 79513498266Sopenharmony_ci unsigned char *pubkey = NULL; 79613498266Sopenharmony_ci 79713498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER == 0x03000000 79813498266Sopenharmony_ci if(!peercert || !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p) || 79913498266Sopenharmony_ci !peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len)) { 80013498266Sopenharmony_ci#else 80113498266Sopenharmony_ci if(!peercert || !peercert->raw.p || !peercert->raw.len) { 80213498266Sopenharmony_ci#endif 80313498266Sopenharmony_ci failf(data, "Failed due to missing peer certificate"); 80413498266Sopenharmony_ci return CURLE_SSL_PINNEDPUBKEYNOTMATCH; 80513498266Sopenharmony_ci } 80613498266Sopenharmony_ci 80713498266Sopenharmony_ci p = calloc(1, sizeof(*p)); 80813498266Sopenharmony_ci 80913498266Sopenharmony_ci if(!p) 81013498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 81113498266Sopenharmony_ci 81213498266Sopenharmony_ci pubkey = malloc(PUB_DER_MAX_BYTES); 81313498266Sopenharmony_ci 81413498266Sopenharmony_ci if(!pubkey) { 81513498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 81613498266Sopenharmony_ci goto pinnedpubkey_error; 81713498266Sopenharmony_ci } 81813498266Sopenharmony_ci 81913498266Sopenharmony_ci mbedtls_x509_crt_init(p); 82013498266Sopenharmony_ci 82113498266Sopenharmony_ci /* Make a copy of our const peercert because mbedtls_pk_write_pubkey_der 82213498266Sopenharmony_ci needs a non-const key, for now. 82313498266Sopenharmony_ci https://github.com/ARMmbed/mbedtls/issues/396 */ 82413498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER == 0x03000000 82513498266Sopenharmony_ci if(mbedtls_x509_crt_parse_der(p, 82613498266Sopenharmony_ci peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(p), 82713498266Sopenharmony_ci peercert->MBEDTLS_PRIVATE(raw).MBEDTLS_PRIVATE(len))) { 82813498266Sopenharmony_ci#else 82913498266Sopenharmony_ci if(mbedtls_x509_crt_parse_der(p, peercert->raw.p, peercert->raw.len)) { 83013498266Sopenharmony_ci#endif 83113498266Sopenharmony_ci failf(data, "Failed copying peer certificate"); 83213498266Sopenharmony_ci result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 83313498266Sopenharmony_ci goto pinnedpubkey_error; 83413498266Sopenharmony_ci } 83513498266Sopenharmony_ci 83613498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER == 0x03000000 83713498266Sopenharmony_ci size = mbedtls_pk_write_pubkey_der(&p->MBEDTLS_PRIVATE(pk), pubkey, 83813498266Sopenharmony_ci PUB_DER_MAX_BYTES); 83913498266Sopenharmony_ci#else 84013498266Sopenharmony_ci size = mbedtls_pk_write_pubkey_der(&p->pk, pubkey, PUB_DER_MAX_BYTES); 84113498266Sopenharmony_ci#endif 84213498266Sopenharmony_ci 84313498266Sopenharmony_ci if(size <= 0) { 84413498266Sopenharmony_ci failf(data, "Failed copying public key from peer certificate"); 84513498266Sopenharmony_ci result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 84613498266Sopenharmony_ci goto pinnedpubkey_error; 84713498266Sopenharmony_ci } 84813498266Sopenharmony_ci 84913498266Sopenharmony_ci /* mbedtls_pk_write_pubkey_der writes data at the end of the buffer. */ 85013498266Sopenharmony_ci result = Curl_pin_peer_pubkey(data, 85113498266Sopenharmony_ci pinnedpubkey, 85213498266Sopenharmony_ci &pubkey[PUB_DER_MAX_BYTES - size], size); 85313498266Sopenharmony_cipinnedpubkey_error: 85413498266Sopenharmony_ci mbedtls_x509_crt_free(p); 85513498266Sopenharmony_ci free(p); 85613498266Sopenharmony_ci free(pubkey); 85713498266Sopenharmony_ci if(result) { 85813498266Sopenharmony_ci return result; 85913498266Sopenharmony_ci } 86013498266Sopenharmony_ci } 86113498266Sopenharmony_ci 86213498266Sopenharmony_ci#ifdef HAS_ALPN 86313498266Sopenharmony_ci if(connssl->alpn) { 86413498266Sopenharmony_ci const char *proto = mbedtls_ssl_get_alpn_protocol(&backend->ssl); 86513498266Sopenharmony_ci 86613498266Sopenharmony_ci Curl_alpn_set_negotiated(cf, data, (const unsigned char *)proto, 86713498266Sopenharmony_ci proto? strlen(proto) : 0); 86813498266Sopenharmony_ci } 86913498266Sopenharmony_ci#endif 87013498266Sopenharmony_ci 87113498266Sopenharmony_ci connssl->connecting_state = ssl_connect_3; 87213498266Sopenharmony_ci infof(data, "SSL connected"); 87313498266Sopenharmony_ci 87413498266Sopenharmony_ci return CURLE_OK; 87513498266Sopenharmony_ci} 87613498266Sopenharmony_ci 87713498266Sopenharmony_cistatic CURLcode 87813498266Sopenharmony_cimbed_connect_step3(struct Curl_cfilter *cf, struct Curl_easy *data) 87913498266Sopenharmony_ci{ 88013498266Sopenharmony_ci CURLcode retcode = CURLE_OK; 88113498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 88213498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 88313498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 88413498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 88513498266Sopenharmony_ci 88613498266Sopenharmony_ci DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 88713498266Sopenharmony_ci DEBUGASSERT(backend); 88813498266Sopenharmony_ci 88913498266Sopenharmony_ci if(ssl_config->primary.sessionid) { 89013498266Sopenharmony_ci int ret; 89113498266Sopenharmony_ci mbedtls_ssl_session *our_ssl_sessionid; 89213498266Sopenharmony_ci void *old_ssl_sessionid = NULL; 89313498266Sopenharmony_ci bool added = FALSE; 89413498266Sopenharmony_ci 89513498266Sopenharmony_ci our_ssl_sessionid = malloc(sizeof(mbedtls_ssl_session)); 89613498266Sopenharmony_ci if(!our_ssl_sessionid) 89713498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 89813498266Sopenharmony_ci 89913498266Sopenharmony_ci mbedtls_ssl_session_init(our_ssl_sessionid); 90013498266Sopenharmony_ci 90113498266Sopenharmony_ci ret = mbedtls_ssl_get_session(&backend->ssl, our_ssl_sessionid); 90213498266Sopenharmony_ci if(ret) { 90313498266Sopenharmony_ci if(ret != MBEDTLS_ERR_SSL_ALLOC_FAILED) 90413498266Sopenharmony_ci mbedtls_ssl_session_free(our_ssl_sessionid); 90513498266Sopenharmony_ci free(our_ssl_sessionid); 90613498266Sopenharmony_ci failf(data, "mbedtls_ssl_get_session returned -0x%x", -ret); 90713498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 90813498266Sopenharmony_ci } 90913498266Sopenharmony_ci 91013498266Sopenharmony_ci /* If there's already a matching session in the cache, delete it */ 91113498266Sopenharmony_ci Curl_ssl_sessionid_lock(data); 91213498266Sopenharmony_ci if(!Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL)) 91313498266Sopenharmony_ci Curl_ssl_delsessionid(data, old_ssl_sessionid); 91413498266Sopenharmony_ci 91513498266Sopenharmony_ci retcode = Curl_ssl_addsessionid(cf, data, our_ssl_sessionid, 91613498266Sopenharmony_ci 0, &added); 91713498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 91813498266Sopenharmony_ci if(!added) { 91913498266Sopenharmony_ci mbedtls_ssl_session_free(our_ssl_sessionid); 92013498266Sopenharmony_ci free(our_ssl_sessionid); 92113498266Sopenharmony_ci } 92213498266Sopenharmony_ci if(retcode) { 92313498266Sopenharmony_ci failf(data, "failed to store ssl session"); 92413498266Sopenharmony_ci return retcode; 92513498266Sopenharmony_ci } 92613498266Sopenharmony_ci } 92713498266Sopenharmony_ci 92813498266Sopenharmony_ci connssl->connecting_state = ssl_connect_done; 92913498266Sopenharmony_ci 93013498266Sopenharmony_ci return CURLE_OK; 93113498266Sopenharmony_ci} 93213498266Sopenharmony_ci 93313498266Sopenharmony_cistatic ssize_t mbed_send(struct Curl_cfilter *cf, struct Curl_easy *data, 93413498266Sopenharmony_ci const void *mem, size_t len, 93513498266Sopenharmony_ci CURLcode *curlcode) 93613498266Sopenharmony_ci{ 93713498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 93813498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 93913498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 94013498266Sopenharmony_ci int ret = -1; 94113498266Sopenharmony_ci 94213498266Sopenharmony_ci (void)data; 94313498266Sopenharmony_ci DEBUGASSERT(backend); 94413498266Sopenharmony_ci ret = mbedtls_ssl_write(&backend->ssl, (unsigned char *)mem, len); 94513498266Sopenharmony_ci 94613498266Sopenharmony_ci if(ret < 0) { 94713498266Sopenharmony_ci *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_WRITE) ? 94813498266Sopenharmony_ci CURLE_AGAIN : CURLE_SEND_ERROR; 94913498266Sopenharmony_ci ret = -1; 95013498266Sopenharmony_ci } 95113498266Sopenharmony_ci 95213498266Sopenharmony_ci return ret; 95313498266Sopenharmony_ci} 95413498266Sopenharmony_ci 95513498266Sopenharmony_cistatic void mbedtls_close_all(struct Curl_easy *data) 95613498266Sopenharmony_ci{ 95713498266Sopenharmony_ci (void)data; 95813498266Sopenharmony_ci} 95913498266Sopenharmony_ci 96013498266Sopenharmony_cistatic void mbedtls_close(struct Curl_cfilter *cf, struct Curl_easy *data) 96113498266Sopenharmony_ci{ 96213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 96313498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 96413498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 96513498266Sopenharmony_ci char buf[32]; 96613498266Sopenharmony_ci 96713498266Sopenharmony_ci (void)data; 96813498266Sopenharmony_ci DEBUGASSERT(backend); 96913498266Sopenharmony_ci 97013498266Sopenharmony_ci /* Maybe the server has already sent a close notify alert. 97113498266Sopenharmony_ci Read it to avoid an RST on the TCP connection. */ 97213498266Sopenharmony_ci (void)mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, sizeof(buf)); 97313498266Sopenharmony_ci 97413498266Sopenharmony_ci mbedtls_pk_free(&backend->pk); 97513498266Sopenharmony_ci mbedtls_x509_crt_free(&backend->clicert); 97613498266Sopenharmony_ci mbedtls_x509_crt_free(&backend->cacert); 97713498266Sopenharmony_ci#ifdef MBEDTLS_X509_CRL_PARSE_C 97813498266Sopenharmony_ci mbedtls_x509_crl_free(&backend->crl); 97913498266Sopenharmony_ci#endif 98013498266Sopenharmony_ci mbedtls_ssl_config_free(&backend->config); 98113498266Sopenharmony_ci mbedtls_ssl_free(&backend->ssl); 98213498266Sopenharmony_ci mbedtls_ctr_drbg_free(&backend->ctr_drbg); 98313498266Sopenharmony_ci#ifndef THREADING_SUPPORT 98413498266Sopenharmony_ci mbedtls_entropy_free(&backend->entropy); 98513498266Sopenharmony_ci#endif /* THREADING_SUPPORT */ 98613498266Sopenharmony_ci} 98713498266Sopenharmony_ci 98813498266Sopenharmony_cistatic ssize_t mbed_recv(struct Curl_cfilter *cf, struct Curl_easy *data, 98913498266Sopenharmony_ci char *buf, size_t buffersize, 99013498266Sopenharmony_ci CURLcode *curlcode) 99113498266Sopenharmony_ci{ 99213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 99313498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 99413498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 99513498266Sopenharmony_ci int ret = -1; 99613498266Sopenharmony_ci ssize_t len = -1; 99713498266Sopenharmony_ci 99813498266Sopenharmony_ci (void)data; 99913498266Sopenharmony_ci DEBUGASSERT(backend); 100013498266Sopenharmony_ci 100113498266Sopenharmony_ci ret = mbedtls_ssl_read(&backend->ssl, (unsigned char *)buf, 100213498266Sopenharmony_ci buffersize); 100313498266Sopenharmony_ci 100413498266Sopenharmony_ci if(ret <= 0) { 100513498266Sopenharmony_ci if(ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) 100613498266Sopenharmony_ci return 0; 100713498266Sopenharmony_ci 100813498266Sopenharmony_ci *curlcode = (ret == MBEDTLS_ERR_SSL_WANT_READ) ? 100913498266Sopenharmony_ci CURLE_AGAIN : CURLE_RECV_ERROR; 101013498266Sopenharmony_ci return -1; 101113498266Sopenharmony_ci } 101213498266Sopenharmony_ci 101313498266Sopenharmony_ci len = ret; 101413498266Sopenharmony_ci 101513498266Sopenharmony_ci return len; 101613498266Sopenharmony_ci} 101713498266Sopenharmony_ci 101813498266Sopenharmony_cistatic void mbedtls_session_free(void *ptr) 101913498266Sopenharmony_ci{ 102013498266Sopenharmony_ci mbedtls_ssl_session_free(ptr); 102113498266Sopenharmony_ci free(ptr); 102213498266Sopenharmony_ci} 102313498266Sopenharmony_ci 102413498266Sopenharmony_cistatic size_t mbedtls_version(char *buffer, size_t size) 102513498266Sopenharmony_ci{ 102613498266Sopenharmony_ci#ifdef MBEDTLS_VERSION_C 102713498266Sopenharmony_ci /* if mbedtls_version_get_number() is available it is better */ 102813498266Sopenharmony_ci unsigned int version = mbedtls_version_get_number(); 102913498266Sopenharmony_ci return msnprintf(buffer, size, "mbedTLS/%u.%u.%u", version>>24, 103013498266Sopenharmony_ci (version>>16)&0xff, (version>>8)&0xff); 103113498266Sopenharmony_ci#else 103213498266Sopenharmony_ci return msnprintf(buffer, size, "mbedTLS/%s", MBEDTLS_VERSION_STRING); 103313498266Sopenharmony_ci#endif 103413498266Sopenharmony_ci} 103513498266Sopenharmony_ci 103613498266Sopenharmony_cistatic CURLcode mbedtls_random(struct Curl_easy *data, 103713498266Sopenharmony_ci unsigned char *entropy, size_t length) 103813498266Sopenharmony_ci{ 103913498266Sopenharmony_ci#if defined(MBEDTLS_CTR_DRBG_C) 104013498266Sopenharmony_ci int ret = -1; 104113498266Sopenharmony_ci char errorbuf[128]; 104213498266Sopenharmony_ci mbedtls_entropy_context ctr_entropy; 104313498266Sopenharmony_ci mbedtls_ctr_drbg_context ctr_drbg; 104413498266Sopenharmony_ci mbedtls_entropy_init(&ctr_entropy); 104513498266Sopenharmony_ci mbedtls_ctr_drbg_init(&ctr_drbg); 104613498266Sopenharmony_ci 104713498266Sopenharmony_ci ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, 104813498266Sopenharmony_ci &ctr_entropy, NULL, 0); 104913498266Sopenharmony_ci 105013498266Sopenharmony_ci if(ret) { 105113498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 105213498266Sopenharmony_ci failf(data, "mbedtls_ctr_drbg_seed returned (-0x%04X) %s", 105313498266Sopenharmony_ci -ret, errorbuf); 105413498266Sopenharmony_ci } 105513498266Sopenharmony_ci else { 105613498266Sopenharmony_ci ret = mbedtls_ctr_drbg_random(&ctr_drbg, entropy, length); 105713498266Sopenharmony_ci 105813498266Sopenharmony_ci if(ret) { 105913498266Sopenharmony_ci mbedtls_strerror(ret, errorbuf, sizeof(errorbuf)); 106013498266Sopenharmony_ci failf(data, "mbedtls_ctr_drbg_random returned (-0x%04X) %s", 106113498266Sopenharmony_ci -ret, errorbuf); 106213498266Sopenharmony_ci } 106313498266Sopenharmony_ci } 106413498266Sopenharmony_ci 106513498266Sopenharmony_ci mbedtls_ctr_drbg_free(&ctr_drbg); 106613498266Sopenharmony_ci mbedtls_entropy_free(&ctr_entropy); 106713498266Sopenharmony_ci 106813498266Sopenharmony_ci return ret == 0 ? CURLE_OK : CURLE_FAILED_INIT; 106913498266Sopenharmony_ci#elif defined(MBEDTLS_HAVEGE_C) 107013498266Sopenharmony_ci mbedtls_havege_state hs; 107113498266Sopenharmony_ci mbedtls_havege_init(&hs); 107213498266Sopenharmony_ci mbedtls_havege_random(&hs, entropy, length); 107313498266Sopenharmony_ci mbedtls_havege_free(&hs); 107413498266Sopenharmony_ci return CURLE_OK; 107513498266Sopenharmony_ci#else 107613498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 107713498266Sopenharmony_ci#endif 107813498266Sopenharmony_ci} 107913498266Sopenharmony_ci 108013498266Sopenharmony_cistatic CURLcode 108113498266Sopenharmony_cimbed_connect_common(struct Curl_cfilter *cf, struct Curl_easy *data, 108213498266Sopenharmony_ci bool nonblocking, 108313498266Sopenharmony_ci bool *done) 108413498266Sopenharmony_ci{ 108513498266Sopenharmony_ci CURLcode retcode; 108613498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 108713498266Sopenharmony_ci curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); 108813498266Sopenharmony_ci timediff_t timeout_ms; 108913498266Sopenharmony_ci int what; 109013498266Sopenharmony_ci 109113498266Sopenharmony_ci /* check if the connection has already been established */ 109213498266Sopenharmony_ci if(ssl_connection_complete == connssl->state) { 109313498266Sopenharmony_ci *done = TRUE; 109413498266Sopenharmony_ci return CURLE_OK; 109513498266Sopenharmony_ci } 109613498266Sopenharmony_ci 109713498266Sopenharmony_ci if(ssl_connect_1 == connssl->connecting_state) { 109813498266Sopenharmony_ci /* Find out how much more time we're allowed */ 109913498266Sopenharmony_ci timeout_ms = Curl_timeleft(data, NULL, TRUE); 110013498266Sopenharmony_ci 110113498266Sopenharmony_ci if(timeout_ms < 0) { 110213498266Sopenharmony_ci /* no need to continue if time already is up */ 110313498266Sopenharmony_ci failf(data, "SSL connection timeout"); 110413498266Sopenharmony_ci return CURLE_OPERATION_TIMEDOUT; 110513498266Sopenharmony_ci } 110613498266Sopenharmony_ci retcode = mbed_connect_step1(cf, data); 110713498266Sopenharmony_ci if(retcode) 110813498266Sopenharmony_ci return retcode; 110913498266Sopenharmony_ci } 111013498266Sopenharmony_ci 111113498266Sopenharmony_ci while(ssl_connect_2 == connssl->connecting_state || 111213498266Sopenharmony_ci ssl_connect_2_reading == connssl->connecting_state || 111313498266Sopenharmony_ci ssl_connect_2_writing == connssl->connecting_state) { 111413498266Sopenharmony_ci 111513498266Sopenharmony_ci /* check allowed time left */ 111613498266Sopenharmony_ci timeout_ms = Curl_timeleft(data, NULL, TRUE); 111713498266Sopenharmony_ci 111813498266Sopenharmony_ci if(timeout_ms < 0) { 111913498266Sopenharmony_ci /* no need to continue if time already is up */ 112013498266Sopenharmony_ci failf(data, "SSL connection timeout"); 112113498266Sopenharmony_ci return CURLE_OPERATION_TIMEDOUT; 112213498266Sopenharmony_ci } 112313498266Sopenharmony_ci 112413498266Sopenharmony_ci /* if ssl is expecting something, check if it's available. */ 112513498266Sopenharmony_ci if(connssl->connecting_state == ssl_connect_2_reading 112613498266Sopenharmony_ci || connssl->connecting_state == ssl_connect_2_writing) { 112713498266Sopenharmony_ci 112813498266Sopenharmony_ci curl_socket_t writefd = ssl_connect_2_writing == 112913498266Sopenharmony_ci connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 113013498266Sopenharmony_ci curl_socket_t readfd = ssl_connect_2_reading == 113113498266Sopenharmony_ci connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 113213498266Sopenharmony_ci 113313498266Sopenharmony_ci what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 113413498266Sopenharmony_ci nonblocking ? 0 : timeout_ms); 113513498266Sopenharmony_ci if(what < 0) { 113613498266Sopenharmony_ci /* fatal error */ 113713498266Sopenharmony_ci failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 113813498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 113913498266Sopenharmony_ci } 114013498266Sopenharmony_ci else if(0 == what) { 114113498266Sopenharmony_ci if(nonblocking) { 114213498266Sopenharmony_ci *done = FALSE; 114313498266Sopenharmony_ci return CURLE_OK; 114413498266Sopenharmony_ci } 114513498266Sopenharmony_ci else { 114613498266Sopenharmony_ci /* timeout */ 114713498266Sopenharmony_ci failf(data, "SSL connection timeout"); 114813498266Sopenharmony_ci return CURLE_OPERATION_TIMEDOUT; 114913498266Sopenharmony_ci } 115013498266Sopenharmony_ci } 115113498266Sopenharmony_ci /* socket is readable or writable */ 115213498266Sopenharmony_ci } 115313498266Sopenharmony_ci 115413498266Sopenharmony_ci /* Run transaction, and return to the caller if it failed or if 115513498266Sopenharmony_ci * this connection is part of a multi handle and this loop would 115613498266Sopenharmony_ci * execute again. This permits the owner of a multi handle to 115713498266Sopenharmony_ci * abort a connection attempt before step2 has completed while 115813498266Sopenharmony_ci * ensuring that a client using select() or epoll() will always 115913498266Sopenharmony_ci * have a valid fdset to wait on. 116013498266Sopenharmony_ci */ 116113498266Sopenharmony_ci retcode = mbed_connect_step2(cf, data); 116213498266Sopenharmony_ci if(retcode || (nonblocking && 116313498266Sopenharmony_ci (ssl_connect_2 == connssl->connecting_state || 116413498266Sopenharmony_ci ssl_connect_2_reading == connssl->connecting_state || 116513498266Sopenharmony_ci ssl_connect_2_writing == connssl->connecting_state))) 116613498266Sopenharmony_ci return retcode; 116713498266Sopenharmony_ci 116813498266Sopenharmony_ci } /* repeat step2 until all transactions are done. */ 116913498266Sopenharmony_ci 117013498266Sopenharmony_ci if(ssl_connect_3 == connssl->connecting_state) { 117113498266Sopenharmony_ci retcode = mbed_connect_step3(cf, data); 117213498266Sopenharmony_ci if(retcode) 117313498266Sopenharmony_ci return retcode; 117413498266Sopenharmony_ci } 117513498266Sopenharmony_ci 117613498266Sopenharmony_ci if(ssl_connect_done == connssl->connecting_state) { 117713498266Sopenharmony_ci connssl->state = ssl_connection_complete; 117813498266Sopenharmony_ci *done = TRUE; 117913498266Sopenharmony_ci } 118013498266Sopenharmony_ci else 118113498266Sopenharmony_ci *done = FALSE; 118213498266Sopenharmony_ci 118313498266Sopenharmony_ci /* Reset our connect state machine */ 118413498266Sopenharmony_ci connssl->connecting_state = ssl_connect_1; 118513498266Sopenharmony_ci 118613498266Sopenharmony_ci return CURLE_OK; 118713498266Sopenharmony_ci} 118813498266Sopenharmony_ci 118913498266Sopenharmony_cistatic CURLcode mbedtls_connect_nonblocking(struct Curl_cfilter *cf, 119013498266Sopenharmony_ci struct Curl_easy *data, 119113498266Sopenharmony_ci bool *done) 119213498266Sopenharmony_ci{ 119313498266Sopenharmony_ci return mbed_connect_common(cf, data, TRUE, done); 119413498266Sopenharmony_ci} 119513498266Sopenharmony_ci 119613498266Sopenharmony_ci 119713498266Sopenharmony_cistatic CURLcode mbedtls_connect(struct Curl_cfilter *cf, 119813498266Sopenharmony_ci struct Curl_easy *data) 119913498266Sopenharmony_ci{ 120013498266Sopenharmony_ci CURLcode retcode; 120113498266Sopenharmony_ci bool done = FALSE; 120213498266Sopenharmony_ci 120313498266Sopenharmony_ci retcode = mbed_connect_common(cf, data, FALSE, &done); 120413498266Sopenharmony_ci if(retcode) 120513498266Sopenharmony_ci return retcode; 120613498266Sopenharmony_ci 120713498266Sopenharmony_ci DEBUGASSERT(done); 120813498266Sopenharmony_ci 120913498266Sopenharmony_ci return CURLE_OK; 121013498266Sopenharmony_ci} 121113498266Sopenharmony_ci 121213498266Sopenharmony_ci/* 121313498266Sopenharmony_ci * return 0 error initializing SSL 121413498266Sopenharmony_ci * return 1 SSL initialized successfully 121513498266Sopenharmony_ci */ 121613498266Sopenharmony_cistatic int mbedtls_init(void) 121713498266Sopenharmony_ci{ 121813498266Sopenharmony_ci return Curl_mbedtlsthreadlock_thread_setup(); 121913498266Sopenharmony_ci} 122013498266Sopenharmony_ci 122113498266Sopenharmony_cistatic void mbedtls_cleanup(void) 122213498266Sopenharmony_ci{ 122313498266Sopenharmony_ci#ifdef THREADING_SUPPORT 122413498266Sopenharmony_ci mbedtls_entropy_free(&ts_entropy); 122513498266Sopenharmony_ci#endif /* THREADING_SUPPORT */ 122613498266Sopenharmony_ci (void)Curl_mbedtlsthreadlock_thread_cleanup(); 122713498266Sopenharmony_ci} 122813498266Sopenharmony_ci 122913498266Sopenharmony_cistatic bool mbedtls_data_pending(struct Curl_cfilter *cf, 123013498266Sopenharmony_ci const struct Curl_easy *data) 123113498266Sopenharmony_ci{ 123213498266Sopenharmony_ci struct ssl_connect_data *ctx = cf->ctx; 123313498266Sopenharmony_ci struct mbed_ssl_backend_data *backend; 123413498266Sopenharmony_ci 123513498266Sopenharmony_ci (void)data; 123613498266Sopenharmony_ci DEBUGASSERT(ctx && ctx->backend); 123713498266Sopenharmony_ci backend = (struct mbed_ssl_backend_data *)ctx->backend; 123813498266Sopenharmony_ci return mbedtls_ssl_get_bytes_avail(&backend->ssl) != 0; 123913498266Sopenharmony_ci} 124013498266Sopenharmony_ci 124113498266Sopenharmony_cistatic CURLcode mbedtls_sha256sum(const unsigned char *input, 124213498266Sopenharmony_ci size_t inputlen, 124313498266Sopenharmony_ci unsigned char *sha256sum, 124413498266Sopenharmony_ci size_t sha256len UNUSED_PARAM) 124513498266Sopenharmony_ci{ 124613498266Sopenharmony_ci /* TODO: explain this for different mbedtls 2.x vs 3 version */ 124713498266Sopenharmony_ci (void)sha256len; 124813498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER < 0x02070000 124913498266Sopenharmony_ci mbedtls_sha256(input, inputlen, sha256sum, 0); 125013498266Sopenharmony_ci#else 125113498266Sopenharmony_ci /* returns 0 on success, otherwise failure */ 125213498266Sopenharmony_ci#if MBEDTLS_VERSION_NUMBER >= 0x03000000 125313498266Sopenharmony_ci if(mbedtls_sha256(input, inputlen, sha256sum, 0) != 0) 125413498266Sopenharmony_ci#else 125513498266Sopenharmony_ci if(mbedtls_sha256_ret(input, inputlen, sha256sum, 0) != 0) 125613498266Sopenharmony_ci#endif 125713498266Sopenharmony_ci return CURLE_BAD_FUNCTION_ARGUMENT; 125813498266Sopenharmony_ci#endif 125913498266Sopenharmony_ci return CURLE_OK; 126013498266Sopenharmony_ci} 126113498266Sopenharmony_ci 126213498266Sopenharmony_cistatic void *mbedtls_get_internals(struct ssl_connect_data *connssl, 126313498266Sopenharmony_ci CURLINFO info UNUSED_PARAM) 126413498266Sopenharmony_ci{ 126513498266Sopenharmony_ci struct mbed_ssl_backend_data *backend = 126613498266Sopenharmony_ci (struct mbed_ssl_backend_data *)connssl->backend; 126713498266Sopenharmony_ci (void)info; 126813498266Sopenharmony_ci DEBUGASSERT(backend); 126913498266Sopenharmony_ci return &backend->ssl; 127013498266Sopenharmony_ci} 127113498266Sopenharmony_ci 127213498266Sopenharmony_ciconst struct Curl_ssl Curl_ssl_mbedtls = { 127313498266Sopenharmony_ci { CURLSSLBACKEND_MBEDTLS, "mbedtls" }, /* info */ 127413498266Sopenharmony_ci 127513498266Sopenharmony_ci SSLSUPP_CA_PATH | 127613498266Sopenharmony_ci SSLSUPP_CAINFO_BLOB | 127713498266Sopenharmony_ci SSLSUPP_PINNEDPUBKEY | 127813498266Sopenharmony_ci SSLSUPP_SSL_CTX | 127913498266Sopenharmony_ci SSLSUPP_HTTPS_PROXY, 128013498266Sopenharmony_ci 128113498266Sopenharmony_ci sizeof(struct mbed_ssl_backend_data), 128213498266Sopenharmony_ci 128313498266Sopenharmony_ci mbedtls_init, /* init */ 128413498266Sopenharmony_ci mbedtls_cleanup, /* cleanup */ 128513498266Sopenharmony_ci mbedtls_version, /* version */ 128613498266Sopenharmony_ci Curl_none_check_cxn, /* check_cxn */ 128713498266Sopenharmony_ci Curl_none_shutdown, /* shutdown */ 128813498266Sopenharmony_ci mbedtls_data_pending, /* data_pending */ 128913498266Sopenharmony_ci mbedtls_random, /* random */ 129013498266Sopenharmony_ci Curl_none_cert_status_request, /* cert_status_request */ 129113498266Sopenharmony_ci mbedtls_connect, /* connect */ 129213498266Sopenharmony_ci mbedtls_connect_nonblocking, /* connect_nonblocking */ 129313498266Sopenharmony_ci Curl_ssl_adjust_pollset, /* adjust_pollset */ 129413498266Sopenharmony_ci mbedtls_get_internals, /* get_internals */ 129513498266Sopenharmony_ci mbedtls_close, /* close_one */ 129613498266Sopenharmony_ci mbedtls_close_all, /* close_all */ 129713498266Sopenharmony_ci mbedtls_session_free, /* session_free */ 129813498266Sopenharmony_ci Curl_none_set_engine, /* set_engine */ 129913498266Sopenharmony_ci Curl_none_set_engine_default, /* set_engine_default */ 130013498266Sopenharmony_ci Curl_none_engines_list, /* engines_list */ 130113498266Sopenharmony_ci Curl_none_false_start, /* false_start */ 130213498266Sopenharmony_ci mbedtls_sha256sum, /* sha256sum */ 130313498266Sopenharmony_ci NULL, /* associate_connection */ 130413498266Sopenharmony_ci NULL, /* disassociate_connection */ 130513498266Sopenharmony_ci NULL, /* free_multi_ssl_backend_data */ 130613498266Sopenharmony_ci mbed_recv, /* recv decrypted data */ 130713498266Sopenharmony_ci mbed_send, /* send data to encrypt */ 130813498266Sopenharmony_ci}; 130913498266Sopenharmony_ci 131013498266Sopenharmony_ci#endif /* USE_MBEDTLS */ 1311