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 * 1013498266Sopenharmony_ci * This software is licensed as described in the file COPYING, which 1113498266Sopenharmony_ci * you should have received as part of this distribution. The terms 1213498266Sopenharmony_ci * are also available at https://curl.se/docs/copyright.html. 1313498266Sopenharmony_ci * 1413498266Sopenharmony_ci * You may opt to use, copy, modify, merge, publish, distribute and/or sell 1513498266Sopenharmony_ci * copies of the Software, and permit persons to whom the Software is 1613498266Sopenharmony_ci * furnished to do so, under the terms of the COPYING file. 1713498266Sopenharmony_ci * 1813498266Sopenharmony_ci * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY 1913498266Sopenharmony_ci * KIND, either express or implied. 2013498266Sopenharmony_ci * 2113498266Sopenharmony_ci * SPDX-License-Identifier: curl 2213498266Sopenharmony_ci * 2313498266Sopenharmony_ci ***************************************************************************/ 2413498266Sopenharmony_ci 2513498266Sopenharmony_ci/* 2613498266Sopenharmony_ci * Source file for all OpenSSL-specific code for the TLS/SSL layer. No code 2713498266Sopenharmony_ci * but vtls.c should ever call or use these functions. 2813498266Sopenharmony_ci */ 2913498266Sopenharmony_ci 3013498266Sopenharmony_ci#include "curl_setup.h" 3113498266Sopenharmony_ci 3213498266Sopenharmony_ci#if defined(USE_QUICHE) || defined(USE_OPENSSL) 3313498266Sopenharmony_ci 3413498266Sopenharmony_ci#include <limits.h> 3513498266Sopenharmony_ci 3613498266Sopenharmony_ci/* Wincrypt must be included before anything that could include OpenSSL. */ 3713498266Sopenharmony_ci#if defined(USE_WIN32_CRYPTO) 3813498266Sopenharmony_ci#include <wincrypt.h> 3913498266Sopenharmony_ci/* Undefine wincrypt conflicting symbols for BoringSSL. */ 4013498266Sopenharmony_ci#undef X509_NAME 4113498266Sopenharmony_ci#undef X509_EXTENSIONS 4213498266Sopenharmony_ci#undef PKCS7_ISSUER_AND_SERIAL 4313498266Sopenharmony_ci#undef PKCS7_SIGNER_INFO 4413498266Sopenharmony_ci#undef OCSP_REQUEST 4513498266Sopenharmony_ci#undef OCSP_RESPONSE 4613498266Sopenharmony_ci#endif 4713498266Sopenharmony_ci 4813498266Sopenharmony_ci#include "urldata.h" 4913498266Sopenharmony_ci#include "sendf.h" 5013498266Sopenharmony_ci#include "formdata.h" /* for the boundary function */ 5113498266Sopenharmony_ci#include "url.h" /* for the ssl config check function */ 5213498266Sopenharmony_ci#include "inet_pton.h" 5313498266Sopenharmony_ci#include "openssl.h" 5413498266Sopenharmony_ci#include "connect.h" 5513498266Sopenharmony_ci#include "slist.h" 5613498266Sopenharmony_ci#include "select.h" 5713498266Sopenharmony_ci#include "vtls.h" 5813498266Sopenharmony_ci#include "vtls_int.h" 5913498266Sopenharmony_ci#include "vauth/vauth.h" 6013498266Sopenharmony_ci#include "keylog.h" 6113498266Sopenharmony_ci#include "strcase.h" 6213498266Sopenharmony_ci#include "hostcheck.h" 6313498266Sopenharmony_ci#include "multiif.h" 6413498266Sopenharmony_ci#include "strerror.h" 6513498266Sopenharmony_ci#include "curl_printf.h" 6613498266Sopenharmony_ci 6713498266Sopenharmony_ci#include <openssl/ssl.h> 6813498266Sopenharmony_ci#include <openssl/rand.h> 6913498266Sopenharmony_ci#include <openssl/x509v3.h> 7013498266Sopenharmony_ci#ifndef OPENSSL_NO_DSA 7113498266Sopenharmony_ci#include <openssl/dsa.h> 7213498266Sopenharmony_ci#endif 7313498266Sopenharmony_ci#include <openssl/dh.h> 7413498266Sopenharmony_ci#include <openssl/err.h> 7513498266Sopenharmony_ci#include <openssl/md5.h> 7613498266Sopenharmony_ci#include <openssl/conf.h> 7713498266Sopenharmony_ci#include <openssl/bn.h> 7813498266Sopenharmony_ci#include <openssl/rsa.h> 7913498266Sopenharmony_ci#include <openssl/bio.h> 8013498266Sopenharmony_ci#include <openssl/buffer.h> 8113498266Sopenharmony_ci#include <openssl/pkcs12.h> 8213498266Sopenharmony_ci#include <openssl/tls1.h> 8313498266Sopenharmony_ci#include <openssl/evp.h> 8413498266Sopenharmony_ci 8513498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_OCSP) 8613498266Sopenharmony_ci#include <openssl/ocsp.h> 8713498266Sopenharmony_ci#endif 8813498266Sopenharmony_ci 8913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090700fL) && /* 0.9.7 or later */ \ 9013498266Sopenharmony_ci !defined(OPENSSL_NO_ENGINE) && !defined(OPENSSL_NO_UI_CONSOLE) 9113498266Sopenharmony_ci#define USE_OPENSSL_ENGINE 9213498266Sopenharmony_ci#include <openssl/engine.h> 9313498266Sopenharmony_ci#endif 9413498266Sopenharmony_ci 9513498266Sopenharmony_ci#include "warnless.h" 9613498266Sopenharmony_ci 9713498266Sopenharmony_ci/* The last #include files should be: */ 9813498266Sopenharmony_ci#include "curl_memory.h" 9913498266Sopenharmony_ci#include "memdebug.h" 10013498266Sopenharmony_ci 10113498266Sopenharmony_ci#ifndef ARRAYSIZE 10213498266Sopenharmony_ci#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) 10313498266Sopenharmony_ci#endif 10413498266Sopenharmony_ci 10513498266Sopenharmony_ci/* Uncomment the ALLOW_RENEG line to a real #define if you want to allow TLS 10613498266Sopenharmony_ci renegotiations when built with BoringSSL. Renegotiating is non-compliant 10713498266Sopenharmony_ci with HTTP/2 and "an extremely dangerous protocol feature". Beware. 10813498266Sopenharmony_ci 10913498266Sopenharmony_ci#define ALLOW_RENEG 1 11013498266Sopenharmony_ci */ 11113498266Sopenharmony_ci 11213498266Sopenharmony_ci#ifndef OPENSSL_VERSION_NUMBER 11313498266Sopenharmony_ci#error "OPENSSL_VERSION_NUMBER not defined" 11413498266Sopenharmony_ci#endif 11513498266Sopenharmony_ci 11613498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 11713498266Sopenharmony_ci#include <openssl/ui.h> 11813498266Sopenharmony_ci#endif 11913498266Sopenharmony_ci 12013498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x00909000L 12113498266Sopenharmony_ci#define SSL_METHOD_QUAL const 12213498266Sopenharmony_ci#else 12313498266Sopenharmony_ci#define SSL_METHOD_QUAL 12413498266Sopenharmony_ci#endif 12513498266Sopenharmony_ci 12613498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10000000L) 12713498266Sopenharmony_ci#define HAVE_ERR_REMOVE_THREAD_STATE 1 12813498266Sopenharmony_ci#endif 12913498266Sopenharmony_ci 13013498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && /* OpenSSL 1.1.0+ */ \ 13113498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 13213498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER < 0x20700000L) 13313498266Sopenharmony_ci#define SSLEAY_VERSION_NUMBER OPENSSL_VERSION_NUMBER 13413498266Sopenharmony_ci#define HAVE_X509_GET0_EXTENSIONS 1 /* added in 1.1.0 -pre1 */ 13513498266Sopenharmony_ci#define HAVE_OPAQUE_EVP_PKEY 1 /* since 1.1.0 -pre3 */ 13613498266Sopenharmony_ci#define HAVE_OPAQUE_RSA_DSA_DH 1 /* since 1.1.0 -pre5 */ 13713498266Sopenharmony_ci#define CONST_EXTS const 13813498266Sopenharmony_ci#define HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED 1 13913498266Sopenharmony_ci 14013498266Sopenharmony_ci/* funny typecast define due to difference in API */ 14113498266Sopenharmony_ci#ifdef LIBRESSL_VERSION_NUMBER 14213498266Sopenharmony_ci#define ARG2_X509_signature_print (X509_ALGOR *) 14313498266Sopenharmony_ci#else 14413498266Sopenharmony_ci#define ARG2_X509_signature_print 14513498266Sopenharmony_ci#endif 14613498266Sopenharmony_ci 14713498266Sopenharmony_ci#else 14813498266Sopenharmony_ci/* For OpenSSL before 1.1.0 */ 14913498266Sopenharmony_ci#define ASN1_STRING_get0_data(x) ASN1_STRING_data(x) 15013498266Sopenharmony_ci#define X509_get0_notBefore(x) X509_get_notBefore(x) 15113498266Sopenharmony_ci#define X509_get0_notAfter(x) X509_get_notAfter(x) 15213498266Sopenharmony_ci#define CONST_EXTS /* nope */ 15313498266Sopenharmony_ci#ifndef LIBRESSL_VERSION_NUMBER 15413498266Sopenharmony_ci#define OpenSSL_version_num() SSLeay() 15513498266Sopenharmony_ci#endif 15613498266Sopenharmony_ci#endif 15713498266Sopenharmony_ci 15813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* 1.0.2 or later */ \ 15913498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 16013498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER < 0x20700000L) 16113498266Sopenharmony_ci#define HAVE_X509_GET0_SIGNATURE 1 16213498266Sopenharmony_ci#endif 16313498266Sopenharmony_ci 16413498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) /* 1.0.2 or later */ 16513498266Sopenharmony_ci#define HAVE_SSL_GET_SHUTDOWN 1 16613498266Sopenharmony_ci#endif 16713498266Sopenharmony_ci 16813498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002003L && \ 16913498266Sopenharmony_ci OPENSSL_VERSION_NUMBER <= 0x10002FFFL && \ 17013498266Sopenharmony_ci !defined(OPENSSL_NO_COMP) 17113498266Sopenharmony_ci#define HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 1 17213498266Sopenharmony_ci#endif 17313498266Sopenharmony_ci 17413498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER < 0x0090808fL) 17513498266Sopenharmony_ci/* not present in older OpenSSL */ 17613498266Sopenharmony_ci#define OPENSSL_load_builtin_modules(x) 17713498266Sopenharmony_ci#endif 17813498266Sopenharmony_ci 17913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) 18013498266Sopenharmony_ci#define HAVE_EVP_PKEY_GET_PARAMS 1 18113498266Sopenharmony_ci#endif 18213498266Sopenharmony_ci 18313498266Sopenharmony_ci#ifdef HAVE_EVP_PKEY_GET_PARAMS 18413498266Sopenharmony_ci#include <openssl/core_names.h> 18513498266Sopenharmony_ci#define DECLARE_PKEY_PARAM_BIGNUM(name) BIGNUM *name = NULL 18613498266Sopenharmony_ci#define FREE_PKEY_PARAM_BIGNUM(name) BN_clear_free(name) 18713498266Sopenharmony_ci#else 18813498266Sopenharmony_ci#define DECLARE_PKEY_PARAM_BIGNUM(name) const BIGNUM *name 18913498266Sopenharmony_ci#define FREE_PKEY_PARAM_BIGNUM(name) 19013498266Sopenharmony_ci#endif 19113498266Sopenharmony_ci 19213498266Sopenharmony_ci/* 19313498266Sopenharmony_ci * Whether SSL_CTX_set_keylog_callback is available. 19413498266Sopenharmony_ci * OpenSSL: supported since 1.1.1 https://github.com/openssl/openssl/pull/2287 19513498266Sopenharmony_ci * BoringSSL: supported since d28f59c27bac (committed 2015-11-19) 19613498266Sopenharmony_ci * LibreSSL: supported since 3.5.0 (released 2022-02-24) 19713498266Sopenharmony_ci */ 19813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10101000L && \ 19913498266Sopenharmony_ci !defined(LIBRESSL_VERSION_NUMBER)) || \ 20013498266Sopenharmony_ci (defined(LIBRESSL_VERSION_NUMBER) && \ 20113498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER >= 0x3050000fL) || \ 20213498266Sopenharmony_ci defined(OPENSSL_IS_BORINGSSL) 20313498266Sopenharmony_ci#define HAVE_KEYLOG_CALLBACK 20413498266Sopenharmony_ci#endif 20513498266Sopenharmony_ci 20613498266Sopenharmony_ci/* Whether SSL_CTX_set_ciphersuites is available. 20713498266Sopenharmony_ci * OpenSSL: supported since 1.1.1 (commit a53b5be6a05) 20813498266Sopenharmony_ci * BoringSSL: no 20913498266Sopenharmony_ci * LibreSSL: supported since 3.4.1 (released 2021-10-14) 21013498266Sopenharmony_ci */ 21113498266Sopenharmony_ci#if ((OPENSSL_VERSION_NUMBER >= 0x10101000L && \ 21213498266Sopenharmony_ci !defined(LIBRESSL_VERSION_NUMBER)) || \ 21313498266Sopenharmony_ci (defined(LIBRESSL_VERSION_NUMBER) && \ 21413498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER >= 0x3040100fL)) && \ 21513498266Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) 21613498266Sopenharmony_ci #define HAVE_SSL_CTX_SET_CIPHERSUITES 21713498266Sopenharmony_ci #if !defined(OPENSSL_IS_AWSLC) 21813498266Sopenharmony_ci #define HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH 21913498266Sopenharmony_ci #endif 22013498266Sopenharmony_ci#endif 22113498266Sopenharmony_ci 22213498266Sopenharmony_ci/* 22313498266Sopenharmony_ci * Whether SSL_CTX_set1_curves_list is available. 22413498266Sopenharmony_ci * OpenSSL: supported since 1.0.2, see 22513498266Sopenharmony_ci * https://www.openssl.org/docs/manmaster/man3/SSL_CTX_set1_groups.html 22613498266Sopenharmony_ci * BoringSSL: supported since 5fd1807d95f7 (committed 2016-09-30) 22713498266Sopenharmony_ci * LibreSSL: since 2.5.3 (April 12, 2017) 22813498266Sopenharmony_ci */ 22913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) || \ 23013498266Sopenharmony_ci defined(OPENSSL_IS_BORINGSSL) 23113498266Sopenharmony_ci#define HAVE_SSL_CTX_SET_EC_CURVES 23213498266Sopenharmony_ci#endif 23313498266Sopenharmony_ci 23413498266Sopenharmony_ci#if defined(LIBRESSL_VERSION_NUMBER) 23513498266Sopenharmony_ci#define OSSL_PACKAGE "LibreSSL" 23613498266Sopenharmony_ci#elif defined(OPENSSL_IS_BORINGSSL) 23713498266Sopenharmony_ci#define OSSL_PACKAGE "BoringSSL" 23813498266Sopenharmony_ci#elif defined(OPENSSL_IS_AWSLC) 23913498266Sopenharmony_ci#define OSSL_PACKAGE "AWS-LC" 24013498266Sopenharmony_ci#else 24113498266Sopenharmony_ci# if defined(USE_NGTCP2) && defined(USE_NGHTTP3) 24213498266Sopenharmony_ci# define OSSL_PACKAGE "quictls" 24313498266Sopenharmony_ci# else 24413498266Sopenharmony_ci# define OSSL_PACKAGE "OpenSSL" 24513498266Sopenharmony_ci#endif 24613498266Sopenharmony_ci#endif 24713498266Sopenharmony_ci 24813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 24913498266Sopenharmony_ci/* up2date versions of OpenSSL maintain reasonably secure defaults without 25013498266Sopenharmony_ci * breaking compatibility, so it is better not to override the defaults in curl 25113498266Sopenharmony_ci */ 25213498266Sopenharmony_ci#define DEFAULT_CIPHER_SELECTION NULL 25313498266Sopenharmony_ci#else 25413498266Sopenharmony_ci/* ... but it is not the case with old versions of OpenSSL */ 25513498266Sopenharmony_ci#define DEFAULT_CIPHER_SELECTION \ 25613498266Sopenharmony_ci "ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH" 25713498266Sopenharmony_ci#endif 25813498266Sopenharmony_ci 25913498266Sopenharmony_ci#ifdef HAVE_OPENSSL_SRP 26013498266Sopenharmony_ci/* the function exists */ 26113498266Sopenharmony_ci#ifdef USE_TLS_SRP 26213498266Sopenharmony_ci/* the functionality is not disabled */ 26313498266Sopenharmony_ci#define USE_OPENSSL_SRP 26413498266Sopenharmony_ci#endif 26513498266Sopenharmony_ci#endif 26613498266Sopenharmony_ci 26713498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 26813498266Sopenharmony_ci#define HAVE_RANDOM_INIT_BY_DEFAULT 1 26913498266Sopenharmony_ci#endif 27013498266Sopenharmony_ci 27113498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ 27213498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 27313498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER < 0x2070100fL) && \ 27413498266Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) && \ 27513498266Sopenharmony_ci !defined(OPENSSL_IS_AWSLC) 27613498266Sopenharmony_ci#define HAVE_OPENSSL_VERSION 27713498266Sopenharmony_ci#endif 27813498266Sopenharmony_ci 27913498266Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) 28013498266Sopenharmony_citypedef uint32_t sslerr_t; 28113498266Sopenharmony_ci#else 28213498266Sopenharmony_citypedef unsigned long sslerr_t; 28313498266Sopenharmony_ci#endif 28413498266Sopenharmony_ci 28513498266Sopenharmony_ci/* 28613498266Sopenharmony_ci * Whether the OpenSSL version has the API needed to support sharing an 28713498266Sopenharmony_ci * X509_STORE between connections. The API is: 28813498266Sopenharmony_ci * * `X509_STORE_up_ref` -- Introduced: OpenSSL 1.1.0. 28913498266Sopenharmony_ci */ 29013498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* OpenSSL >= 1.1.0 */ 29113498266Sopenharmony_ci#define HAVE_SSL_X509_STORE_SHARE 29213498266Sopenharmony_ci#endif 29313498266Sopenharmony_ci 29413498266Sopenharmony_ci/* What API version do we use? */ 29513498266Sopenharmony_ci#if defined(LIBRESSL_VERSION_NUMBER) 29613498266Sopenharmony_ci#define USE_PRE_1_1_API (LIBRESSL_VERSION_NUMBER < 0x2070000f) 29713498266Sopenharmony_ci#else /* !LIBRESSL_VERSION_NUMBER */ 29813498266Sopenharmony_ci#define USE_PRE_1_1_API (OPENSSL_VERSION_NUMBER < 0x10100000L) 29913498266Sopenharmony_ci#endif /* !LIBRESSL_VERSION_NUMBER */ 30013498266Sopenharmony_ci 30113498266Sopenharmony_cistruct ossl_ssl_backend_data { 30213498266Sopenharmony_ci /* these ones requires specific SSL-types */ 30313498266Sopenharmony_ci SSL_CTX* ctx; 30413498266Sopenharmony_ci SSL* handle; 30513498266Sopenharmony_ci X509* server_cert; 30613498266Sopenharmony_ci BIO_METHOD *bio_method; 30713498266Sopenharmony_ci CURLcode io_result; /* result of last BIO cfilter operation */ 30813498266Sopenharmony_ci#ifndef HAVE_KEYLOG_CALLBACK 30913498266Sopenharmony_ci /* Set to true once a valid keylog entry has been created to avoid dupes. */ 31013498266Sopenharmony_ci bool keylog_done; 31113498266Sopenharmony_ci#endif 31213498266Sopenharmony_ci bool x509_store_setup; /* x509 store has been set up */ 31313498266Sopenharmony_ci}; 31413498266Sopenharmony_ci 31513498266Sopenharmony_ci#if defined(HAVE_SSL_X509_STORE_SHARE) 31613498266Sopenharmony_cistruct multi_ssl_backend_data { 31713498266Sopenharmony_ci char *CAfile; /* CAfile path used to generate X509 store */ 31813498266Sopenharmony_ci X509_STORE *store; /* cached X509 store or NULL if none */ 31913498266Sopenharmony_ci struct curltime time; /* when the cached store was created */ 32013498266Sopenharmony_ci}; 32113498266Sopenharmony_ci#endif /* HAVE_SSL_X509_STORE_SHARE */ 32213498266Sopenharmony_ci 32313498266Sopenharmony_ci#define push_certinfo(_label, _num) \ 32413498266Sopenharmony_cido { \ 32513498266Sopenharmony_ci long info_len = BIO_get_mem_data(mem, &ptr); \ 32613498266Sopenharmony_ci Curl_ssl_push_certinfo_len(data, _num, _label, ptr, info_len); \ 32713498266Sopenharmony_ci if(1 != BIO_reset(mem)) \ 32813498266Sopenharmony_ci break; \ 32913498266Sopenharmony_ci} while(0) 33013498266Sopenharmony_ci 33113498266Sopenharmony_cistatic void pubkey_show(struct Curl_easy *data, 33213498266Sopenharmony_ci BIO *mem, 33313498266Sopenharmony_ci int num, 33413498266Sopenharmony_ci const char *type, 33513498266Sopenharmony_ci const char *name, 33613498266Sopenharmony_ci const BIGNUM *bn) 33713498266Sopenharmony_ci{ 33813498266Sopenharmony_ci char *ptr; 33913498266Sopenharmony_ci char namebuf[32]; 34013498266Sopenharmony_ci 34113498266Sopenharmony_ci msnprintf(namebuf, sizeof(namebuf), "%s(%s)", type, name); 34213498266Sopenharmony_ci 34313498266Sopenharmony_ci if(bn) 34413498266Sopenharmony_ci BN_print(mem, bn); 34513498266Sopenharmony_ci push_certinfo(namebuf, num); 34613498266Sopenharmony_ci} 34713498266Sopenharmony_ci 34813498266Sopenharmony_ci#ifdef HAVE_OPAQUE_RSA_DSA_DH 34913498266Sopenharmony_ci#define print_pubkey_BN(_type, _name, _num) \ 35013498266Sopenharmony_ci pubkey_show(data, mem, _num, #_type, #_name, _name) 35113498266Sopenharmony_ci 35213498266Sopenharmony_ci#else 35313498266Sopenharmony_ci#define print_pubkey_BN(_type, _name, _num) \ 35413498266Sopenharmony_cido { \ 35513498266Sopenharmony_ci if(_type->_name) { \ 35613498266Sopenharmony_ci pubkey_show(data, mem, _num, #_type, #_name, _type->_name); \ 35713498266Sopenharmony_ci } \ 35813498266Sopenharmony_ci} while(0) 35913498266Sopenharmony_ci#endif 36013498266Sopenharmony_ci 36113498266Sopenharmony_cistatic int asn1_object_dump(ASN1_OBJECT *a, char *buf, size_t len) 36213498266Sopenharmony_ci{ 36313498266Sopenharmony_ci int i, ilen; 36413498266Sopenharmony_ci 36513498266Sopenharmony_ci ilen = (int)len; 36613498266Sopenharmony_ci if(ilen < 0) 36713498266Sopenharmony_ci return 1; /* buffer too big */ 36813498266Sopenharmony_ci 36913498266Sopenharmony_ci i = i2t_ASN1_OBJECT(buf, ilen, a); 37013498266Sopenharmony_ci 37113498266Sopenharmony_ci if(i >= ilen) 37213498266Sopenharmony_ci return 1; /* buffer too small */ 37313498266Sopenharmony_ci 37413498266Sopenharmony_ci return 0; 37513498266Sopenharmony_ci} 37613498266Sopenharmony_ci 37713498266Sopenharmony_cistatic void X509V3_ext(struct Curl_easy *data, 37813498266Sopenharmony_ci int certnum, 37913498266Sopenharmony_ci CONST_EXTS STACK_OF(X509_EXTENSION) *exts) 38013498266Sopenharmony_ci{ 38113498266Sopenharmony_ci int i; 38213498266Sopenharmony_ci 38313498266Sopenharmony_ci if((int)sk_X509_EXTENSION_num(exts) <= 0) 38413498266Sopenharmony_ci /* no extensions, bail out */ 38513498266Sopenharmony_ci return; 38613498266Sopenharmony_ci 38713498266Sopenharmony_ci for(i = 0; i < (int)sk_X509_EXTENSION_num(exts); i++) { 38813498266Sopenharmony_ci ASN1_OBJECT *obj; 38913498266Sopenharmony_ci X509_EXTENSION *ext = sk_X509_EXTENSION_value(exts, i); 39013498266Sopenharmony_ci BUF_MEM *biomem; 39113498266Sopenharmony_ci char namebuf[128]; 39213498266Sopenharmony_ci BIO *bio_out = BIO_new(BIO_s_mem()); 39313498266Sopenharmony_ci 39413498266Sopenharmony_ci if(!bio_out) 39513498266Sopenharmony_ci return; 39613498266Sopenharmony_ci 39713498266Sopenharmony_ci obj = X509_EXTENSION_get_object(ext); 39813498266Sopenharmony_ci 39913498266Sopenharmony_ci asn1_object_dump(obj, namebuf, sizeof(namebuf)); 40013498266Sopenharmony_ci 40113498266Sopenharmony_ci if(!X509V3_EXT_print(bio_out, ext, 0, 0)) 40213498266Sopenharmony_ci ASN1_STRING_print(bio_out, (ASN1_STRING *)X509_EXTENSION_get_data(ext)); 40313498266Sopenharmony_ci 40413498266Sopenharmony_ci BIO_get_mem_ptr(bio_out, &biomem); 40513498266Sopenharmony_ci Curl_ssl_push_certinfo_len(data, certnum, namebuf, biomem->data, 40613498266Sopenharmony_ci biomem->length); 40713498266Sopenharmony_ci BIO_free(bio_out); 40813498266Sopenharmony_ci } 40913498266Sopenharmony_ci} 41013498266Sopenharmony_ci 41113498266Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) 41213498266Sopenharmony_citypedef size_t numcert_t; 41313498266Sopenharmony_ci#else 41413498266Sopenharmony_citypedef int numcert_t; 41513498266Sopenharmony_ci#endif 41613498266Sopenharmony_ci 41713498266Sopenharmony_ciCURLcode Curl_ossl_certchain(struct Curl_easy *data, SSL *ssl) 41813498266Sopenharmony_ci{ 41913498266Sopenharmony_ci CURLcode result; 42013498266Sopenharmony_ci STACK_OF(X509) *sk; 42113498266Sopenharmony_ci int i; 42213498266Sopenharmony_ci numcert_t numcerts; 42313498266Sopenharmony_ci BIO *mem; 42413498266Sopenharmony_ci 42513498266Sopenharmony_ci DEBUGASSERT(ssl); 42613498266Sopenharmony_ci 42713498266Sopenharmony_ci sk = SSL_get_peer_cert_chain(ssl); 42813498266Sopenharmony_ci if(!sk) { 42913498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 43013498266Sopenharmony_ci } 43113498266Sopenharmony_ci 43213498266Sopenharmony_ci numcerts = sk_X509_num(sk); 43313498266Sopenharmony_ci 43413498266Sopenharmony_ci result = Curl_ssl_init_certinfo(data, (int)numcerts); 43513498266Sopenharmony_ci if(result) { 43613498266Sopenharmony_ci return result; 43713498266Sopenharmony_ci } 43813498266Sopenharmony_ci 43913498266Sopenharmony_ci mem = BIO_new(BIO_s_mem()); 44013498266Sopenharmony_ci if(!mem) { 44113498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 44213498266Sopenharmony_ci } 44313498266Sopenharmony_ci 44413498266Sopenharmony_ci for(i = 0; i < (int)numcerts; i++) { 44513498266Sopenharmony_ci ASN1_INTEGER *num; 44613498266Sopenharmony_ci X509 *x = sk_X509_value(sk, i); 44713498266Sopenharmony_ci EVP_PKEY *pubkey = NULL; 44813498266Sopenharmony_ci int j; 44913498266Sopenharmony_ci char *ptr; 45013498266Sopenharmony_ci const ASN1_BIT_STRING *psig = NULL; 45113498266Sopenharmony_ci 45213498266Sopenharmony_ci X509_NAME_print_ex(mem, X509_get_subject_name(x), 0, XN_FLAG_ONELINE); 45313498266Sopenharmony_ci push_certinfo("Subject", i); 45413498266Sopenharmony_ci 45513498266Sopenharmony_ci X509_NAME_print_ex(mem, X509_get_issuer_name(x), 0, XN_FLAG_ONELINE); 45613498266Sopenharmony_ci push_certinfo("Issuer", i); 45713498266Sopenharmony_ci 45813498266Sopenharmony_ci BIO_printf(mem, "%lx", X509_get_version(x)); 45913498266Sopenharmony_ci push_certinfo("Version", i); 46013498266Sopenharmony_ci 46113498266Sopenharmony_ci num = X509_get_serialNumber(x); 46213498266Sopenharmony_ci if(num->type == V_ASN1_NEG_INTEGER) 46313498266Sopenharmony_ci BIO_puts(mem, "-"); 46413498266Sopenharmony_ci for(j = 0; j < num->length; j++) 46513498266Sopenharmony_ci BIO_printf(mem, "%02x", num->data[j]); 46613498266Sopenharmony_ci push_certinfo("Serial Number", i); 46713498266Sopenharmony_ci 46813498266Sopenharmony_ci#if defined(HAVE_X509_GET0_SIGNATURE) && defined(HAVE_X509_GET0_EXTENSIONS) 46913498266Sopenharmony_ci { 47013498266Sopenharmony_ci const X509_ALGOR *sigalg = NULL; 47113498266Sopenharmony_ci X509_PUBKEY *xpubkey = NULL; 47213498266Sopenharmony_ci ASN1_OBJECT *pubkeyoid = NULL; 47313498266Sopenharmony_ci 47413498266Sopenharmony_ci X509_get0_signature(&psig, &sigalg, x); 47513498266Sopenharmony_ci if(sigalg) { 47613498266Sopenharmony_ci const ASN1_OBJECT *sigalgoid = NULL; 47713498266Sopenharmony_ci X509_ALGOR_get0(&sigalgoid, NULL, NULL, sigalg); 47813498266Sopenharmony_ci i2a_ASN1_OBJECT(mem, sigalgoid); 47913498266Sopenharmony_ci push_certinfo("Signature Algorithm", i); 48013498266Sopenharmony_ci } 48113498266Sopenharmony_ci 48213498266Sopenharmony_ci xpubkey = X509_get_X509_PUBKEY(x); 48313498266Sopenharmony_ci if(xpubkey) { 48413498266Sopenharmony_ci X509_PUBKEY_get0_param(&pubkeyoid, NULL, NULL, NULL, xpubkey); 48513498266Sopenharmony_ci if(pubkeyoid) { 48613498266Sopenharmony_ci i2a_ASN1_OBJECT(mem, pubkeyoid); 48713498266Sopenharmony_ci push_certinfo("Public Key Algorithm", i); 48813498266Sopenharmony_ci } 48913498266Sopenharmony_ci } 49013498266Sopenharmony_ci 49113498266Sopenharmony_ci X509V3_ext(data, i, X509_get0_extensions(x)); 49213498266Sopenharmony_ci } 49313498266Sopenharmony_ci#else 49413498266Sopenharmony_ci { 49513498266Sopenharmony_ci /* before OpenSSL 1.0.2 */ 49613498266Sopenharmony_ci X509_CINF *cinf = x->cert_info; 49713498266Sopenharmony_ci 49813498266Sopenharmony_ci i2a_ASN1_OBJECT(mem, cinf->signature->algorithm); 49913498266Sopenharmony_ci push_certinfo("Signature Algorithm", i); 50013498266Sopenharmony_ci 50113498266Sopenharmony_ci i2a_ASN1_OBJECT(mem, cinf->key->algor->algorithm); 50213498266Sopenharmony_ci push_certinfo("Public Key Algorithm", i); 50313498266Sopenharmony_ci 50413498266Sopenharmony_ci X509V3_ext(data, i, cinf->extensions); 50513498266Sopenharmony_ci 50613498266Sopenharmony_ci psig = x->signature; 50713498266Sopenharmony_ci } 50813498266Sopenharmony_ci#endif 50913498266Sopenharmony_ci 51013498266Sopenharmony_ci ASN1_TIME_print(mem, X509_get0_notBefore(x)); 51113498266Sopenharmony_ci push_certinfo("Start date", i); 51213498266Sopenharmony_ci 51313498266Sopenharmony_ci ASN1_TIME_print(mem, X509_get0_notAfter(x)); 51413498266Sopenharmony_ci push_certinfo("Expire date", i); 51513498266Sopenharmony_ci 51613498266Sopenharmony_ci pubkey = X509_get_pubkey(x); 51713498266Sopenharmony_ci if(!pubkey) 51813498266Sopenharmony_ci infof(data, " Unable to load public key"); 51913498266Sopenharmony_ci else { 52013498266Sopenharmony_ci int pktype; 52113498266Sopenharmony_ci#ifdef HAVE_OPAQUE_EVP_PKEY 52213498266Sopenharmony_ci pktype = EVP_PKEY_id(pubkey); 52313498266Sopenharmony_ci#else 52413498266Sopenharmony_ci pktype = pubkey->type; 52513498266Sopenharmony_ci#endif 52613498266Sopenharmony_ci switch(pktype) { 52713498266Sopenharmony_ci case EVP_PKEY_RSA: 52813498266Sopenharmony_ci { 52913498266Sopenharmony_ci#ifndef HAVE_EVP_PKEY_GET_PARAMS 53013498266Sopenharmony_ci RSA *rsa; 53113498266Sopenharmony_ci#ifdef HAVE_OPAQUE_EVP_PKEY 53213498266Sopenharmony_ci rsa = EVP_PKEY_get0_RSA(pubkey); 53313498266Sopenharmony_ci#else 53413498266Sopenharmony_ci rsa = pubkey->pkey.rsa; 53513498266Sopenharmony_ci#endif /* HAVE_OPAQUE_EVP_PKEY */ 53613498266Sopenharmony_ci#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ 53713498266Sopenharmony_ci 53813498266Sopenharmony_ci { 53913498266Sopenharmony_ci#ifdef HAVE_OPAQUE_RSA_DSA_DH 54013498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(n); 54113498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(e); 54213498266Sopenharmony_ci#ifdef HAVE_EVP_PKEY_GET_PARAMS 54313498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_N, &n); 54413498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_RSA_E, &e); 54513498266Sopenharmony_ci#else 54613498266Sopenharmony_ci RSA_get0_key(rsa, &n, &e, NULL); 54713498266Sopenharmony_ci#endif /* HAVE_EVP_PKEY_GET_PARAMS */ 54813498266Sopenharmony_ci BIO_printf(mem, "%d", n ? BN_num_bits(n) : 0); 54913498266Sopenharmony_ci#else 55013498266Sopenharmony_ci BIO_printf(mem, "%d", rsa->n ? BN_num_bits(rsa->n) : 0); 55113498266Sopenharmony_ci#endif /* HAVE_OPAQUE_RSA_DSA_DH */ 55213498266Sopenharmony_ci push_certinfo("RSA Public Key", i); 55313498266Sopenharmony_ci print_pubkey_BN(rsa, n, i); 55413498266Sopenharmony_ci print_pubkey_BN(rsa, e, i); 55513498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(n); 55613498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(e); 55713498266Sopenharmony_ci } 55813498266Sopenharmony_ci 55913498266Sopenharmony_ci break; 56013498266Sopenharmony_ci } 56113498266Sopenharmony_ci case EVP_PKEY_DSA: 56213498266Sopenharmony_ci { 56313498266Sopenharmony_ci#ifndef OPENSSL_NO_DSA 56413498266Sopenharmony_ci#ifndef HAVE_EVP_PKEY_GET_PARAMS 56513498266Sopenharmony_ci DSA *dsa; 56613498266Sopenharmony_ci#ifdef HAVE_OPAQUE_EVP_PKEY 56713498266Sopenharmony_ci dsa = EVP_PKEY_get0_DSA(pubkey); 56813498266Sopenharmony_ci#else 56913498266Sopenharmony_ci dsa = pubkey->pkey.dsa; 57013498266Sopenharmony_ci#endif /* HAVE_OPAQUE_EVP_PKEY */ 57113498266Sopenharmony_ci#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ 57213498266Sopenharmony_ci { 57313498266Sopenharmony_ci#ifdef HAVE_OPAQUE_RSA_DSA_DH 57413498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(p); 57513498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(q); 57613498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(g); 57713498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(pub_key); 57813498266Sopenharmony_ci#ifdef HAVE_EVP_PKEY_GET_PARAMS 57913498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); 58013498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); 58113498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); 58213498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); 58313498266Sopenharmony_ci#else 58413498266Sopenharmony_ci DSA_get0_pqg(dsa, &p, &q, &g); 58513498266Sopenharmony_ci DSA_get0_key(dsa, &pub_key, NULL); 58613498266Sopenharmony_ci#endif /* HAVE_EVP_PKEY_GET_PARAMS */ 58713498266Sopenharmony_ci#endif /* HAVE_OPAQUE_RSA_DSA_DH */ 58813498266Sopenharmony_ci print_pubkey_BN(dsa, p, i); 58913498266Sopenharmony_ci print_pubkey_BN(dsa, q, i); 59013498266Sopenharmony_ci print_pubkey_BN(dsa, g, i); 59113498266Sopenharmony_ci print_pubkey_BN(dsa, pub_key, i); 59213498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(p); 59313498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(q); 59413498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(g); 59513498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(pub_key); 59613498266Sopenharmony_ci } 59713498266Sopenharmony_ci#endif /* !OPENSSL_NO_DSA */ 59813498266Sopenharmony_ci break; 59913498266Sopenharmony_ci } 60013498266Sopenharmony_ci case EVP_PKEY_DH: 60113498266Sopenharmony_ci { 60213498266Sopenharmony_ci#ifndef HAVE_EVP_PKEY_GET_PARAMS 60313498266Sopenharmony_ci DH *dh; 60413498266Sopenharmony_ci#ifdef HAVE_OPAQUE_EVP_PKEY 60513498266Sopenharmony_ci dh = EVP_PKEY_get0_DH(pubkey); 60613498266Sopenharmony_ci#else 60713498266Sopenharmony_ci dh = pubkey->pkey.dh; 60813498266Sopenharmony_ci#endif /* HAVE_OPAQUE_EVP_PKEY */ 60913498266Sopenharmony_ci#endif /* !HAVE_EVP_PKEY_GET_PARAMS */ 61013498266Sopenharmony_ci { 61113498266Sopenharmony_ci#ifdef HAVE_OPAQUE_RSA_DSA_DH 61213498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(p); 61313498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(q); 61413498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(g); 61513498266Sopenharmony_ci DECLARE_PKEY_PARAM_BIGNUM(pub_key); 61613498266Sopenharmony_ci#ifdef HAVE_EVP_PKEY_GET_PARAMS 61713498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_P, &p); 61813498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_Q, &q); 61913498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_FFC_G, &g); 62013498266Sopenharmony_ci EVP_PKEY_get_bn_param(pubkey, OSSL_PKEY_PARAM_PUB_KEY, &pub_key); 62113498266Sopenharmony_ci#else 62213498266Sopenharmony_ci DH_get0_pqg(dh, &p, &q, &g); 62313498266Sopenharmony_ci DH_get0_key(dh, &pub_key, NULL); 62413498266Sopenharmony_ci#endif /* HAVE_EVP_PKEY_GET_PARAMS */ 62513498266Sopenharmony_ci print_pubkey_BN(dh, p, i); 62613498266Sopenharmony_ci print_pubkey_BN(dh, q, i); 62713498266Sopenharmony_ci print_pubkey_BN(dh, g, i); 62813498266Sopenharmony_ci#else 62913498266Sopenharmony_ci print_pubkey_BN(dh, p, i); 63013498266Sopenharmony_ci print_pubkey_BN(dh, g, i); 63113498266Sopenharmony_ci#endif /* HAVE_OPAQUE_RSA_DSA_DH */ 63213498266Sopenharmony_ci print_pubkey_BN(dh, pub_key, i); 63313498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(p); 63413498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(q); 63513498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(g); 63613498266Sopenharmony_ci FREE_PKEY_PARAM_BIGNUM(pub_key); 63713498266Sopenharmony_ci } 63813498266Sopenharmony_ci break; 63913498266Sopenharmony_ci } 64013498266Sopenharmony_ci } 64113498266Sopenharmony_ci EVP_PKEY_free(pubkey); 64213498266Sopenharmony_ci } 64313498266Sopenharmony_ci 64413498266Sopenharmony_ci if(psig) { 64513498266Sopenharmony_ci for(j = 0; j < psig->length; j++) 64613498266Sopenharmony_ci BIO_printf(mem, "%02x:", psig->data[j]); 64713498266Sopenharmony_ci push_certinfo("Signature", i); 64813498266Sopenharmony_ci } 64913498266Sopenharmony_ci 65013498266Sopenharmony_ci PEM_write_bio_X509(mem, x); 65113498266Sopenharmony_ci push_certinfo("Cert", i); 65213498266Sopenharmony_ci } 65313498266Sopenharmony_ci 65413498266Sopenharmony_ci BIO_free(mem); 65513498266Sopenharmony_ci 65613498266Sopenharmony_ci return CURLE_OK; 65713498266Sopenharmony_ci} 65813498266Sopenharmony_ci 65913498266Sopenharmony_ci#endif /* quiche or OpenSSL */ 66013498266Sopenharmony_ci 66113498266Sopenharmony_ci#ifdef USE_OPENSSL 66213498266Sopenharmony_ci 66313498266Sopenharmony_ci#if USE_PRE_1_1_API 66413498266Sopenharmony_ci#if !defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER < 0x2070000fL 66513498266Sopenharmony_ci#define BIO_set_init(x,v) ((x)->init=(v)) 66613498266Sopenharmony_ci#define BIO_get_data(x) ((x)->ptr) 66713498266Sopenharmony_ci#define BIO_set_data(x,v) ((x)->ptr=(v)) 66813498266Sopenharmony_ci#endif 66913498266Sopenharmony_ci#define BIO_get_shutdown(x) ((x)->shutdown) 67013498266Sopenharmony_ci#define BIO_set_shutdown(x,v) ((x)->shutdown=(v)) 67113498266Sopenharmony_ci#endif /* USE_PRE_1_1_API */ 67213498266Sopenharmony_ci 67313498266Sopenharmony_cistatic int ossl_bio_cf_create(BIO *bio) 67413498266Sopenharmony_ci{ 67513498266Sopenharmony_ci BIO_set_shutdown(bio, 1); 67613498266Sopenharmony_ci BIO_set_init(bio, 1); 67713498266Sopenharmony_ci#if USE_PRE_1_1_API 67813498266Sopenharmony_ci bio->num = -1; 67913498266Sopenharmony_ci#endif 68013498266Sopenharmony_ci BIO_set_data(bio, NULL); 68113498266Sopenharmony_ci return 1; 68213498266Sopenharmony_ci} 68313498266Sopenharmony_ci 68413498266Sopenharmony_cistatic int ossl_bio_cf_destroy(BIO *bio) 68513498266Sopenharmony_ci{ 68613498266Sopenharmony_ci if(!bio) 68713498266Sopenharmony_ci return 0; 68813498266Sopenharmony_ci return 1; 68913498266Sopenharmony_ci} 69013498266Sopenharmony_ci 69113498266Sopenharmony_cistatic long ossl_bio_cf_ctrl(BIO *bio, int cmd, long num, void *ptr) 69213498266Sopenharmony_ci{ 69313498266Sopenharmony_ci struct Curl_cfilter *cf = BIO_get_data(bio); 69413498266Sopenharmony_ci long ret = 1; 69513498266Sopenharmony_ci 69613498266Sopenharmony_ci (void)cf; 69713498266Sopenharmony_ci (void)ptr; 69813498266Sopenharmony_ci switch(cmd) { 69913498266Sopenharmony_ci case BIO_CTRL_GET_CLOSE: 70013498266Sopenharmony_ci ret = (long)BIO_get_shutdown(bio); 70113498266Sopenharmony_ci break; 70213498266Sopenharmony_ci case BIO_CTRL_SET_CLOSE: 70313498266Sopenharmony_ci BIO_set_shutdown(bio, (int)num); 70413498266Sopenharmony_ci break; 70513498266Sopenharmony_ci case BIO_CTRL_FLUSH: 70613498266Sopenharmony_ci /* we do no delayed writes, but if we ever would, this 70713498266Sopenharmony_ci * needs to trigger it. */ 70813498266Sopenharmony_ci ret = 1; 70913498266Sopenharmony_ci break; 71013498266Sopenharmony_ci case BIO_CTRL_DUP: 71113498266Sopenharmony_ci ret = 1; 71213498266Sopenharmony_ci break; 71313498266Sopenharmony_ci#ifdef BIO_CTRL_EOF 71413498266Sopenharmony_ci case BIO_CTRL_EOF: 71513498266Sopenharmony_ci /* EOF has been reached on input? */ 71613498266Sopenharmony_ci return (!cf->next || !cf->next->connected); 71713498266Sopenharmony_ci#endif 71813498266Sopenharmony_ci default: 71913498266Sopenharmony_ci ret = 0; 72013498266Sopenharmony_ci break; 72113498266Sopenharmony_ci } 72213498266Sopenharmony_ci return ret; 72313498266Sopenharmony_ci} 72413498266Sopenharmony_ci 72513498266Sopenharmony_cistatic int ossl_bio_cf_out_write(BIO *bio, const char *buf, int blen) 72613498266Sopenharmony_ci{ 72713498266Sopenharmony_ci struct Curl_cfilter *cf = BIO_get_data(bio); 72813498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 72913498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 73013498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 73113498266Sopenharmony_ci struct Curl_easy *data = CF_DATA_CURRENT(cf); 73213498266Sopenharmony_ci ssize_t nwritten; 73313498266Sopenharmony_ci CURLcode result = CURLE_SEND_ERROR; 73413498266Sopenharmony_ci 73513498266Sopenharmony_ci DEBUGASSERT(data); 73613498266Sopenharmony_ci nwritten = Curl_conn_cf_send(cf->next, data, buf, blen, &result); 73713498266Sopenharmony_ci CURL_TRC_CF(data, cf, "ossl_bio_cf_out_write(len=%d) -> %d, err=%d", 73813498266Sopenharmony_ci blen, (int)nwritten, result); 73913498266Sopenharmony_ci BIO_clear_retry_flags(bio); 74013498266Sopenharmony_ci backend->io_result = result; 74113498266Sopenharmony_ci if(nwritten < 0) { 74213498266Sopenharmony_ci if(CURLE_AGAIN == result) 74313498266Sopenharmony_ci BIO_set_retry_write(bio); 74413498266Sopenharmony_ci } 74513498266Sopenharmony_ci return (int)nwritten; 74613498266Sopenharmony_ci} 74713498266Sopenharmony_ci 74813498266Sopenharmony_cistatic int ossl_bio_cf_in_read(BIO *bio, char *buf, int blen) 74913498266Sopenharmony_ci{ 75013498266Sopenharmony_ci struct Curl_cfilter *cf = BIO_get_data(bio); 75113498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 75213498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 75313498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 75413498266Sopenharmony_ci struct Curl_easy *data = CF_DATA_CURRENT(cf); 75513498266Sopenharmony_ci ssize_t nread; 75613498266Sopenharmony_ci CURLcode result = CURLE_RECV_ERROR; 75713498266Sopenharmony_ci 75813498266Sopenharmony_ci DEBUGASSERT(data); 75913498266Sopenharmony_ci /* OpenSSL catches this case, so should we. */ 76013498266Sopenharmony_ci if(!buf) 76113498266Sopenharmony_ci return 0; 76213498266Sopenharmony_ci 76313498266Sopenharmony_ci nread = Curl_conn_cf_recv(cf->next, data, buf, blen, &result); 76413498266Sopenharmony_ci CURL_TRC_CF(data, cf, "ossl_bio_cf_in_read(len=%d) -> %d, err=%d", 76513498266Sopenharmony_ci blen, (int)nread, result); 76613498266Sopenharmony_ci BIO_clear_retry_flags(bio); 76713498266Sopenharmony_ci backend->io_result = result; 76813498266Sopenharmony_ci if(nread < 0) { 76913498266Sopenharmony_ci if(CURLE_AGAIN == result) 77013498266Sopenharmony_ci BIO_set_retry_read(bio); 77113498266Sopenharmony_ci } 77213498266Sopenharmony_ci 77313498266Sopenharmony_ci /* Before returning server replies to the SSL instance, we need 77413498266Sopenharmony_ci * to have setup the x509 store or verification will fail. */ 77513498266Sopenharmony_ci if(!backend->x509_store_setup) { 77613498266Sopenharmony_ci result = Curl_ssl_setup_x509_store(cf, data, backend->ctx); 77713498266Sopenharmony_ci if(result) { 77813498266Sopenharmony_ci backend->io_result = result; 77913498266Sopenharmony_ci return -1; 78013498266Sopenharmony_ci } 78113498266Sopenharmony_ci backend->x509_store_setup = TRUE; 78213498266Sopenharmony_ci } 78313498266Sopenharmony_ci 78413498266Sopenharmony_ci return (int)nread; 78513498266Sopenharmony_ci} 78613498266Sopenharmony_ci 78713498266Sopenharmony_ci#if USE_PRE_1_1_API 78813498266Sopenharmony_ci 78913498266Sopenharmony_cistatic BIO_METHOD ossl_bio_cf_meth_1_0 = { 79013498266Sopenharmony_ci BIO_TYPE_MEM, 79113498266Sopenharmony_ci "OpenSSL CF BIO", 79213498266Sopenharmony_ci ossl_bio_cf_out_write, 79313498266Sopenharmony_ci ossl_bio_cf_in_read, 79413498266Sopenharmony_ci NULL, /* puts is never called */ 79513498266Sopenharmony_ci NULL, /* gets is never called */ 79613498266Sopenharmony_ci ossl_bio_cf_ctrl, 79713498266Sopenharmony_ci ossl_bio_cf_create, 79813498266Sopenharmony_ci ossl_bio_cf_destroy, 79913498266Sopenharmony_ci NULL 80013498266Sopenharmony_ci}; 80113498266Sopenharmony_ci 80213498266Sopenharmony_cistatic BIO_METHOD *ossl_bio_cf_method_create(void) 80313498266Sopenharmony_ci{ 80413498266Sopenharmony_ci return &ossl_bio_cf_meth_1_0; 80513498266Sopenharmony_ci} 80613498266Sopenharmony_ci 80713498266Sopenharmony_ci#define ossl_bio_cf_method_free(m) Curl_nop_stmt 80813498266Sopenharmony_ci 80913498266Sopenharmony_ci#else 81013498266Sopenharmony_ci 81113498266Sopenharmony_cistatic BIO_METHOD *ossl_bio_cf_method_create(void) 81213498266Sopenharmony_ci{ 81313498266Sopenharmony_ci BIO_METHOD *m = BIO_meth_new(BIO_TYPE_MEM, "OpenSSL CF BIO"); 81413498266Sopenharmony_ci if(m) { 81513498266Sopenharmony_ci BIO_meth_set_write(m, &ossl_bio_cf_out_write); 81613498266Sopenharmony_ci BIO_meth_set_read(m, &ossl_bio_cf_in_read); 81713498266Sopenharmony_ci BIO_meth_set_ctrl(m, &ossl_bio_cf_ctrl); 81813498266Sopenharmony_ci BIO_meth_set_create(m, &ossl_bio_cf_create); 81913498266Sopenharmony_ci BIO_meth_set_destroy(m, &ossl_bio_cf_destroy); 82013498266Sopenharmony_ci } 82113498266Sopenharmony_ci return m; 82213498266Sopenharmony_ci} 82313498266Sopenharmony_ci 82413498266Sopenharmony_cistatic void ossl_bio_cf_method_free(BIO_METHOD *m) 82513498266Sopenharmony_ci{ 82613498266Sopenharmony_ci if(m) 82713498266Sopenharmony_ci BIO_meth_free(m); 82813498266Sopenharmony_ci} 82913498266Sopenharmony_ci 83013498266Sopenharmony_ci#endif 83113498266Sopenharmony_ci 83213498266Sopenharmony_ci 83313498266Sopenharmony_ci/* 83413498266Sopenharmony_ci * Number of bytes to read from the random number seed file. This must be 83513498266Sopenharmony_ci * a finite value (because some entropy "files" like /dev/urandom have 83613498266Sopenharmony_ci * an infinite length), but must be large enough to provide enough 83713498266Sopenharmony_ci * entropy to properly seed OpenSSL's PRNG. 83813498266Sopenharmony_ci */ 83913498266Sopenharmony_ci#define RAND_LOAD_LENGTH 1024 84013498266Sopenharmony_ci 84113498266Sopenharmony_ci#ifdef HAVE_KEYLOG_CALLBACK 84213498266Sopenharmony_cistatic void ossl_keylog_callback(const SSL *ssl, const char *line) 84313498266Sopenharmony_ci{ 84413498266Sopenharmony_ci (void)ssl; 84513498266Sopenharmony_ci 84613498266Sopenharmony_ci Curl_tls_keylog_write_line(line); 84713498266Sopenharmony_ci} 84813498266Sopenharmony_ci#else 84913498266Sopenharmony_ci/* 85013498266Sopenharmony_ci * ossl_log_tls12_secret is called by libcurl to make the CLIENT_RANDOMs if the 85113498266Sopenharmony_ci * OpenSSL being used doesn't have native support for doing that. 85213498266Sopenharmony_ci */ 85313498266Sopenharmony_cistatic void 85413498266Sopenharmony_ciossl_log_tls12_secret(const SSL *ssl, bool *keylog_done) 85513498266Sopenharmony_ci{ 85613498266Sopenharmony_ci const SSL_SESSION *session = SSL_get_session(ssl); 85713498266Sopenharmony_ci unsigned char client_random[SSL3_RANDOM_SIZE]; 85813498266Sopenharmony_ci unsigned char master_key[SSL_MAX_MASTER_KEY_LENGTH]; 85913498266Sopenharmony_ci int master_key_length = 0; 86013498266Sopenharmony_ci 86113498266Sopenharmony_ci if(!session || *keylog_done) 86213498266Sopenharmony_ci return; 86313498266Sopenharmony_ci 86413498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ 86513498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 86613498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER < 0x20700000L) 86713498266Sopenharmony_ci /* ssl->s3 is not checked in openssl 1.1.0-pre6, but let's assume that 86813498266Sopenharmony_ci * we have a valid SSL context if we have a non-NULL session. */ 86913498266Sopenharmony_ci SSL_get_client_random(ssl, client_random, SSL3_RANDOM_SIZE); 87013498266Sopenharmony_ci master_key_length = (int) 87113498266Sopenharmony_ci SSL_SESSION_get_master_key(session, master_key, SSL_MAX_MASTER_KEY_LENGTH); 87213498266Sopenharmony_ci#else 87313498266Sopenharmony_ci if(ssl->s3 && session->master_key_length > 0) { 87413498266Sopenharmony_ci master_key_length = session->master_key_length; 87513498266Sopenharmony_ci memcpy(master_key, session->master_key, session->master_key_length); 87613498266Sopenharmony_ci memcpy(client_random, ssl->s3->client_random, SSL3_RANDOM_SIZE); 87713498266Sopenharmony_ci } 87813498266Sopenharmony_ci#endif 87913498266Sopenharmony_ci 88013498266Sopenharmony_ci /* The handshake has not progressed sufficiently yet, or this is a TLS 1.3 88113498266Sopenharmony_ci * session (when curl was built with older OpenSSL headers and running with 88213498266Sopenharmony_ci * newer OpenSSL runtime libraries). */ 88313498266Sopenharmony_ci if(master_key_length <= 0) 88413498266Sopenharmony_ci return; 88513498266Sopenharmony_ci 88613498266Sopenharmony_ci *keylog_done = true; 88713498266Sopenharmony_ci Curl_tls_keylog_write("CLIENT_RANDOM", client_random, 88813498266Sopenharmony_ci master_key, master_key_length); 88913498266Sopenharmony_ci} 89013498266Sopenharmony_ci#endif /* !HAVE_KEYLOG_CALLBACK */ 89113498266Sopenharmony_ci 89213498266Sopenharmony_cistatic const char *SSL_ERROR_to_str(int err) 89313498266Sopenharmony_ci{ 89413498266Sopenharmony_ci switch(err) { 89513498266Sopenharmony_ci case SSL_ERROR_NONE: 89613498266Sopenharmony_ci return "SSL_ERROR_NONE"; 89713498266Sopenharmony_ci case SSL_ERROR_SSL: 89813498266Sopenharmony_ci return "SSL_ERROR_SSL"; 89913498266Sopenharmony_ci case SSL_ERROR_WANT_READ: 90013498266Sopenharmony_ci return "SSL_ERROR_WANT_READ"; 90113498266Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 90213498266Sopenharmony_ci return "SSL_ERROR_WANT_WRITE"; 90313498266Sopenharmony_ci case SSL_ERROR_WANT_X509_LOOKUP: 90413498266Sopenharmony_ci return "SSL_ERROR_WANT_X509_LOOKUP"; 90513498266Sopenharmony_ci case SSL_ERROR_SYSCALL: 90613498266Sopenharmony_ci return "SSL_ERROR_SYSCALL"; 90713498266Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: 90813498266Sopenharmony_ci return "SSL_ERROR_ZERO_RETURN"; 90913498266Sopenharmony_ci case SSL_ERROR_WANT_CONNECT: 91013498266Sopenharmony_ci return "SSL_ERROR_WANT_CONNECT"; 91113498266Sopenharmony_ci case SSL_ERROR_WANT_ACCEPT: 91213498266Sopenharmony_ci return "SSL_ERROR_WANT_ACCEPT"; 91313498266Sopenharmony_ci#if defined(SSL_ERROR_WANT_ASYNC) 91413498266Sopenharmony_ci case SSL_ERROR_WANT_ASYNC: 91513498266Sopenharmony_ci return "SSL_ERROR_WANT_ASYNC"; 91613498266Sopenharmony_ci#endif 91713498266Sopenharmony_ci#if defined(SSL_ERROR_WANT_ASYNC_JOB) 91813498266Sopenharmony_ci case SSL_ERROR_WANT_ASYNC_JOB: 91913498266Sopenharmony_ci return "SSL_ERROR_WANT_ASYNC_JOB"; 92013498266Sopenharmony_ci#endif 92113498266Sopenharmony_ci#if defined(SSL_ERROR_WANT_EARLY) 92213498266Sopenharmony_ci case SSL_ERROR_WANT_EARLY: 92313498266Sopenharmony_ci return "SSL_ERROR_WANT_EARLY"; 92413498266Sopenharmony_ci#endif 92513498266Sopenharmony_ci default: 92613498266Sopenharmony_ci return "SSL_ERROR unknown"; 92713498266Sopenharmony_ci } 92813498266Sopenharmony_ci} 92913498266Sopenharmony_ci 93013498266Sopenharmony_cistatic size_t ossl_version(char *buffer, size_t size); 93113498266Sopenharmony_ci 93213498266Sopenharmony_ci/* Return error string for last OpenSSL error 93313498266Sopenharmony_ci */ 93413498266Sopenharmony_cistatic char *ossl_strerror(unsigned long error, char *buf, size_t size) 93513498266Sopenharmony_ci{ 93613498266Sopenharmony_ci size_t len; 93713498266Sopenharmony_ci DEBUGASSERT(size); 93813498266Sopenharmony_ci *buf = '\0'; 93913498266Sopenharmony_ci 94013498266Sopenharmony_ci len = ossl_version(buf, size); 94113498266Sopenharmony_ci DEBUGASSERT(len < (size - 2)); 94213498266Sopenharmony_ci if(len < (size - 2)) { 94313498266Sopenharmony_ci buf += len; 94413498266Sopenharmony_ci size -= (len + 2); 94513498266Sopenharmony_ci *buf++ = ':'; 94613498266Sopenharmony_ci *buf++ = ' '; 94713498266Sopenharmony_ci *buf = '\0'; 94813498266Sopenharmony_ci } 94913498266Sopenharmony_ci 95013498266Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) 95113498266Sopenharmony_ci ERR_error_string_n((uint32_t)error, buf, size); 95213498266Sopenharmony_ci#else 95313498266Sopenharmony_ci ERR_error_string_n(error, buf, size); 95413498266Sopenharmony_ci#endif 95513498266Sopenharmony_ci 95613498266Sopenharmony_ci if(!*buf) { 95713498266Sopenharmony_ci const char *msg = error ? "Unknown error" : "No error"; 95813498266Sopenharmony_ci if(strlen(msg) < size) 95913498266Sopenharmony_ci strcpy(buf, msg); 96013498266Sopenharmony_ci } 96113498266Sopenharmony_ci 96213498266Sopenharmony_ci return buf; 96313498266Sopenharmony_ci} 96413498266Sopenharmony_ci 96513498266Sopenharmony_cistatic int passwd_callback(char *buf, int num, int encrypting, 96613498266Sopenharmony_ci void *global_passwd) 96713498266Sopenharmony_ci{ 96813498266Sopenharmony_ci DEBUGASSERT(0 == encrypting); 96913498266Sopenharmony_ci 97013498266Sopenharmony_ci if(!encrypting) { 97113498266Sopenharmony_ci int klen = curlx_uztosi(strlen((char *)global_passwd)); 97213498266Sopenharmony_ci if(num > klen) { 97313498266Sopenharmony_ci memcpy(buf, global_passwd, klen + 1); 97413498266Sopenharmony_ci return klen; 97513498266Sopenharmony_ci } 97613498266Sopenharmony_ci } 97713498266Sopenharmony_ci return 0; 97813498266Sopenharmony_ci} 97913498266Sopenharmony_ci 98013498266Sopenharmony_ci/* 98113498266Sopenharmony_ci * rand_enough() returns TRUE if we have seeded the random engine properly. 98213498266Sopenharmony_ci */ 98313498266Sopenharmony_cistatic bool rand_enough(void) 98413498266Sopenharmony_ci{ 98513498266Sopenharmony_ci return (0 != RAND_status()) ? TRUE : FALSE; 98613498266Sopenharmony_ci} 98713498266Sopenharmony_ci 98813498266Sopenharmony_cistatic CURLcode ossl_seed(struct Curl_easy *data) 98913498266Sopenharmony_ci{ 99013498266Sopenharmony_ci /* This might get called before it has been added to a multi handle */ 99113498266Sopenharmony_ci if(data->multi && data->multi->ssl_seeded) 99213498266Sopenharmony_ci return CURLE_OK; 99313498266Sopenharmony_ci 99413498266Sopenharmony_ci if(rand_enough()) { 99513498266Sopenharmony_ci /* OpenSSL 1.1.0+ should return here */ 99613498266Sopenharmony_ci if(data->multi) 99713498266Sopenharmony_ci data->multi->ssl_seeded = TRUE; 99813498266Sopenharmony_ci return CURLE_OK; 99913498266Sopenharmony_ci } 100013498266Sopenharmony_ci#ifdef HAVE_RANDOM_INIT_BY_DEFAULT 100113498266Sopenharmony_ci /* with OpenSSL 1.1.0+, a failed RAND_status is a showstopper */ 100213498266Sopenharmony_ci failf(data, "Insufficient randomness"); 100313498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 100413498266Sopenharmony_ci#else 100513498266Sopenharmony_ci 100613498266Sopenharmony_ci#ifdef RANDOM_FILE 100713498266Sopenharmony_ci RAND_load_file(RANDOM_FILE, RAND_LOAD_LENGTH); 100813498266Sopenharmony_ci if(rand_enough()) 100913498266Sopenharmony_ci return CURLE_OK; 101013498266Sopenharmony_ci#endif 101113498266Sopenharmony_ci 101213498266Sopenharmony_ci /* fallback to a custom seeding of the PRNG using a hash based on a current 101313498266Sopenharmony_ci time */ 101413498266Sopenharmony_ci do { 101513498266Sopenharmony_ci unsigned char randb[64]; 101613498266Sopenharmony_ci size_t len = sizeof(randb); 101713498266Sopenharmony_ci size_t i, i_max; 101813498266Sopenharmony_ci for(i = 0, i_max = len / sizeof(struct curltime); i < i_max; ++i) { 101913498266Sopenharmony_ci struct curltime tv = Curl_now(); 102013498266Sopenharmony_ci Curl_wait_ms(1); 102113498266Sopenharmony_ci tv.tv_sec *= i + 1; 102213498266Sopenharmony_ci tv.tv_usec *= (unsigned int)i + 2; 102313498266Sopenharmony_ci tv.tv_sec ^= ((Curl_now().tv_sec + Curl_now().tv_usec) * 102413498266Sopenharmony_ci (i + 3)) << 8; 102513498266Sopenharmony_ci tv.tv_usec ^= (unsigned int) ((Curl_now().tv_sec + 102613498266Sopenharmony_ci Curl_now().tv_usec) * 102713498266Sopenharmony_ci (i + 4)) << 16; 102813498266Sopenharmony_ci memcpy(&randb[i * sizeof(struct curltime)], &tv, 102913498266Sopenharmony_ci sizeof(struct curltime)); 103013498266Sopenharmony_ci } 103113498266Sopenharmony_ci RAND_add(randb, (int)len, (double)len/2); 103213498266Sopenharmony_ci } while(!rand_enough()); 103313498266Sopenharmony_ci 103413498266Sopenharmony_ci { 103513498266Sopenharmony_ci /* generates a default path for the random seed file */ 103613498266Sopenharmony_ci char fname[256]; 103713498266Sopenharmony_ci fname[0] = 0; /* blank it first */ 103813498266Sopenharmony_ci RAND_file_name(fname, sizeof(fname)); 103913498266Sopenharmony_ci if(fname[0]) { 104013498266Sopenharmony_ci /* we got a file name to try */ 104113498266Sopenharmony_ci RAND_load_file(fname, RAND_LOAD_LENGTH); 104213498266Sopenharmony_ci if(rand_enough()) 104313498266Sopenharmony_ci return CURLE_OK; 104413498266Sopenharmony_ci } 104513498266Sopenharmony_ci } 104613498266Sopenharmony_ci 104713498266Sopenharmony_ci infof(data, "libcurl is now using a weak random seed"); 104813498266Sopenharmony_ci return (rand_enough() ? CURLE_OK : 104913498266Sopenharmony_ci CURLE_SSL_CONNECT_ERROR /* confusing error code */); 105013498266Sopenharmony_ci#endif 105113498266Sopenharmony_ci} 105213498266Sopenharmony_ci 105313498266Sopenharmony_ci#ifndef SSL_FILETYPE_ENGINE 105413498266Sopenharmony_ci#define SSL_FILETYPE_ENGINE 42 105513498266Sopenharmony_ci#endif 105613498266Sopenharmony_ci#ifndef SSL_FILETYPE_PKCS12 105713498266Sopenharmony_ci#define SSL_FILETYPE_PKCS12 43 105813498266Sopenharmony_ci#endif 105913498266Sopenharmony_cistatic int do_file_type(const char *type) 106013498266Sopenharmony_ci{ 106113498266Sopenharmony_ci if(!type || !type[0]) 106213498266Sopenharmony_ci return SSL_FILETYPE_PEM; 106313498266Sopenharmony_ci if(strcasecompare(type, "PEM")) 106413498266Sopenharmony_ci return SSL_FILETYPE_PEM; 106513498266Sopenharmony_ci if(strcasecompare(type, "DER")) 106613498266Sopenharmony_ci return SSL_FILETYPE_ASN1; 106713498266Sopenharmony_ci if(strcasecompare(type, "ENG")) 106813498266Sopenharmony_ci return SSL_FILETYPE_ENGINE; 106913498266Sopenharmony_ci if(strcasecompare(type, "P12")) 107013498266Sopenharmony_ci return SSL_FILETYPE_PKCS12; 107113498266Sopenharmony_ci return -1; 107213498266Sopenharmony_ci} 107313498266Sopenharmony_ci 107413498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 107513498266Sopenharmony_ci/* 107613498266Sopenharmony_ci * Supply default password to the engine user interface conversation. 107713498266Sopenharmony_ci * The password is passed by OpenSSL engine from ENGINE_load_private_key() 107813498266Sopenharmony_ci * last argument to the ui and can be obtained by UI_get0_user_data(ui) here. 107913498266Sopenharmony_ci */ 108013498266Sopenharmony_cistatic int ssl_ui_reader(UI *ui, UI_STRING *uis) 108113498266Sopenharmony_ci{ 108213498266Sopenharmony_ci const char *password; 108313498266Sopenharmony_ci switch(UI_get_string_type(uis)) { 108413498266Sopenharmony_ci case UIT_PROMPT: 108513498266Sopenharmony_ci case UIT_VERIFY: 108613498266Sopenharmony_ci password = (const char *)UI_get0_user_data(ui); 108713498266Sopenharmony_ci if(password && (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { 108813498266Sopenharmony_ci UI_set_result(ui, uis, password); 108913498266Sopenharmony_ci return 1; 109013498266Sopenharmony_ci } 109113498266Sopenharmony_ci FALLTHROUGH(); 109213498266Sopenharmony_ci default: 109313498266Sopenharmony_ci break; 109413498266Sopenharmony_ci } 109513498266Sopenharmony_ci return (UI_method_get_reader(UI_OpenSSL()))(ui, uis); 109613498266Sopenharmony_ci} 109713498266Sopenharmony_ci 109813498266Sopenharmony_ci/* 109913498266Sopenharmony_ci * Suppress interactive request for a default password if available. 110013498266Sopenharmony_ci */ 110113498266Sopenharmony_cistatic int ssl_ui_writer(UI *ui, UI_STRING *uis) 110213498266Sopenharmony_ci{ 110313498266Sopenharmony_ci switch(UI_get_string_type(uis)) { 110413498266Sopenharmony_ci case UIT_PROMPT: 110513498266Sopenharmony_ci case UIT_VERIFY: 110613498266Sopenharmony_ci if(UI_get0_user_data(ui) && 110713498266Sopenharmony_ci (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD)) { 110813498266Sopenharmony_ci return 1; 110913498266Sopenharmony_ci } 111013498266Sopenharmony_ci FALLTHROUGH(); 111113498266Sopenharmony_ci default: 111213498266Sopenharmony_ci break; 111313498266Sopenharmony_ci } 111413498266Sopenharmony_ci return (UI_method_get_writer(UI_OpenSSL()))(ui, uis); 111513498266Sopenharmony_ci} 111613498266Sopenharmony_ci 111713498266Sopenharmony_ci/* 111813498266Sopenharmony_ci * Check if a given string is a PKCS#11 URI 111913498266Sopenharmony_ci */ 112013498266Sopenharmony_cistatic bool is_pkcs11_uri(const char *string) 112113498266Sopenharmony_ci{ 112213498266Sopenharmony_ci return (string && strncasecompare(string, "pkcs11:", 7)); 112313498266Sopenharmony_ci} 112413498266Sopenharmony_ci 112513498266Sopenharmony_ci#endif 112613498266Sopenharmony_ci 112713498266Sopenharmony_cistatic CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine); 112813498266Sopenharmony_ci 112913498266Sopenharmony_cistatic int 113013498266Sopenharmony_ciSSL_CTX_use_certificate_blob(SSL_CTX *ctx, const struct curl_blob *blob, 113113498266Sopenharmony_ci int type, const char *key_passwd) 113213498266Sopenharmony_ci{ 113313498266Sopenharmony_ci int ret = 0; 113413498266Sopenharmony_ci X509 *x = NULL; 113513498266Sopenharmony_ci /* the typecast of blob->len is fine since it is guaranteed to never be 113613498266Sopenharmony_ci larger than CURL_MAX_INPUT_LENGTH */ 113713498266Sopenharmony_ci BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); 113813498266Sopenharmony_ci if(!in) 113913498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 114013498266Sopenharmony_ci 114113498266Sopenharmony_ci if(type == SSL_FILETYPE_ASN1) { 114213498266Sopenharmony_ci /* j = ERR_R_ASN1_LIB; */ 114313498266Sopenharmony_ci x = d2i_X509_bio(in, NULL); 114413498266Sopenharmony_ci } 114513498266Sopenharmony_ci else if(type == SSL_FILETYPE_PEM) { 114613498266Sopenharmony_ci /* ERR_R_PEM_LIB; */ 114713498266Sopenharmony_ci x = PEM_read_bio_X509(in, NULL, 114813498266Sopenharmony_ci passwd_callback, (void *)key_passwd); 114913498266Sopenharmony_ci } 115013498266Sopenharmony_ci else { 115113498266Sopenharmony_ci ret = 0; 115213498266Sopenharmony_ci goto end; 115313498266Sopenharmony_ci } 115413498266Sopenharmony_ci 115513498266Sopenharmony_ci if(!x) { 115613498266Sopenharmony_ci ret = 0; 115713498266Sopenharmony_ci goto end; 115813498266Sopenharmony_ci } 115913498266Sopenharmony_ci 116013498266Sopenharmony_ci ret = SSL_CTX_use_certificate(ctx, x); 116113498266Sopenharmony_ciend: 116213498266Sopenharmony_ci X509_free(x); 116313498266Sopenharmony_ci BIO_free(in); 116413498266Sopenharmony_ci return ret; 116513498266Sopenharmony_ci} 116613498266Sopenharmony_ci 116713498266Sopenharmony_cistatic int 116813498266Sopenharmony_ciSSL_CTX_use_PrivateKey_blob(SSL_CTX *ctx, const struct curl_blob *blob, 116913498266Sopenharmony_ci int type, const char *key_passwd) 117013498266Sopenharmony_ci{ 117113498266Sopenharmony_ci int ret = 0; 117213498266Sopenharmony_ci EVP_PKEY *pkey = NULL; 117313498266Sopenharmony_ci BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); 117413498266Sopenharmony_ci if(!in) 117513498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 117613498266Sopenharmony_ci 117713498266Sopenharmony_ci if(type == SSL_FILETYPE_PEM) 117813498266Sopenharmony_ci pkey = PEM_read_bio_PrivateKey(in, NULL, passwd_callback, 117913498266Sopenharmony_ci (void *)key_passwd); 118013498266Sopenharmony_ci else if(type == SSL_FILETYPE_ASN1) 118113498266Sopenharmony_ci pkey = d2i_PrivateKey_bio(in, NULL); 118213498266Sopenharmony_ci else { 118313498266Sopenharmony_ci ret = 0; 118413498266Sopenharmony_ci goto end; 118513498266Sopenharmony_ci } 118613498266Sopenharmony_ci if(!pkey) { 118713498266Sopenharmony_ci ret = 0; 118813498266Sopenharmony_ci goto end; 118913498266Sopenharmony_ci } 119013498266Sopenharmony_ci ret = SSL_CTX_use_PrivateKey(ctx, pkey); 119113498266Sopenharmony_ci EVP_PKEY_free(pkey); 119213498266Sopenharmony_ciend: 119313498266Sopenharmony_ci BIO_free(in); 119413498266Sopenharmony_ci return ret; 119513498266Sopenharmony_ci} 119613498266Sopenharmony_ci 119713498266Sopenharmony_cistatic int 119813498266Sopenharmony_ciSSL_CTX_use_certificate_chain_blob(SSL_CTX *ctx, const struct curl_blob *blob, 119913498266Sopenharmony_ci const char *key_passwd) 120013498266Sopenharmony_ci{ 120113498266Sopenharmony_ci/* SSL_CTX_add1_chain_cert introduced in OpenSSL 1.0.2 */ 120213498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x1000200fL) && /* OpenSSL 1.0.2 or later */ \ 120313498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 120413498266Sopenharmony_ci (LIBRESSL_VERSION_NUMBER < 0x2090100fL)) /* LibreSSL 2.9.1 or later */ 120513498266Sopenharmony_ci int ret = 0; 120613498266Sopenharmony_ci X509 *x = NULL; 120713498266Sopenharmony_ci void *passwd_callback_userdata = (void *)key_passwd; 120813498266Sopenharmony_ci BIO *in = BIO_new_mem_buf(blob->data, (int)(blob->len)); 120913498266Sopenharmony_ci if(!in) 121013498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 121113498266Sopenharmony_ci 121213498266Sopenharmony_ci ERR_clear_error(); 121313498266Sopenharmony_ci 121413498266Sopenharmony_ci x = PEM_read_bio_X509_AUX(in, NULL, 121513498266Sopenharmony_ci passwd_callback, (void *)key_passwd); 121613498266Sopenharmony_ci 121713498266Sopenharmony_ci if(!x) { 121813498266Sopenharmony_ci ret = 0; 121913498266Sopenharmony_ci goto end; 122013498266Sopenharmony_ci } 122113498266Sopenharmony_ci 122213498266Sopenharmony_ci ret = SSL_CTX_use_certificate(ctx, x); 122313498266Sopenharmony_ci 122413498266Sopenharmony_ci if(ERR_peek_error() != 0) 122513498266Sopenharmony_ci ret = 0; 122613498266Sopenharmony_ci 122713498266Sopenharmony_ci if(ret) { 122813498266Sopenharmony_ci X509 *ca; 122913498266Sopenharmony_ci sslerr_t err; 123013498266Sopenharmony_ci 123113498266Sopenharmony_ci if(!SSL_CTX_clear_chain_certs(ctx)) { 123213498266Sopenharmony_ci ret = 0; 123313498266Sopenharmony_ci goto end; 123413498266Sopenharmony_ci } 123513498266Sopenharmony_ci 123613498266Sopenharmony_ci while((ca = PEM_read_bio_X509(in, NULL, passwd_callback, 123713498266Sopenharmony_ci passwd_callback_userdata)) 123813498266Sopenharmony_ci != NULL) { 123913498266Sopenharmony_ci 124013498266Sopenharmony_ci if(!SSL_CTX_add0_chain_cert(ctx, ca)) { 124113498266Sopenharmony_ci X509_free(ca); 124213498266Sopenharmony_ci ret = 0; 124313498266Sopenharmony_ci goto end; 124413498266Sopenharmony_ci } 124513498266Sopenharmony_ci } 124613498266Sopenharmony_ci 124713498266Sopenharmony_ci err = ERR_peek_last_error(); 124813498266Sopenharmony_ci if((ERR_GET_LIB(err) == ERR_LIB_PEM) && 124913498266Sopenharmony_ci (ERR_GET_REASON(err) == PEM_R_NO_START_LINE)) 125013498266Sopenharmony_ci ERR_clear_error(); 125113498266Sopenharmony_ci else 125213498266Sopenharmony_ci ret = 0; 125313498266Sopenharmony_ci } 125413498266Sopenharmony_ci 125513498266Sopenharmony_ciend: 125613498266Sopenharmony_ci X509_free(x); 125713498266Sopenharmony_ci BIO_free(in); 125813498266Sopenharmony_ci return ret; 125913498266Sopenharmony_ci#else 126013498266Sopenharmony_ci (void)ctx; /* unused */ 126113498266Sopenharmony_ci (void)blob; /* unused */ 126213498266Sopenharmony_ci (void)key_passwd; /* unused */ 126313498266Sopenharmony_ci return 0; 126413498266Sopenharmony_ci#endif 126513498266Sopenharmony_ci} 126613498266Sopenharmony_ci 126713498266Sopenharmony_cistatic 126813498266Sopenharmony_ciint cert_stuff(struct Curl_easy *data, 126913498266Sopenharmony_ci SSL_CTX* ctx, 127013498266Sopenharmony_ci char *cert_file, 127113498266Sopenharmony_ci const struct curl_blob *cert_blob, 127213498266Sopenharmony_ci const char *cert_type, 127313498266Sopenharmony_ci char *key_file, 127413498266Sopenharmony_ci const struct curl_blob *key_blob, 127513498266Sopenharmony_ci const char *key_type, 127613498266Sopenharmony_ci char *key_passwd) 127713498266Sopenharmony_ci{ 127813498266Sopenharmony_ci char error_buffer[256]; 127913498266Sopenharmony_ci bool check_privkey = TRUE; 128013498266Sopenharmony_ci 128113498266Sopenharmony_ci int file_type = do_file_type(cert_type); 128213498266Sopenharmony_ci 128313498266Sopenharmony_ci if(cert_file || cert_blob || (file_type == SSL_FILETYPE_ENGINE)) { 128413498266Sopenharmony_ci SSL *ssl; 128513498266Sopenharmony_ci X509 *x509; 128613498266Sopenharmony_ci int cert_done = 0; 128713498266Sopenharmony_ci int cert_use_result; 128813498266Sopenharmony_ci 128913498266Sopenharmony_ci if(key_passwd) { 129013498266Sopenharmony_ci /* set the password in the callback userdata */ 129113498266Sopenharmony_ci SSL_CTX_set_default_passwd_cb_userdata(ctx, key_passwd); 129213498266Sopenharmony_ci /* Set passwd callback: */ 129313498266Sopenharmony_ci SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); 129413498266Sopenharmony_ci } 129513498266Sopenharmony_ci 129613498266Sopenharmony_ci 129713498266Sopenharmony_ci switch(file_type) { 129813498266Sopenharmony_ci case SSL_FILETYPE_PEM: 129913498266Sopenharmony_ci /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ 130013498266Sopenharmony_ci cert_use_result = cert_blob ? 130113498266Sopenharmony_ci SSL_CTX_use_certificate_chain_blob(ctx, cert_blob, key_passwd) : 130213498266Sopenharmony_ci SSL_CTX_use_certificate_chain_file(ctx, cert_file); 130313498266Sopenharmony_ci if(cert_use_result != 1) { 130413498266Sopenharmony_ci failf(data, 130513498266Sopenharmony_ci "could not load PEM client certificate from %s, " OSSL_PACKAGE 130613498266Sopenharmony_ci " error %s, " 130713498266Sopenharmony_ci "(no key found, wrong pass phrase, or wrong file format?)", 130813498266Sopenharmony_ci (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file), 130913498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 131013498266Sopenharmony_ci sizeof(error_buffer)) ); 131113498266Sopenharmony_ci return 0; 131213498266Sopenharmony_ci } 131313498266Sopenharmony_ci break; 131413498266Sopenharmony_ci 131513498266Sopenharmony_ci case SSL_FILETYPE_ASN1: 131613498266Sopenharmony_ci /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but 131713498266Sopenharmony_ci we use the case above for PEM so this can only be performed with 131813498266Sopenharmony_ci ASN1 files. */ 131913498266Sopenharmony_ci 132013498266Sopenharmony_ci cert_use_result = cert_blob ? 132113498266Sopenharmony_ci SSL_CTX_use_certificate_blob(ctx, cert_blob, 132213498266Sopenharmony_ci file_type, key_passwd) : 132313498266Sopenharmony_ci SSL_CTX_use_certificate_file(ctx, cert_file, file_type); 132413498266Sopenharmony_ci if(cert_use_result != 1) { 132513498266Sopenharmony_ci failf(data, 132613498266Sopenharmony_ci "could not load ASN1 client certificate from %s, " OSSL_PACKAGE 132713498266Sopenharmony_ci " error %s, " 132813498266Sopenharmony_ci "(no key found, wrong pass phrase, or wrong file format?)", 132913498266Sopenharmony_ci (cert_blob ? "CURLOPT_SSLCERT_BLOB" : cert_file), 133013498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 133113498266Sopenharmony_ci sizeof(error_buffer)) ); 133213498266Sopenharmony_ci return 0; 133313498266Sopenharmony_ci } 133413498266Sopenharmony_ci break; 133513498266Sopenharmony_ci case SSL_FILETYPE_ENGINE: 133613498266Sopenharmony_ci#if defined(USE_OPENSSL_ENGINE) && defined(ENGINE_CTRL_GET_CMD_FROM_NAME) 133713498266Sopenharmony_ci { 133813498266Sopenharmony_ci /* Implicitly use pkcs11 engine if none was provided and the 133913498266Sopenharmony_ci * cert_file is a PKCS#11 URI */ 134013498266Sopenharmony_ci if(!data->state.engine) { 134113498266Sopenharmony_ci if(is_pkcs11_uri(cert_file)) { 134213498266Sopenharmony_ci if(ossl_set_engine(data, "pkcs11") != CURLE_OK) { 134313498266Sopenharmony_ci return 0; 134413498266Sopenharmony_ci } 134513498266Sopenharmony_ci } 134613498266Sopenharmony_ci } 134713498266Sopenharmony_ci 134813498266Sopenharmony_ci if(data->state.engine) { 134913498266Sopenharmony_ci const char *cmd_name = "LOAD_CERT_CTRL"; 135013498266Sopenharmony_ci struct { 135113498266Sopenharmony_ci const char *cert_id; 135213498266Sopenharmony_ci X509 *cert; 135313498266Sopenharmony_ci } params; 135413498266Sopenharmony_ci 135513498266Sopenharmony_ci params.cert_id = cert_file; 135613498266Sopenharmony_ci params.cert = NULL; 135713498266Sopenharmony_ci 135813498266Sopenharmony_ci /* Does the engine supports LOAD_CERT_CTRL ? */ 135913498266Sopenharmony_ci if(!ENGINE_ctrl(data->state.engine, ENGINE_CTRL_GET_CMD_FROM_NAME, 136013498266Sopenharmony_ci 0, (void *)cmd_name, NULL)) { 136113498266Sopenharmony_ci failf(data, "ssl engine does not support loading certificates"); 136213498266Sopenharmony_ci return 0; 136313498266Sopenharmony_ci } 136413498266Sopenharmony_ci 136513498266Sopenharmony_ci /* Load the certificate from the engine */ 136613498266Sopenharmony_ci if(!ENGINE_ctrl_cmd(data->state.engine, cmd_name, 136713498266Sopenharmony_ci 0, ¶ms, NULL, 1)) { 136813498266Sopenharmony_ci failf(data, "ssl engine cannot load client cert with id" 136913498266Sopenharmony_ci " '%s' [%s]", cert_file, 137013498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 137113498266Sopenharmony_ci sizeof(error_buffer))); 137213498266Sopenharmony_ci return 0; 137313498266Sopenharmony_ci } 137413498266Sopenharmony_ci 137513498266Sopenharmony_ci if(!params.cert) { 137613498266Sopenharmony_ci failf(data, "ssl engine didn't initialized the certificate " 137713498266Sopenharmony_ci "properly."); 137813498266Sopenharmony_ci return 0; 137913498266Sopenharmony_ci } 138013498266Sopenharmony_ci 138113498266Sopenharmony_ci if(SSL_CTX_use_certificate(ctx, params.cert) != 1) { 138213498266Sopenharmony_ci failf(data, "unable to set client certificate [%s]", 138313498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 138413498266Sopenharmony_ci sizeof(error_buffer))); 138513498266Sopenharmony_ci return 0; 138613498266Sopenharmony_ci } 138713498266Sopenharmony_ci X509_free(params.cert); /* we don't need the handle any more... */ 138813498266Sopenharmony_ci } 138913498266Sopenharmony_ci else { 139013498266Sopenharmony_ci failf(data, "crypto engine not set, can't load certificate"); 139113498266Sopenharmony_ci return 0; 139213498266Sopenharmony_ci } 139313498266Sopenharmony_ci } 139413498266Sopenharmony_ci break; 139513498266Sopenharmony_ci#else 139613498266Sopenharmony_ci failf(data, "file type ENG for certificate not implemented"); 139713498266Sopenharmony_ci return 0; 139813498266Sopenharmony_ci#endif 139913498266Sopenharmony_ci 140013498266Sopenharmony_ci case SSL_FILETYPE_PKCS12: 140113498266Sopenharmony_ci { 140213498266Sopenharmony_ci BIO *cert_bio = NULL; 140313498266Sopenharmony_ci PKCS12 *p12 = NULL; 140413498266Sopenharmony_ci EVP_PKEY *pri; 140513498266Sopenharmony_ci STACK_OF(X509) *ca = NULL; 140613498266Sopenharmony_ci if(cert_blob) { 140713498266Sopenharmony_ci cert_bio = BIO_new_mem_buf(cert_blob->data, (int)(cert_blob->len)); 140813498266Sopenharmony_ci if(!cert_bio) { 140913498266Sopenharmony_ci failf(data, 141013498266Sopenharmony_ci "BIO_new_mem_buf NULL, " OSSL_PACKAGE 141113498266Sopenharmony_ci " error %s", 141213498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 141313498266Sopenharmony_ci sizeof(error_buffer)) ); 141413498266Sopenharmony_ci return 0; 141513498266Sopenharmony_ci } 141613498266Sopenharmony_ci } 141713498266Sopenharmony_ci else { 141813498266Sopenharmony_ci cert_bio = BIO_new(BIO_s_file()); 141913498266Sopenharmony_ci if(!cert_bio) { 142013498266Sopenharmony_ci failf(data, 142113498266Sopenharmony_ci "BIO_new return NULL, " OSSL_PACKAGE 142213498266Sopenharmony_ci " error %s", 142313498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 142413498266Sopenharmony_ci sizeof(error_buffer)) ); 142513498266Sopenharmony_ci return 0; 142613498266Sopenharmony_ci } 142713498266Sopenharmony_ci 142813498266Sopenharmony_ci if(BIO_read_filename(cert_bio, cert_file) <= 0) { 142913498266Sopenharmony_ci failf(data, "could not open PKCS12 file '%s'", cert_file); 143013498266Sopenharmony_ci BIO_free(cert_bio); 143113498266Sopenharmony_ci return 0; 143213498266Sopenharmony_ci } 143313498266Sopenharmony_ci } 143413498266Sopenharmony_ci 143513498266Sopenharmony_ci p12 = d2i_PKCS12_bio(cert_bio, NULL); 143613498266Sopenharmony_ci BIO_free(cert_bio); 143713498266Sopenharmony_ci 143813498266Sopenharmony_ci if(!p12) { 143913498266Sopenharmony_ci failf(data, "error reading PKCS12 file '%s'", 144013498266Sopenharmony_ci cert_blob ? "(memory blob)" : cert_file); 144113498266Sopenharmony_ci return 0; 144213498266Sopenharmony_ci } 144313498266Sopenharmony_ci 144413498266Sopenharmony_ci PKCS12_PBE_add(); 144513498266Sopenharmony_ci 144613498266Sopenharmony_ci if(!PKCS12_parse(p12, key_passwd, &pri, &x509, 144713498266Sopenharmony_ci &ca)) { 144813498266Sopenharmony_ci failf(data, 144913498266Sopenharmony_ci "could not parse PKCS12 file, check password, " OSSL_PACKAGE 145013498266Sopenharmony_ci " error %s", 145113498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 145213498266Sopenharmony_ci sizeof(error_buffer)) ); 145313498266Sopenharmony_ci PKCS12_free(p12); 145413498266Sopenharmony_ci return 0; 145513498266Sopenharmony_ci } 145613498266Sopenharmony_ci 145713498266Sopenharmony_ci PKCS12_free(p12); 145813498266Sopenharmony_ci 145913498266Sopenharmony_ci if(SSL_CTX_use_certificate(ctx, x509) != 1) { 146013498266Sopenharmony_ci failf(data, 146113498266Sopenharmony_ci "could not load PKCS12 client certificate, " OSSL_PACKAGE 146213498266Sopenharmony_ci " error %s", 146313498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 146413498266Sopenharmony_ci sizeof(error_buffer)) ); 146513498266Sopenharmony_ci goto fail; 146613498266Sopenharmony_ci } 146713498266Sopenharmony_ci 146813498266Sopenharmony_ci if(SSL_CTX_use_PrivateKey(ctx, pri) != 1) { 146913498266Sopenharmony_ci failf(data, "unable to use private key from PKCS12 file '%s'", 147013498266Sopenharmony_ci cert_file); 147113498266Sopenharmony_ci goto fail; 147213498266Sopenharmony_ci } 147313498266Sopenharmony_ci 147413498266Sopenharmony_ci if(!SSL_CTX_check_private_key (ctx)) { 147513498266Sopenharmony_ci failf(data, "private key from PKCS12 file '%s' " 147613498266Sopenharmony_ci "does not match certificate in same file", cert_file); 147713498266Sopenharmony_ci goto fail; 147813498266Sopenharmony_ci } 147913498266Sopenharmony_ci /* Set Certificate Verification chain */ 148013498266Sopenharmony_ci if(ca) { 148113498266Sopenharmony_ci while(sk_X509_num(ca)) { 148213498266Sopenharmony_ci /* 148313498266Sopenharmony_ci * Note that sk_X509_pop() is used below to make sure the cert is 148413498266Sopenharmony_ci * removed from the stack properly before getting passed to 148513498266Sopenharmony_ci * SSL_CTX_add_extra_chain_cert(), which takes ownership. Previously 148613498266Sopenharmony_ci * we used sk_X509_value() instead, but then we'd clean it in the 148713498266Sopenharmony_ci * subsequent sk_X509_pop_free() call. 148813498266Sopenharmony_ci */ 148913498266Sopenharmony_ci X509 *x = sk_X509_pop(ca); 149013498266Sopenharmony_ci if(!SSL_CTX_add_client_CA(ctx, x)) { 149113498266Sopenharmony_ci X509_free(x); 149213498266Sopenharmony_ci failf(data, "cannot add certificate to client CA list"); 149313498266Sopenharmony_ci goto fail; 149413498266Sopenharmony_ci } 149513498266Sopenharmony_ci if(!SSL_CTX_add_extra_chain_cert(ctx, x)) { 149613498266Sopenharmony_ci X509_free(x); 149713498266Sopenharmony_ci failf(data, "cannot add certificate to certificate chain"); 149813498266Sopenharmony_ci goto fail; 149913498266Sopenharmony_ci } 150013498266Sopenharmony_ci } 150113498266Sopenharmony_ci } 150213498266Sopenharmony_ci 150313498266Sopenharmony_ci cert_done = 1; 150413498266Sopenharmony_cifail: 150513498266Sopenharmony_ci EVP_PKEY_free(pri); 150613498266Sopenharmony_ci X509_free(x509); 150713498266Sopenharmony_ci sk_X509_pop_free(ca, X509_free); 150813498266Sopenharmony_ci if(!cert_done) 150913498266Sopenharmony_ci return 0; /* failure! */ 151013498266Sopenharmony_ci break; 151113498266Sopenharmony_ci } 151213498266Sopenharmony_ci default: 151313498266Sopenharmony_ci failf(data, "not supported file type '%s' for certificate", cert_type); 151413498266Sopenharmony_ci return 0; 151513498266Sopenharmony_ci } 151613498266Sopenharmony_ci 151713498266Sopenharmony_ci if((!key_file) && (!key_blob)) { 151813498266Sopenharmony_ci key_file = cert_file; 151913498266Sopenharmony_ci key_blob = cert_blob; 152013498266Sopenharmony_ci } 152113498266Sopenharmony_ci else 152213498266Sopenharmony_ci file_type = do_file_type(key_type); 152313498266Sopenharmony_ci 152413498266Sopenharmony_ci switch(file_type) { 152513498266Sopenharmony_ci case SSL_FILETYPE_PEM: 152613498266Sopenharmony_ci if(cert_done) 152713498266Sopenharmony_ci break; 152813498266Sopenharmony_ci FALLTHROUGH(); 152913498266Sopenharmony_ci case SSL_FILETYPE_ASN1: 153013498266Sopenharmony_ci cert_use_result = key_blob ? 153113498266Sopenharmony_ci SSL_CTX_use_PrivateKey_blob(ctx, key_blob, file_type, key_passwd) : 153213498266Sopenharmony_ci SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type); 153313498266Sopenharmony_ci if(cert_use_result != 1) { 153413498266Sopenharmony_ci failf(data, "unable to set private key file: '%s' type %s", 153513498266Sopenharmony_ci key_file?key_file:"(memory blob)", key_type?key_type:"PEM"); 153613498266Sopenharmony_ci return 0; 153713498266Sopenharmony_ci } 153813498266Sopenharmony_ci break; 153913498266Sopenharmony_ci case SSL_FILETYPE_ENGINE: 154013498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 154113498266Sopenharmony_ci { 154213498266Sopenharmony_ci EVP_PKEY *priv_key = NULL; 154313498266Sopenharmony_ci 154413498266Sopenharmony_ci /* Implicitly use pkcs11 engine if none was provided and the 154513498266Sopenharmony_ci * key_file is a PKCS#11 URI */ 154613498266Sopenharmony_ci if(!data->state.engine) { 154713498266Sopenharmony_ci if(is_pkcs11_uri(key_file)) { 154813498266Sopenharmony_ci if(ossl_set_engine(data, "pkcs11") != CURLE_OK) { 154913498266Sopenharmony_ci return 0; 155013498266Sopenharmony_ci } 155113498266Sopenharmony_ci } 155213498266Sopenharmony_ci } 155313498266Sopenharmony_ci 155413498266Sopenharmony_ci if(data->state.engine) { 155513498266Sopenharmony_ci UI_METHOD *ui_method = 155613498266Sopenharmony_ci UI_create_method((char *)"curl user interface"); 155713498266Sopenharmony_ci if(!ui_method) { 155813498266Sopenharmony_ci failf(data, "unable do create " OSSL_PACKAGE 155913498266Sopenharmony_ci " user-interface method"); 156013498266Sopenharmony_ci return 0; 156113498266Sopenharmony_ci } 156213498266Sopenharmony_ci UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL())); 156313498266Sopenharmony_ci UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL())); 156413498266Sopenharmony_ci UI_method_set_reader(ui_method, ssl_ui_reader); 156513498266Sopenharmony_ci UI_method_set_writer(ui_method, ssl_ui_writer); 156613498266Sopenharmony_ci priv_key = ENGINE_load_private_key(data->state.engine, key_file, 156713498266Sopenharmony_ci ui_method, 156813498266Sopenharmony_ci key_passwd); 156913498266Sopenharmony_ci UI_destroy_method(ui_method); 157013498266Sopenharmony_ci if(!priv_key) { 157113498266Sopenharmony_ci failf(data, "failed to load private key from crypto engine"); 157213498266Sopenharmony_ci return 0; 157313498266Sopenharmony_ci } 157413498266Sopenharmony_ci if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { 157513498266Sopenharmony_ci failf(data, "unable to set private key"); 157613498266Sopenharmony_ci EVP_PKEY_free(priv_key); 157713498266Sopenharmony_ci return 0; 157813498266Sopenharmony_ci } 157913498266Sopenharmony_ci EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ 158013498266Sopenharmony_ci } 158113498266Sopenharmony_ci else { 158213498266Sopenharmony_ci failf(data, "crypto engine not set, can't load private key"); 158313498266Sopenharmony_ci return 0; 158413498266Sopenharmony_ci } 158513498266Sopenharmony_ci } 158613498266Sopenharmony_ci break; 158713498266Sopenharmony_ci#else 158813498266Sopenharmony_ci failf(data, "file type ENG for private key not supported"); 158913498266Sopenharmony_ci return 0; 159013498266Sopenharmony_ci#endif 159113498266Sopenharmony_ci case SSL_FILETYPE_PKCS12: 159213498266Sopenharmony_ci if(!cert_done) { 159313498266Sopenharmony_ci failf(data, "file type P12 for private key not supported"); 159413498266Sopenharmony_ci return 0; 159513498266Sopenharmony_ci } 159613498266Sopenharmony_ci break; 159713498266Sopenharmony_ci default: 159813498266Sopenharmony_ci failf(data, "not supported file type for private key"); 159913498266Sopenharmony_ci return 0; 160013498266Sopenharmony_ci } 160113498266Sopenharmony_ci 160213498266Sopenharmony_ci ssl = SSL_new(ctx); 160313498266Sopenharmony_ci if(!ssl) { 160413498266Sopenharmony_ci failf(data, "unable to create an SSL structure"); 160513498266Sopenharmony_ci return 0; 160613498266Sopenharmony_ci } 160713498266Sopenharmony_ci 160813498266Sopenharmony_ci x509 = SSL_get_certificate(ssl); 160913498266Sopenharmony_ci 161013498266Sopenharmony_ci /* This version was provided by Evan Jordan and is supposed to not 161113498266Sopenharmony_ci leak memory as the previous version: */ 161213498266Sopenharmony_ci if(x509) { 161313498266Sopenharmony_ci EVP_PKEY *pktmp = X509_get_pubkey(x509); 161413498266Sopenharmony_ci EVP_PKEY_copy_parameters(pktmp, SSL_get_privatekey(ssl)); 161513498266Sopenharmony_ci EVP_PKEY_free(pktmp); 161613498266Sopenharmony_ci } 161713498266Sopenharmony_ci 161813498266Sopenharmony_ci#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_IS_BORINGSSL) && \ 161913498266Sopenharmony_ci !defined(OPENSSL_NO_DEPRECATED_3_0) 162013498266Sopenharmony_ci { 162113498266Sopenharmony_ci /* If RSA is used, don't check the private key if its flags indicate 162213498266Sopenharmony_ci * it doesn't support it. */ 162313498266Sopenharmony_ci EVP_PKEY *priv_key = SSL_get_privatekey(ssl); 162413498266Sopenharmony_ci int pktype; 162513498266Sopenharmony_ci#ifdef HAVE_OPAQUE_EVP_PKEY 162613498266Sopenharmony_ci pktype = EVP_PKEY_id(priv_key); 162713498266Sopenharmony_ci#else 162813498266Sopenharmony_ci pktype = priv_key->type; 162913498266Sopenharmony_ci#endif 163013498266Sopenharmony_ci if(pktype == EVP_PKEY_RSA) { 163113498266Sopenharmony_ci RSA *rsa = EVP_PKEY_get1_RSA(priv_key); 163213498266Sopenharmony_ci if(RSA_flags(rsa) & RSA_METHOD_FLAG_NO_CHECK) 163313498266Sopenharmony_ci check_privkey = FALSE; 163413498266Sopenharmony_ci RSA_free(rsa); /* Decrement reference count */ 163513498266Sopenharmony_ci } 163613498266Sopenharmony_ci } 163713498266Sopenharmony_ci#endif 163813498266Sopenharmony_ci 163913498266Sopenharmony_ci SSL_free(ssl); 164013498266Sopenharmony_ci 164113498266Sopenharmony_ci /* If we are using DSA, we can copy the parameters from 164213498266Sopenharmony_ci * the private key */ 164313498266Sopenharmony_ci 164413498266Sopenharmony_ci if(check_privkey == TRUE) { 164513498266Sopenharmony_ci /* Now we know that a key and cert have been set against 164613498266Sopenharmony_ci * the SSL context */ 164713498266Sopenharmony_ci if(!SSL_CTX_check_private_key(ctx)) { 164813498266Sopenharmony_ci failf(data, "Private key does not match the certificate public key"); 164913498266Sopenharmony_ci return 0; 165013498266Sopenharmony_ci } 165113498266Sopenharmony_ci } 165213498266Sopenharmony_ci } 165313498266Sopenharmony_ci return 1; 165413498266Sopenharmony_ci} 165513498266Sopenharmony_ci 165613498266Sopenharmony_ciCURLcode Curl_ossl_set_client_cert(struct Curl_easy *data, SSL_CTX *ctx, 165713498266Sopenharmony_ci char *cert_file, 165813498266Sopenharmony_ci const struct curl_blob *cert_blob, 165913498266Sopenharmony_ci const char *cert_type, char *key_file, 166013498266Sopenharmony_ci const struct curl_blob *key_blob, 166113498266Sopenharmony_ci const char *key_type, char *key_passwd) 166213498266Sopenharmony_ci{ 166313498266Sopenharmony_ci int rv = cert_stuff(data, ctx, cert_file, cert_blob, cert_type, key_file, 166413498266Sopenharmony_ci key_blob, key_type, key_passwd); 166513498266Sopenharmony_ci if(rv != 1) { 166613498266Sopenharmony_ci return CURLE_SSL_CERTPROBLEM; 166713498266Sopenharmony_ci } 166813498266Sopenharmony_ci 166913498266Sopenharmony_ci return CURLE_OK; 167013498266Sopenharmony_ci} 167113498266Sopenharmony_ci 167213498266Sopenharmony_ci/* returns non-zero on failure */ 167313498266Sopenharmony_cistatic int x509_name_oneline(X509_NAME *a, char *buf, size_t size) 167413498266Sopenharmony_ci{ 167513498266Sopenharmony_ci BIO *bio_out = BIO_new(BIO_s_mem()); 167613498266Sopenharmony_ci BUF_MEM *biomem; 167713498266Sopenharmony_ci int rc; 167813498266Sopenharmony_ci 167913498266Sopenharmony_ci if(!bio_out) 168013498266Sopenharmony_ci return 1; /* alloc failed! */ 168113498266Sopenharmony_ci 168213498266Sopenharmony_ci rc = X509_NAME_print_ex(bio_out, a, 0, XN_FLAG_SEP_SPLUS_SPC); 168313498266Sopenharmony_ci BIO_get_mem_ptr(bio_out, &biomem); 168413498266Sopenharmony_ci 168513498266Sopenharmony_ci if((size_t)biomem->length < size) 168613498266Sopenharmony_ci size = biomem->length; 168713498266Sopenharmony_ci else 168813498266Sopenharmony_ci size--; /* don't overwrite the buffer end */ 168913498266Sopenharmony_ci 169013498266Sopenharmony_ci memcpy(buf, biomem->data, size); 169113498266Sopenharmony_ci buf[size] = 0; 169213498266Sopenharmony_ci 169313498266Sopenharmony_ci BIO_free(bio_out); 169413498266Sopenharmony_ci 169513498266Sopenharmony_ci return !rc; 169613498266Sopenharmony_ci} 169713498266Sopenharmony_ci 169813498266Sopenharmony_ci/** 169913498266Sopenharmony_ci * Global SSL init 170013498266Sopenharmony_ci * 170113498266Sopenharmony_ci * @retval 0 error initializing SSL 170213498266Sopenharmony_ci * @retval 1 SSL initialized successfully 170313498266Sopenharmony_ci */ 170413498266Sopenharmony_cistatic int ossl_init(void) 170513498266Sopenharmony_ci{ 170613498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ 170713498266Sopenharmony_ci (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x2070000fL) 170813498266Sopenharmony_ci const uint64_t flags = 170913498266Sopenharmony_ci#ifdef OPENSSL_INIT_ENGINE_ALL_BUILTIN 171013498266Sopenharmony_ci /* not present in BoringSSL */ 171113498266Sopenharmony_ci OPENSSL_INIT_ENGINE_ALL_BUILTIN | 171213498266Sopenharmony_ci#endif 171313498266Sopenharmony_ci#ifdef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 171413498266Sopenharmony_ci OPENSSL_INIT_NO_LOAD_CONFIG | 171513498266Sopenharmony_ci#else 171613498266Sopenharmony_ci OPENSSL_INIT_LOAD_CONFIG | 171713498266Sopenharmony_ci#endif 171813498266Sopenharmony_ci 0; 171913498266Sopenharmony_ci OPENSSL_init_ssl(flags, NULL); 172013498266Sopenharmony_ci#else 172113498266Sopenharmony_ci OPENSSL_load_builtin_modules(); 172213498266Sopenharmony_ci 172313498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 172413498266Sopenharmony_ci ENGINE_load_builtin_engines(); 172513498266Sopenharmony_ci#endif 172613498266Sopenharmony_ci 172713498266Sopenharmony_ci/* CONF_MFLAGS_DEFAULT_SECTION was introduced some time between 0.9.8b and 172813498266Sopenharmony_ci 0.9.8e */ 172913498266Sopenharmony_ci#ifndef CONF_MFLAGS_DEFAULT_SECTION 173013498266Sopenharmony_ci#define CONF_MFLAGS_DEFAULT_SECTION 0x0 173113498266Sopenharmony_ci#endif 173213498266Sopenharmony_ci 173313498266Sopenharmony_ci#ifndef CURL_DISABLE_OPENSSL_AUTO_LOAD_CONFIG 173413498266Sopenharmony_ci CONF_modules_load_file(NULL, NULL, 173513498266Sopenharmony_ci CONF_MFLAGS_DEFAULT_SECTION| 173613498266Sopenharmony_ci CONF_MFLAGS_IGNORE_MISSING_FILE); 173713498266Sopenharmony_ci#endif 173813498266Sopenharmony_ci 173913498266Sopenharmony_ci /* Let's get nice error messages */ 174013498266Sopenharmony_ci SSL_load_error_strings(); 174113498266Sopenharmony_ci 174213498266Sopenharmony_ci /* Init the global ciphers and digests */ 174313498266Sopenharmony_ci if(!SSLeay_add_ssl_algorithms()) 174413498266Sopenharmony_ci return 0; 174513498266Sopenharmony_ci 174613498266Sopenharmony_ci OpenSSL_add_all_algorithms(); 174713498266Sopenharmony_ci#endif 174813498266Sopenharmony_ci 174913498266Sopenharmony_ci Curl_tls_keylog_open(); 175013498266Sopenharmony_ci 175113498266Sopenharmony_ci return 1; 175213498266Sopenharmony_ci} 175313498266Sopenharmony_ci 175413498266Sopenharmony_ci/* Global cleanup */ 175513498266Sopenharmony_cistatic void ossl_cleanup(void) 175613498266Sopenharmony_ci{ 175713498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ 175813498266Sopenharmony_ci (!defined(LIBRESSL_VERSION_NUMBER) || LIBRESSL_VERSION_NUMBER >= 0x2070000fL) 175913498266Sopenharmony_ci /* OpenSSL 1.1 deprecates all these cleanup functions and 176013498266Sopenharmony_ci turns them into no-ops in OpenSSL 1.0 compatibility mode */ 176113498266Sopenharmony_ci#else 176213498266Sopenharmony_ci /* Free ciphers and digests lists */ 176313498266Sopenharmony_ci EVP_cleanup(); 176413498266Sopenharmony_ci 176513498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 176613498266Sopenharmony_ci /* Free engine list */ 176713498266Sopenharmony_ci ENGINE_cleanup(); 176813498266Sopenharmony_ci#endif 176913498266Sopenharmony_ci 177013498266Sopenharmony_ci /* Free OpenSSL error strings */ 177113498266Sopenharmony_ci ERR_free_strings(); 177213498266Sopenharmony_ci 177313498266Sopenharmony_ci /* Free thread local error state, destroying hash upon zero refcount */ 177413498266Sopenharmony_ci#ifdef HAVE_ERR_REMOVE_THREAD_STATE 177513498266Sopenharmony_ci ERR_remove_thread_state(NULL); 177613498266Sopenharmony_ci#else 177713498266Sopenharmony_ci ERR_remove_state(0); 177813498266Sopenharmony_ci#endif 177913498266Sopenharmony_ci 178013498266Sopenharmony_ci /* Free all memory allocated by all configuration modules */ 178113498266Sopenharmony_ci CONF_modules_free(); 178213498266Sopenharmony_ci 178313498266Sopenharmony_ci#ifdef HAVE_SSL_COMP_FREE_COMPRESSION_METHODS 178413498266Sopenharmony_ci SSL_COMP_free_compression_methods(); 178513498266Sopenharmony_ci#endif 178613498266Sopenharmony_ci#endif 178713498266Sopenharmony_ci 178813498266Sopenharmony_ci Curl_tls_keylog_close(); 178913498266Sopenharmony_ci} 179013498266Sopenharmony_ci 179113498266Sopenharmony_ci/* Selects an OpenSSL crypto engine 179213498266Sopenharmony_ci */ 179313498266Sopenharmony_cistatic CURLcode ossl_set_engine(struct Curl_easy *data, const char *engine) 179413498266Sopenharmony_ci{ 179513498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 179613498266Sopenharmony_ci ENGINE *e; 179713498266Sopenharmony_ci 179813498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x00909000L 179913498266Sopenharmony_ci e = ENGINE_by_id(engine); 180013498266Sopenharmony_ci#else 180113498266Sopenharmony_ci /* avoid memory leak */ 180213498266Sopenharmony_ci for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { 180313498266Sopenharmony_ci const char *e_id = ENGINE_get_id(e); 180413498266Sopenharmony_ci if(!strcmp(engine, e_id)) 180513498266Sopenharmony_ci break; 180613498266Sopenharmony_ci } 180713498266Sopenharmony_ci#endif 180813498266Sopenharmony_ci 180913498266Sopenharmony_ci if(!e) { 181013498266Sopenharmony_ci failf(data, "SSL Engine '%s' not found", engine); 181113498266Sopenharmony_ci return CURLE_SSL_ENGINE_NOTFOUND; 181213498266Sopenharmony_ci } 181313498266Sopenharmony_ci 181413498266Sopenharmony_ci if(data->state.engine) { 181513498266Sopenharmony_ci ENGINE_finish(data->state.engine); 181613498266Sopenharmony_ci ENGINE_free(data->state.engine); 181713498266Sopenharmony_ci data->state.engine = NULL; 181813498266Sopenharmony_ci } 181913498266Sopenharmony_ci if(!ENGINE_init(e)) { 182013498266Sopenharmony_ci char buf[256]; 182113498266Sopenharmony_ci 182213498266Sopenharmony_ci ENGINE_free(e); 182313498266Sopenharmony_ci failf(data, "Failed to initialise SSL Engine '%s': %s", 182413498266Sopenharmony_ci engine, ossl_strerror(ERR_get_error(), buf, sizeof(buf))); 182513498266Sopenharmony_ci return CURLE_SSL_ENGINE_INITFAILED; 182613498266Sopenharmony_ci } 182713498266Sopenharmony_ci data->state.engine = e; 182813498266Sopenharmony_ci return CURLE_OK; 182913498266Sopenharmony_ci#else 183013498266Sopenharmony_ci (void)engine; 183113498266Sopenharmony_ci failf(data, "SSL Engine not supported"); 183213498266Sopenharmony_ci return CURLE_SSL_ENGINE_NOTFOUND; 183313498266Sopenharmony_ci#endif 183413498266Sopenharmony_ci} 183513498266Sopenharmony_ci 183613498266Sopenharmony_ci/* Sets engine as default for all SSL operations 183713498266Sopenharmony_ci */ 183813498266Sopenharmony_cistatic CURLcode ossl_set_engine_default(struct Curl_easy *data) 183913498266Sopenharmony_ci{ 184013498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 184113498266Sopenharmony_ci if(data->state.engine) { 184213498266Sopenharmony_ci if(ENGINE_set_default(data->state.engine, ENGINE_METHOD_ALL) > 0) { 184313498266Sopenharmony_ci infof(data, "set default crypto engine '%s'", 184413498266Sopenharmony_ci ENGINE_get_id(data->state.engine)); 184513498266Sopenharmony_ci } 184613498266Sopenharmony_ci else { 184713498266Sopenharmony_ci failf(data, "set default crypto engine '%s' failed", 184813498266Sopenharmony_ci ENGINE_get_id(data->state.engine)); 184913498266Sopenharmony_ci return CURLE_SSL_ENGINE_SETFAILED; 185013498266Sopenharmony_ci } 185113498266Sopenharmony_ci } 185213498266Sopenharmony_ci#else 185313498266Sopenharmony_ci (void) data; 185413498266Sopenharmony_ci#endif 185513498266Sopenharmony_ci return CURLE_OK; 185613498266Sopenharmony_ci} 185713498266Sopenharmony_ci 185813498266Sopenharmony_ci/* Return list of OpenSSL crypto engine names. 185913498266Sopenharmony_ci */ 186013498266Sopenharmony_cistatic struct curl_slist *ossl_engines_list(struct Curl_easy *data) 186113498266Sopenharmony_ci{ 186213498266Sopenharmony_ci struct curl_slist *list = NULL; 186313498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 186413498266Sopenharmony_ci struct curl_slist *beg; 186513498266Sopenharmony_ci ENGINE *e; 186613498266Sopenharmony_ci 186713498266Sopenharmony_ci for(e = ENGINE_get_first(); e; e = ENGINE_get_next(e)) { 186813498266Sopenharmony_ci beg = curl_slist_append(list, ENGINE_get_id(e)); 186913498266Sopenharmony_ci if(!beg) { 187013498266Sopenharmony_ci curl_slist_free_all(list); 187113498266Sopenharmony_ci return NULL; 187213498266Sopenharmony_ci } 187313498266Sopenharmony_ci list = beg; 187413498266Sopenharmony_ci } 187513498266Sopenharmony_ci#endif 187613498266Sopenharmony_ci (void) data; 187713498266Sopenharmony_ci return list; 187813498266Sopenharmony_ci} 187913498266Sopenharmony_ci 188013498266Sopenharmony_cistatic void ossl_close(struct Curl_cfilter *cf, struct Curl_easy *data) 188113498266Sopenharmony_ci{ 188213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 188313498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 188413498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 188513498266Sopenharmony_ci 188613498266Sopenharmony_ci (void)data; 188713498266Sopenharmony_ci DEBUGASSERT(backend); 188813498266Sopenharmony_ci 188913498266Sopenharmony_ci if(backend->handle) { 189013498266Sopenharmony_ci if(cf->next && cf->next->connected) { 189113498266Sopenharmony_ci char buf[1024]; 189213498266Sopenharmony_ci int nread, err; 189313498266Sopenharmony_ci long sslerr; 189413498266Sopenharmony_ci 189513498266Sopenharmony_ci /* Maybe the server has already sent a close notify alert. 189613498266Sopenharmony_ci Read it to avoid an RST on the TCP connection. */ 189713498266Sopenharmony_ci (void)SSL_read(backend->handle, buf, (int)sizeof(buf)); 189813498266Sopenharmony_ci ERR_clear_error(); 189913498266Sopenharmony_ci if(SSL_shutdown(backend->handle) == 1) { 190013498266Sopenharmony_ci CURL_TRC_CF(data, cf, "SSL shutdown finished"); 190113498266Sopenharmony_ci } 190213498266Sopenharmony_ci else { 190313498266Sopenharmony_ci nread = SSL_read(backend->handle, buf, (int)sizeof(buf)); 190413498266Sopenharmony_ci err = SSL_get_error(backend->handle, nread); 190513498266Sopenharmony_ci switch(err) { 190613498266Sopenharmony_ci case SSL_ERROR_NONE: /* this is not an error */ 190713498266Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: /* no more data */ 190813498266Sopenharmony_ci CURL_TRC_CF(data, cf, "SSL shutdown, EOF from server"); 190913498266Sopenharmony_ci break; 191013498266Sopenharmony_ci case SSL_ERROR_WANT_READ: 191113498266Sopenharmony_ci /* SSL has send its notify and now wants to read the reply 191213498266Sopenharmony_ci * from the server. We are not really interested in that. */ 191313498266Sopenharmony_ci CURL_TRC_CF(data, cf, "SSL shutdown sent"); 191413498266Sopenharmony_ci break; 191513498266Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 191613498266Sopenharmony_ci CURL_TRC_CF(data, cf, "SSL shutdown send blocked"); 191713498266Sopenharmony_ci break; 191813498266Sopenharmony_ci default: 191913498266Sopenharmony_ci sslerr = ERR_get_error(); 192013498266Sopenharmony_ci CURL_TRC_CF(data, cf, "SSL shutdown, error: '%s', errno %d", 192113498266Sopenharmony_ci (sslerr ? 192213498266Sopenharmony_ci ossl_strerror(sslerr, buf, sizeof(buf)) : 192313498266Sopenharmony_ci SSL_ERROR_to_str(err)), 192413498266Sopenharmony_ci SOCKERRNO); 192513498266Sopenharmony_ci break; 192613498266Sopenharmony_ci } 192713498266Sopenharmony_ci } 192813498266Sopenharmony_ci 192913498266Sopenharmony_ci ERR_clear_error(); 193013498266Sopenharmony_ci SSL_set_connect_state(backend->handle); 193113498266Sopenharmony_ci } 193213498266Sopenharmony_ci 193313498266Sopenharmony_ci SSL_free(backend->handle); 193413498266Sopenharmony_ci backend->handle = NULL; 193513498266Sopenharmony_ci } 193613498266Sopenharmony_ci if(backend->ctx) { 193713498266Sopenharmony_ci SSL_CTX_free(backend->ctx); 193813498266Sopenharmony_ci backend->ctx = NULL; 193913498266Sopenharmony_ci backend->x509_store_setup = FALSE; 194013498266Sopenharmony_ci } 194113498266Sopenharmony_ci if(backend->bio_method) { 194213498266Sopenharmony_ci ossl_bio_cf_method_free(backend->bio_method); 194313498266Sopenharmony_ci backend->bio_method = NULL; 194413498266Sopenharmony_ci } 194513498266Sopenharmony_ci} 194613498266Sopenharmony_ci 194713498266Sopenharmony_ci/* 194813498266Sopenharmony_ci * This function is called to shut down the SSL layer but keep the 194913498266Sopenharmony_ci * socket open (CCC - Clear Command Channel) 195013498266Sopenharmony_ci */ 195113498266Sopenharmony_cistatic int ossl_shutdown(struct Curl_cfilter *cf, 195213498266Sopenharmony_ci struct Curl_easy *data) 195313498266Sopenharmony_ci{ 195413498266Sopenharmony_ci int retval = 0; 195513498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 195613498266Sopenharmony_ci char buf[256]; /* We will use this for the OpenSSL error buffer, so it has 195713498266Sopenharmony_ci to be at least 256 bytes long. */ 195813498266Sopenharmony_ci unsigned long sslerror; 195913498266Sopenharmony_ci int nread; 196013498266Sopenharmony_ci int buffsize; 196113498266Sopenharmony_ci int err; 196213498266Sopenharmony_ci bool done = FALSE; 196313498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 196413498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 196513498266Sopenharmony_ci int loop = 10; 196613498266Sopenharmony_ci 196713498266Sopenharmony_ci DEBUGASSERT(backend); 196813498266Sopenharmony_ci 196913498266Sopenharmony_ci#ifndef CURL_DISABLE_FTP 197013498266Sopenharmony_ci /* This has only been tested on the proftpd server, and the mod_tls code 197113498266Sopenharmony_ci sends a close notify alert without waiting for a close notify alert in 197213498266Sopenharmony_ci response. Thus we wait for a close notify alert from the server, but 197313498266Sopenharmony_ci we do not send one. Let's hope other servers do the same... */ 197413498266Sopenharmony_ci 197513498266Sopenharmony_ci if(data->set.ftp_ccc == CURLFTPSSL_CCC_ACTIVE) 197613498266Sopenharmony_ci (void)SSL_shutdown(backend->handle); 197713498266Sopenharmony_ci#endif 197813498266Sopenharmony_ci 197913498266Sopenharmony_ci if(backend->handle) { 198013498266Sopenharmony_ci buffsize = (int)sizeof(buf); 198113498266Sopenharmony_ci while(!done && loop--) { 198213498266Sopenharmony_ci int what = SOCKET_READABLE(Curl_conn_cf_get_socket(cf, data), 198313498266Sopenharmony_ci SSL_SHUTDOWN_TIMEOUT); 198413498266Sopenharmony_ci if(what > 0) { 198513498266Sopenharmony_ci ERR_clear_error(); 198613498266Sopenharmony_ci 198713498266Sopenharmony_ci /* Something to read, let's do it and hope that it is the close 198813498266Sopenharmony_ci notify alert from the server */ 198913498266Sopenharmony_ci nread = SSL_read(backend->handle, buf, buffsize); 199013498266Sopenharmony_ci err = SSL_get_error(backend->handle, nread); 199113498266Sopenharmony_ci 199213498266Sopenharmony_ci switch(err) { 199313498266Sopenharmony_ci case SSL_ERROR_NONE: /* this is not an error */ 199413498266Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: /* no more data */ 199513498266Sopenharmony_ci /* This is the expected response. There was no data but only 199613498266Sopenharmony_ci the close notify alert */ 199713498266Sopenharmony_ci done = TRUE; 199813498266Sopenharmony_ci break; 199913498266Sopenharmony_ci case SSL_ERROR_WANT_READ: 200013498266Sopenharmony_ci /* there's data pending, re-invoke SSL_read() */ 200113498266Sopenharmony_ci infof(data, "SSL_ERROR_WANT_READ"); 200213498266Sopenharmony_ci break; 200313498266Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 200413498266Sopenharmony_ci /* SSL wants a write. Really odd. Let's bail out. */ 200513498266Sopenharmony_ci infof(data, "SSL_ERROR_WANT_WRITE"); 200613498266Sopenharmony_ci done = TRUE; 200713498266Sopenharmony_ci break; 200813498266Sopenharmony_ci default: 200913498266Sopenharmony_ci /* openssl/ssl.h says "look at error stack/return value/errno" */ 201013498266Sopenharmony_ci sslerror = ERR_get_error(); 201113498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_read on shutdown: %s, errno %d", 201213498266Sopenharmony_ci (sslerror ? 201313498266Sopenharmony_ci ossl_strerror(sslerror, buf, sizeof(buf)) : 201413498266Sopenharmony_ci SSL_ERROR_to_str(err)), 201513498266Sopenharmony_ci SOCKERRNO); 201613498266Sopenharmony_ci done = TRUE; 201713498266Sopenharmony_ci break; 201813498266Sopenharmony_ci } 201913498266Sopenharmony_ci } 202013498266Sopenharmony_ci else if(0 == what) { 202113498266Sopenharmony_ci /* timeout */ 202213498266Sopenharmony_ci failf(data, "SSL shutdown timeout"); 202313498266Sopenharmony_ci done = TRUE; 202413498266Sopenharmony_ci } 202513498266Sopenharmony_ci else { 202613498266Sopenharmony_ci /* anything that gets here is fatally bad */ 202713498266Sopenharmony_ci failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 202813498266Sopenharmony_ci retval = -1; 202913498266Sopenharmony_ci done = TRUE; 203013498266Sopenharmony_ci } 203113498266Sopenharmony_ci } /* while()-loop for the select() */ 203213498266Sopenharmony_ci 203313498266Sopenharmony_ci if(data->set.verbose) { 203413498266Sopenharmony_ci#ifdef HAVE_SSL_GET_SHUTDOWN 203513498266Sopenharmony_ci switch(SSL_get_shutdown(backend->handle)) { 203613498266Sopenharmony_ci case SSL_SENT_SHUTDOWN: 203713498266Sopenharmony_ci infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN"); 203813498266Sopenharmony_ci break; 203913498266Sopenharmony_ci case SSL_RECEIVED_SHUTDOWN: 204013498266Sopenharmony_ci infof(data, "SSL_get_shutdown() returned SSL_RECEIVED_SHUTDOWN"); 204113498266Sopenharmony_ci break; 204213498266Sopenharmony_ci case SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN: 204313498266Sopenharmony_ci infof(data, "SSL_get_shutdown() returned SSL_SENT_SHUTDOWN|" 204413498266Sopenharmony_ci "SSL_RECEIVED__SHUTDOWN"); 204513498266Sopenharmony_ci break; 204613498266Sopenharmony_ci } 204713498266Sopenharmony_ci#endif 204813498266Sopenharmony_ci } 204913498266Sopenharmony_ci 205013498266Sopenharmony_ci SSL_free(backend->handle); 205113498266Sopenharmony_ci backend->handle = NULL; 205213498266Sopenharmony_ci } 205313498266Sopenharmony_ci return retval; 205413498266Sopenharmony_ci} 205513498266Sopenharmony_ci 205613498266Sopenharmony_cistatic void ossl_session_free(void *ptr) 205713498266Sopenharmony_ci{ 205813498266Sopenharmony_ci /* free the ID */ 205913498266Sopenharmony_ci SSL_SESSION_free(ptr); 206013498266Sopenharmony_ci} 206113498266Sopenharmony_ci 206213498266Sopenharmony_ci/* 206313498266Sopenharmony_ci * This function is called when the 'data' struct is going away. Close 206413498266Sopenharmony_ci * down everything and free all resources! 206513498266Sopenharmony_ci */ 206613498266Sopenharmony_cistatic void ossl_close_all(struct Curl_easy *data) 206713498266Sopenharmony_ci{ 206813498266Sopenharmony_ci#ifdef USE_OPENSSL_ENGINE 206913498266Sopenharmony_ci if(data->state.engine) { 207013498266Sopenharmony_ci ENGINE_finish(data->state.engine); 207113498266Sopenharmony_ci ENGINE_free(data->state.engine); 207213498266Sopenharmony_ci data->state.engine = NULL; 207313498266Sopenharmony_ci } 207413498266Sopenharmony_ci#else 207513498266Sopenharmony_ci (void)data; 207613498266Sopenharmony_ci#endif 207713498266Sopenharmony_ci#if !defined(HAVE_ERR_REMOVE_THREAD_STATE_DEPRECATED) && \ 207813498266Sopenharmony_ci defined(HAVE_ERR_REMOVE_THREAD_STATE) 207913498266Sopenharmony_ci /* OpenSSL 1.0.1 and 1.0.2 build an error queue that is stored per-thread 208013498266Sopenharmony_ci so we need to clean it here in case the thread will be killed. All OpenSSL 208113498266Sopenharmony_ci code should extract the error in association with the error so clearing 208213498266Sopenharmony_ci this queue here should be harmless at worst. */ 208313498266Sopenharmony_ci ERR_remove_thread_state(NULL); 208413498266Sopenharmony_ci#endif 208513498266Sopenharmony_ci} 208613498266Sopenharmony_ci 208713498266Sopenharmony_ci/* ====================================================== */ 208813498266Sopenharmony_ci 208913498266Sopenharmony_ci/* 209013498266Sopenharmony_ci * Match subjectAltName against the host name. 209113498266Sopenharmony_ci */ 209213498266Sopenharmony_cistatic bool subj_alt_hostcheck(struct Curl_easy *data, 209313498266Sopenharmony_ci const char *match_pattern, 209413498266Sopenharmony_ci size_t matchlen, 209513498266Sopenharmony_ci const char *hostname, 209613498266Sopenharmony_ci size_t hostlen, 209713498266Sopenharmony_ci const char *dispname) 209813498266Sopenharmony_ci{ 209913498266Sopenharmony_ci#ifdef CURL_DISABLE_VERBOSE_STRINGS 210013498266Sopenharmony_ci (void)dispname; 210113498266Sopenharmony_ci (void)data; 210213498266Sopenharmony_ci#endif 210313498266Sopenharmony_ci if(Curl_cert_hostcheck(match_pattern, matchlen, hostname, hostlen)) { 210413498266Sopenharmony_ci infof(data, " subjectAltName: host \"%s\" matched cert's \"%s\"", 210513498266Sopenharmony_ci dispname, match_pattern); 210613498266Sopenharmony_ci return TRUE; 210713498266Sopenharmony_ci } 210813498266Sopenharmony_ci return FALSE; 210913498266Sopenharmony_ci} 211013498266Sopenharmony_ci 211113498266Sopenharmony_ci/* Quote from RFC2818 section 3.1 "Server Identity" 211213498266Sopenharmony_ci 211313498266Sopenharmony_ci If a subjectAltName extension of type dNSName is present, that MUST 211413498266Sopenharmony_ci be used as the identity. Otherwise, the (most specific) Common Name 211513498266Sopenharmony_ci field in the Subject field of the certificate MUST be used. Although 211613498266Sopenharmony_ci the use of the Common Name is existing practice, it is deprecated and 211713498266Sopenharmony_ci Certification Authorities are encouraged to use the dNSName instead. 211813498266Sopenharmony_ci 211913498266Sopenharmony_ci Matching is performed using the matching rules specified by 212013498266Sopenharmony_ci [RFC2459]. If more than one identity of a given type is present in 212113498266Sopenharmony_ci the certificate (e.g., more than one dNSName name, a match in any one 212213498266Sopenharmony_ci of the set is considered acceptable.) Names may contain the wildcard 212313498266Sopenharmony_ci character * which is considered to match any single domain name 212413498266Sopenharmony_ci component or component fragment. E.g., *.a.com matches foo.a.com but 212513498266Sopenharmony_ci not bar.foo.a.com. f*.com matches foo.com but not bar.com. 212613498266Sopenharmony_ci 212713498266Sopenharmony_ci In some cases, the URI is specified as an IP address rather than a 212813498266Sopenharmony_ci hostname. In this case, the iPAddress subjectAltName must be present 212913498266Sopenharmony_ci in the certificate and must exactly match the IP in the URI. 213013498266Sopenharmony_ci 213113498266Sopenharmony_ci This function is now used from ngtcp2 (QUIC) as well. 213213498266Sopenharmony_ci*/ 213313498266Sopenharmony_ciCURLcode Curl_ossl_verifyhost(struct Curl_easy *data, struct connectdata *conn, 213413498266Sopenharmony_ci struct ssl_peer *peer, X509 *server_cert) 213513498266Sopenharmony_ci{ 213613498266Sopenharmony_ci bool matched = FALSE; 213713498266Sopenharmony_ci int target = GEN_DNS; /* target type, GEN_DNS or GEN_IPADD */ 213813498266Sopenharmony_ci size_t addrlen = 0; 213913498266Sopenharmony_ci STACK_OF(GENERAL_NAME) *altnames; 214013498266Sopenharmony_ci#ifdef ENABLE_IPV6 214113498266Sopenharmony_ci struct in6_addr addr; 214213498266Sopenharmony_ci#else 214313498266Sopenharmony_ci struct in_addr addr; 214413498266Sopenharmony_ci#endif 214513498266Sopenharmony_ci CURLcode result = CURLE_OK; 214613498266Sopenharmony_ci bool dNSName = FALSE; /* if a dNSName field exists in the cert */ 214713498266Sopenharmony_ci bool iPAddress = FALSE; /* if a iPAddress field exists in the cert */ 214813498266Sopenharmony_ci size_t hostlen; 214913498266Sopenharmony_ci 215013498266Sopenharmony_ci (void)conn; 215113498266Sopenharmony_ci hostlen = strlen(peer->hostname); 215213498266Sopenharmony_ci if(peer->is_ip_address) { 215313498266Sopenharmony_ci#ifdef ENABLE_IPV6 215413498266Sopenharmony_ci if(conn->bits.ipv6_ip && 215513498266Sopenharmony_ci Curl_inet_pton(AF_INET6, peer->hostname, &addr)) { 215613498266Sopenharmony_ci target = GEN_IPADD; 215713498266Sopenharmony_ci addrlen = sizeof(struct in6_addr); 215813498266Sopenharmony_ci } 215913498266Sopenharmony_ci else 216013498266Sopenharmony_ci#endif 216113498266Sopenharmony_ci if(Curl_inet_pton(AF_INET, peer->hostname, &addr)) { 216213498266Sopenharmony_ci target = GEN_IPADD; 216313498266Sopenharmony_ci addrlen = sizeof(struct in_addr); 216413498266Sopenharmony_ci } 216513498266Sopenharmony_ci } 216613498266Sopenharmony_ci 216713498266Sopenharmony_ci /* get a "list" of alternative names */ 216813498266Sopenharmony_ci altnames = X509_get_ext_d2i(server_cert, NID_subject_alt_name, NULL, NULL); 216913498266Sopenharmony_ci 217013498266Sopenharmony_ci if(altnames) { 217113498266Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) 217213498266Sopenharmony_ci size_t numalts; 217313498266Sopenharmony_ci size_t i; 217413498266Sopenharmony_ci#else 217513498266Sopenharmony_ci int numalts; 217613498266Sopenharmony_ci int i; 217713498266Sopenharmony_ci#endif 217813498266Sopenharmony_ci bool dnsmatched = FALSE; 217913498266Sopenharmony_ci bool ipmatched = FALSE; 218013498266Sopenharmony_ci 218113498266Sopenharmony_ci /* get amount of alternatives, RFC2459 claims there MUST be at least 218213498266Sopenharmony_ci one, but we don't depend on it... */ 218313498266Sopenharmony_ci numalts = sk_GENERAL_NAME_num(altnames); 218413498266Sopenharmony_ci 218513498266Sopenharmony_ci /* loop through all alternatives - until a dnsmatch */ 218613498266Sopenharmony_ci for(i = 0; (i < numalts) && !dnsmatched; i++) { 218713498266Sopenharmony_ci /* get a handle to alternative name number i */ 218813498266Sopenharmony_ci const GENERAL_NAME *check = sk_GENERAL_NAME_value(altnames, i); 218913498266Sopenharmony_ci 219013498266Sopenharmony_ci if(check->type == GEN_DNS) 219113498266Sopenharmony_ci dNSName = TRUE; 219213498266Sopenharmony_ci else if(check->type == GEN_IPADD) 219313498266Sopenharmony_ci iPAddress = TRUE; 219413498266Sopenharmony_ci 219513498266Sopenharmony_ci /* only check alternatives of the same type the target is */ 219613498266Sopenharmony_ci if(check->type == target) { 219713498266Sopenharmony_ci /* get data and length */ 219813498266Sopenharmony_ci const char *altptr = (char *)ASN1_STRING_get0_data(check->d.ia5); 219913498266Sopenharmony_ci size_t altlen = (size_t) ASN1_STRING_length(check->d.ia5); 220013498266Sopenharmony_ci 220113498266Sopenharmony_ci switch(target) { 220213498266Sopenharmony_ci case GEN_DNS: /* name/pattern comparison */ 220313498266Sopenharmony_ci /* The OpenSSL man page explicitly says: "In general it cannot be 220413498266Sopenharmony_ci assumed that the data returned by ASN1_STRING_data() is null 220513498266Sopenharmony_ci terminated or does not contain embedded nulls." But also that 220613498266Sopenharmony_ci "The actual format of the data will depend on the actual string 220713498266Sopenharmony_ci type itself: for example for an IA5String the data will be ASCII" 220813498266Sopenharmony_ci 220913498266Sopenharmony_ci It has been however verified that in 0.9.6 and 0.9.7, IA5String 221013498266Sopenharmony_ci is always null-terminated. 221113498266Sopenharmony_ci */ 221213498266Sopenharmony_ci if((altlen == strlen(altptr)) && 221313498266Sopenharmony_ci /* if this isn't true, there was an embedded zero in the name 221413498266Sopenharmony_ci string and we cannot match it. */ 221513498266Sopenharmony_ci subj_alt_hostcheck(data, altptr, altlen, 221613498266Sopenharmony_ci peer->hostname, hostlen, 221713498266Sopenharmony_ci peer->dispname)) { 221813498266Sopenharmony_ci dnsmatched = TRUE; 221913498266Sopenharmony_ci } 222013498266Sopenharmony_ci break; 222113498266Sopenharmony_ci 222213498266Sopenharmony_ci case GEN_IPADD: /* IP address comparison */ 222313498266Sopenharmony_ci /* compare alternative IP address if the data chunk is the same size 222413498266Sopenharmony_ci our server IP address is */ 222513498266Sopenharmony_ci if((altlen == addrlen) && !memcmp(altptr, &addr, altlen)) { 222613498266Sopenharmony_ci ipmatched = TRUE; 222713498266Sopenharmony_ci infof(data, 222813498266Sopenharmony_ci " subjectAltName: host \"%s\" matched cert's IP address!", 222913498266Sopenharmony_ci peer->dispname); 223013498266Sopenharmony_ci } 223113498266Sopenharmony_ci break; 223213498266Sopenharmony_ci } 223313498266Sopenharmony_ci } 223413498266Sopenharmony_ci } 223513498266Sopenharmony_ci GENERAL_NAMES_free(altnames); 223613498266Sopenharmony_ci 223713498266Sopenharmony_ci if(dnsmatched || ipmatched) 223813498266Sopenharmony_ci matched = TRUE; 223913498266Sopenharmony_ci } 224013498266Sopenharmony_ci 224113498266Sopenharmony_ci if(matched) 224213498266Sopenharmony_ci /* an alternative name matched */ 224313498266Sopenharmony_ci ; 224413498266Sopenharmony_ci else if(dNSName || iPAddress) { 224513498266Sopenharmony_ci infof(data, " subjectAltName does not match %s", peer->dispname); 224613498266Sopenharmony_ci failf(data, "SSL: no alternative certificate subject name matches " 224713498266Sopenharmony_ci "target host name '%s'", peer->dispname); 224813498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 224913498266Sopenharmony_ci } 225013498266Sopenharmony_ci else { 225113498266Sopenharmony_ci /* we have to look to the last occurrence of a commonName in the 225213498266Sopenharmony_ci distinguished one to get the most significant one. */ 225313498266Sopenharmony_ci int i = -1; 225413498266Sopenharmony_ci unsigned char *peer_CN = NULL; 225513498266Sopenharmony_ci int peerlen = 0; 225613498266Sopenharmony_ci 225713498266Sopenharmony_ci /* The following is done because of a bug in 0.9.6b */ 225813498266Sopenharmony_ci X509_NAME *name = X509_get_subject_name(server_cert); 225913498266Sopenharmony_ci if(name) { 226013498266Sopenharmony_ci int j; 226113498266Sopenharmony_ci while((j = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0) 226213498266Sopenharmony_ci i = j; 226313498266Sopenharmony_ci } 226413498266Sopenharmony_ci 226513498266Sopenharmony_ci /* we have the name entry and we will now convert this to a string 226613498266Sopenharmony_ci that we can use for comparison. Doing this we support BMPstring, 226713498266Sopenharmony_ci UTF8, etc. */ 226813498266Sopenharmony_ci 226913498266Sopenharmony_ci if(i >= 0) { 227013498266Sopenharmony_ci ASN1_STRING *tmp = 227113498266Sopenharmony_ci X509_NAME_ENTRY_get_data(X509_NAME_get_entry(name, i)); 227213498266Sopenharmony_ci 227313498266Sopenharmony_ci /* In OpenSSL 0.9.7d and earlier, ASN1_STRING_to_UTF8 fails if the input 227413498266Sopenharmony_ci is already UTF-8 encoded. We check for this case and copy the raw 227513498266Sopenharmony_ci string manually to avoid the problem. This code can be made 227613498266Sopenharmony_ci conditional in the future when OpenSSL has been fixed. */ 227713498266Sopenharmony_ci if(tmp) { 227813498266Sopenharmony_ci if(ASN1_STRING_type(tmp) == V_ASN1_UTF8STRING) { 227913498266Sopenharmony_ci peerlen = ASN1_STRING_length(tmp); 228013498266Sopenharmony_ci if(peerlen >= 0) { 228113498266Sopenharmony_ci peer_CN = OPENSSL_malloc(peerlen + 1); 228213498266Sopenharmony_ci if(peer_CN) { 228313498266Sopenharmony_ci memcpy(peer_CN, ASN1_STRING_get0_data(tmp), peerlen); 228413498266Sopenharmony_ci peer_CN[peerlen] = '\0'; 228513498266Sopenharmony_ci } 228613498266Sopenharmony_ci else 228713498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 228813498266Sopenharmony_ci } 228913498266Sopenharmony_ci } 229013498266Sopenharmony_ci else /* not a UTF8 name */ 229113498266Sopenharmony_ci peerlen = ASN1_STRING_to_UTF8(&peer_CN, tmp); 229213498266Sopenharmony_ci 229313498266Sopenharmony_ci if(peer_CN && (curlx_uztosi(strlen((char *)peer_CN)) != peerlen)) { 229413498266Sopenharmony_ci /* there was a terminating zero before the end of string, this 229513498266Sopenharmony_ci cannot match and we return failure! */ 229613498266Sopenharmony_ci failf(data, "SSL: illegal cert name field"); 229713498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 229813498266Sopenharmony_ci } 229913498266Sopenharmony_ci } 230013498266Sopenharmony_ci } 230113498266Sopenharmony_ci 230213498266Sopenharmony_ci if(result) 230313498266Sopenharmony_ci /* error already detected, pass through */ 230413498266Sopenharmony_ci ; 230513498266Sopenharmony_ci else if(!peer_CN) { 230613498266Sopenharmony_ci failf(data, 230713498266Sopenharmony_ci "SSL: unable to obtain common name from peer certificate"); 230813498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 230913498266Sopenharmony_ci } 231013498266Sopenharmony_ci else if(!Curl_cert_hostcheck((const char *)peer_CN, 231113498266Sopenharmony_ci peerlen, peer->hostname, hostlen)) { 231213498266Sopenharmony_ci failf(data, "SSL: certificate subject name '%s' does not match " 231313498266Sopenharmony_ci "target host name '%s'", peer_CN, peer->dispname); 231413498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 231513498266Sopenharmony_ci } 231613498266Sopenharmony_ci else { 231713498266Sopenharmony_ci infof(data, " common name: %s (matched)", peer_CN); 231813498266Sopenharmony_ci } 231913498266Sopenharmony_ci if(peer_CN) 232013498266Sopenharmony_ci OPENSSL_free(peer_CN); 232113498266Sopenharmony_ci } 232213498266Sopenharmony_ci 232313498266Sopenharmony_ci return result; 232413498266Sopenharmony_ci} 232513498266Sopenharmony_ci 232613498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ 232713498266Sopenharmony_ci !defined(OPENSSL_NO_OCSP) 232813498266Sopenharmony_cistatic CURLcode verifystatus(struct Curl_cfilter *cf, 232913498266Sopenharmony_ci struct Curl_easy *data) 233013498266Sopenharmony_ci{ 233113498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 233213498266Sopenharmony_ci int i, ocsp_status; 233313498266Sopenharmony_ci#if defined(OPENSSL_IS_AWSLC) 233413498266Sopenharmony_ci const uint8_t *status; 233513498266Sopenharmony_ci#else 233613498266Sopenharmony_ci unsigned char *status; 233713498266Sopenharmony_ci#endif 233813498266Sopenharmony_ci const unsigned char *p; 233913498266Sopenharmony_ci CURLcode result = CURLE_OK; 234013498266Sopenharmony_ci OCSP_RESPONSE *rsp = NULL; 234113498266Sopenharmony_ci OCSP_BASICRESP *br = NULL; 234213498266Sopenharmony_ci X509_STORE *st = NULL; 234313498266Sopenharmony_ci STACK_OF(X509) *ch = NULL; 234413498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 234513498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 234613498266Sopenharmony_ci X509 *cert; 234713498266Sopenharmony_ci OCSP_CERTID *id = NULL; 234813498266Sopenharmony_ci int cert_status, crl_reason; 234913498266Sopenharmony_ci ASN1_GENERALIZEDTIME *rev, *thisupd, *nextupd; 235013498266Sopenharmony_ci int ret; 235113498266Sopenharmony_ci long len; 235213498266Sopenharmony_ci 235313498266Sopenharmony_ci DEBUGASSERT(backend); 235413498266Sopenharmony_ci 235513498266Sopenharmony_ci len = SSL_get_tlsext_status_ocsp_resp(backend->handle, &status); 235613498266Sopenharmony_ci 235713498266Sopenharmony_ci if(!status) { 235813498266Sopenharmony_ci failf(data, "No OCSP response received"); 235913498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 236013498266Sopenharmony_ci goto end; 236113498266Sopenharmony_ci } 236213498266Sopenharmony_ci p = status; 236313498266Sopenharmony_ci rsp = d2i_OCSP_RESPONSE(NULL, &p, len); 236413498266Sopenharmony_ci if(!rsp) { 236513498266Sopenharmony_ci failf(data, "Invalid OCSP response"); 236613498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 236713498266Sopenharmony_ci goto end; 236813498266Sopenharmony_ci } 236913498266Sopenharmony_ci 237013498266Sopenharmony_ci ocsp_status = OCSP_response_status(rsp); 237113498266Sopenharmony_ci if(ocsp_status != OCSP_RESPONSE_STATUS_SUCCESSFUL) { 237213498266Sopenharmony_ci failf(data, "Invalid OCSP response status: %s (%d)", 237313498266Sopenharmony_ci OCSP_response_status_str(ocsp_status), ocsp_status); 237413498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 237513498266Sopenharmony_ci goto end; 237613498266Sopenharmony_ci } 237713498266Sopenharmony_ci 237813498266Sopenharmony_ci br = OCSP_response_get1_basic(rsp); 237913498266Sopenharmony_ci if(!br) { 238013498266Sopenharmony_ci failf(data, "Invalid OCSP response"); 238113498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 238213498266Sopenharmony_ci goto end; 238313498266Sopenharmony_ci } 238413498266Sopenharmony_ci 238513498266Sopenharmony_ci ch = SSL_get_peer_cert_chain(backend->handle); 238613498266Sopenharmony_ci if(!ch) { 238713498266Sopenharmony_ci failf(data, "Could not get peer certificate chain"); 238813498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 238913498266Sopenharmony_ci goto end; 239013498266Sopenharmony_ci } 239113498266Sopenharmony_ci st = SSL_CTX_get_cert_store(backend->ctx); 239213498266Sopenharmony_ci 239313498266Sopenharmony_ci#if ((OPENSSL_VERSION_NUMBER <= 0x1000201fL) /* Fixed after 1.0.2a */ || \ 239413498266Sopenharmony_ci (defined(LIBRESSL_VERSION_NUMBER) && \ 239513498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER <= 0x2040200fL)) 239613498266Sopenharmony_ci /* The authorized responder cert in the OCSP response MUST be signed by the 239713498266Sopenharmony_ci peer cert's issuer (see RFC6960 section 4.2.2.2). If that's a root cert, 239813498266Sopenharmony_ci no problem, but if it's an intermediate cert OpenSSL has a bug where it 239913498266Sopenharmony_ci expects this issuer to be present in the chain embedded in the OCSP 240013498266Sopenharmony_ci response. So we add it if necessary. */ 240113498266Sopenharmony_ci 240213498266Sopenharmony_ci /* First make sure the peer cert chain includes both a peer and an issuer, 240313498266Sopenharmony_ci and the OCSP response contains a responder cert. */ 240413498266Sopenharmony_ci if(sk_X509_num(ch) >= 2 && sk_X509_num(br->certs) >= 1) { 240513498266Sopenharmony_ci X509 *responder = sk_X509_value(br->certs, sk_X509_num(br->certs) - 1); 240613498266Sopenharmony_ci 240713498266Sopenharmony_ci /* Find issuer of responder cert and add it to the OCSP response chain */ 240813498266Sopenharmony_ci for(i = 0; i < sk_X509_num(ch); i++) { 240913498266Sopenharmony_ci X509 *issuer = sk_X509_value(ch, i); 241013498266Sopenharmony_ci if(X509_check_issued(issuer, responder) == X509_V_OK) { 241113498266Sopenharmony_ci if(!OCSP_basic_add1_cert(br, issuer)) { 241213498266Sopenharmony_ci failf(data, "Could not add issuer cert to OCSP response"); 241313498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 241413498266Sopenharmony_ci goto end; 241513498266Sopenharmony_ci } 241613498266Sopenharmony_ci } 241713498266Sopenharmony_ci } 241813498266Sopenharmony_ci } 241913498266Sopenharmony_ci#endif 242013498266Sopenharmony_ci 242113498266Sopenharmony_ci if(OCSP_basic_verify(br, ch, st, 0) <= 0) { 242213498266Sopenharmony_ci failf(data, "OCSP response verification failed"); 242313498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 242413498266Sopenharmony_ci goto end; 242513498266Sopenharmony_ci } 242613498266Sopenharmony_ci 242713498266Sopenharmony_ci /* Compute the certificate's ID */ 242813498266Sopenharmony_ci cert = SSL_get1_peer_certificate(backend->handle); 242913498266Sopenharmony_ci if(!cert) { 243013498266Sopenharmony_ci failf(data, "Error getting peer certificate"); 243113498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 243213498266Sopenharmony_ci goto end; 243313498266Sopenharmony_ci } 243413498266Sopenharmony_ci 243513498266Sopenharmony_ci for(i = 0; i < (int)sk_X509_num(ch); i++) { 243613498266Sopenharmony_ci X509 *issuer = sk_X509_value(ch, i); 243713498266Sopenharmony_ci if(X509_check_issued(issuer, cert) == X509_V_OK) { 243813498266Sopenharmony_ci id = OCSP_cert_to_id(EVP_sha1(), cert, issuer); 243913498266Sopenharmony_ci break; 244013498266Sopenharmony_ci } 244113498266Sopenharmony_ci } 244213498266Sopenharmony_ci X509_free(cert); 244313498266Sopenharmony_ci 244413498266Sopenharmony_ci if(!id) { 244513498266Sopenharmony_ci failf(data, "Error computing OCSP ID"); 244613498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 244713498266Sopenharmony_ci goto end; 244813498266Sopenharmony_ci } 244913498266Sopenharmony_ci 245013498266Sopenharmony_ci /* Find the single OCSP response corresponding to the certificate ID */ 245113498266Sopenharmony_ci ret = OCSP_resp_find_status(br, id, &cert_status, &crl_reason, &rev, 245213498266Sopenharmony_ci &thisupd, &nextupd); 245313498266Sopenharmony_ci OCSP_CERTID_free(id); 245413498266Sopenharmony_ci if(ret != 1) { 245513498266Sopenharmony_ci failf(data, "Could not find certificate ID in OCSP response"); 245613498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 245713498266Sopenharmony_ci goto end; 245813498266Sopenharmony_ci } 245913498266Sopenharmony_ci 246013498266Sopenharmony_ci /* Validate the corresponding single OCSP response */ 246113498266Sopenharmony_ci if(!OCSP_check_validity(thisupd, nextupd, 300L, -1L)) { 246213498266Sopenharmony_ci failf(data, "OCSP response has expired"); 246313498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 246413498266Sopenharmony_ci goto end; 246513498266Sopenharmony_ci } 246613498266Sopenharmony_ci 246713498266Sopenharmony_ci infof(data, "SSL certificate status: %s (%d)", 246813498266Sopenharmony_ci OCSP_cert_status_str(cert_status), cert_status); 246913498266Sopenharmony_ci 247013498266Sopenharmony_ci switch(cert_status) { 247113498266Sopenharmony_ci case V_OCSP_CERTSTATUS_GOOD: 247213498266Sopenharmony_ci break; 247313498266Sopenharmony_ci 247413498266Sopenharmony_ci case V_OCSP_CERTSTATUS_REVOKED: 247513498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 247613498266Sopenharmony_ci failf(data, "SSL certificate revocation reason: %s (%d)", 247713498266Sopenharmony_ci OCSP_crl_reason_str(crl_reason), crl_reason); 247813498266Sopenharmony_ci goto end; 247913498266Sopenharmony_ci 248013498266Sopenharmony_ci case V_OCSP_CERTSTATUS_UNKNOWN: 248113498266Sopenharmony_ci default: 248213498266Sopenharmony_ci result = CURLE_SSL_INVALIDCERTSTATUS; 248313498266Sopenharmony_ci goto end; 248413498266Sopenharmony_ci } 248513498266Sopenharmony_ci 248613498266Sopenharmony_ciend: 248713498266Sopenharmony_ci if(br) 248813498266Sopenharmony_ci OCSP_BASICRESP_free(br); 248913498266Sopenharmony_ci OCSP_RESPONSE_free(rsp); 249013498266Sopenharmony_ci 249113498266Sopenharmony_ci return result; 249213498266Sopenharmony_ci} 249313498266Sopenharmony_ci#endif 249413498266Sopenharmony_ci 249513498266Sopenharmony_ci#endif /* USE_OPENSSL */ 249613498266Sopenharmony_ci 249713498266Sopenharmony_ci/* The SSL_CTRL_SET_MSG_CALLBACK doesn't exist in ancient OpenSSL versions 249813498266Sopenharmony_ci and thus this cannot be done there. */ 249913498266Sopenharmony_ci#ifdef SSL_CTRL_SET_MSG_CALLBACK 250013498266Sopenharmony_ci 250113498266Sopenharmony_cistatic const char *ssl_msg_type(int ssl_ver, int msg) 250213498266Sopenharmony_ci{ 250313498266Sopenharmony_ci#ifdef SSL2_VERSION_MAJOR 250413498266Sopenharmony_ci if(ssl_ver == SSL2_VERSION_MAJOR) { 250513498266Sopenharmony_ci switch(msg) { 250613498266Sopenharmony_ci case SSL2_MT_ERROR: 250713498266Sopenharmony_ci return "Error"; 250813498266Sopenharmony_ci case SSL2_MT_CLIENT_HELLO: 250913498266Sopenharmony_ci return "Client hello"; 251013498266Sopenharmony_ci case SSL2_MT_CLIENT_MASTER_KEY: 251113498266Sopenharmony_ci return "Client key"; 251213498266Sopenharmony_ci case SSL2_MT_CLIENT_FINISHED: 251313498266Sopenharmony_ci return "Client finished"; 251413498266Sopenharmony_ci case SSL2_MT_SERVER_HELLO: 251513498266Sopenharmony_ci return "Server hello"; 251613498266Sopenharmony_ci case SSL2_MT_SERVER_VERIFY: 251713498266Sopenharmony_ci return "Server verify"; 251813498266Sopenharmony_ci case SSL2_MT_SERVER_FINISHED: 251913498266Sopenharmony_ci return "Server finished"; 252013498266Sopenharmony_ci case SSL2_MT_REQUEST_CERTIFICATE: 252113498266Sopenharmony_ci return "Request CERT"; 252213498266Sopenharmony_ci case SSL2_MT_CLIENT_CERTIFICATE: 252313498266Sopenharmony_ci return "Client CERT"; 252413498266Sopenharmony_ci } 252513498266Sopenharmony_ci } 252613498266Sopenharmony_ci else 252713498266Sopenharmony_ci#endif 252813498266Sopenharmony_ci if(ssl_ver == SSL3_VERSION_MAJOR) { 252913498266Sopenharmony_ci switch(msg) { 253013498266Sopenharmony_ci case SSL3_MT_HELLO_REQUEST: 253113498266Sopenharmony_ci return "Hello request"; 253213498266Sopenharmony_ci case SSL3_MT_CLIENT_HELLO: 253313498266Sopenharmony_ci return "Client hello"; 253413498266Sopenharmony_ci case SSL3_MT_SERVER_HELLO: 253513498266Sopenharmony_ci return "Server hello"; 253613498266Sopenharmony_ci#ifdef SSL3_MT_NEWSESSION_TICKET 253713498266Sopenharmony_ci case SSL3_MT_NEWSESSION_TICKET: 253813498266Sopenharmony_ci return "Newsession Ticket"; 253913498266Sopenharmony_ci#endif 254013498266Sopenharmony_ci case SSL3_MT_CERTIFICATE: 254113498266Sopenharmony_ci return "Certificate"; 254213498266Sopenharmony_ci case SSL3_MT_SERVER_KEY_EXCHANGE: 254313498266Sopenharmony_ci return "Server key exchange"; 254413498266Sopenharmony_ci case SSL3_MT_CLIENT_KEY_EXCHANGE: 254513498266Sopenharmony_ci return "Client key exchange"; 254613498266Sopenharmony_ci case SSL3_MT_CERTIFICATE_REQUEST: 254713498266Sopenharmony_ci return "Request CERT"; 254813498266Sopenharmony_ci case SSL3_MT_SERVER_DONE: 254913498266Sopenharmony_ci return "Server finished"; 255013498266Sopenharmony_ci case SSL3_MT_CERTIFICATE_VERIFY: 255113498266Sopenharmony_ci return "CERT verify"; 255213498266Sopenharmony_ci case SSL3_MT_FINISHED: 255313498266Sopenharmony_ci return "Finished"; 255413498266Sopenharmony_ci#ifdef SSL3_MT_CERTIFICATE_STATUS 255513498266Sopenharmony_ci case SSL3_MT_CERTIFICATE_STATUS: 255613498266Sopenharmony_ci return "Certificate Status"; 255713498266Sopenharmony_ci#endif 255813498266Sopenharmony_ci#ifdef SSL3_MT_ENCRYPTED_EXTENSIONS 255913498266Sopenharmony_ci case SSL3_MT_ENCRYPTED_EXTENSIONS: 256013498266Sopenharmony_ci return "Encrypted Extensions"; 256113498266Sopenharmony_ci#endif 256213498266Sopenharmony_ci#ifdef SSL3_MT_SUPPLEMENTAL_DATA 256313498266Sopenharmony_ci case SSL3_MT_SUPPLEMENTAL_DATA: 256413498266Sopenharmony_ci return "Supplemental data"; 256513498266Sopenharmony_ci#endif 256613498266Sopenharmony_ci#ifdef SSL3_MT_END_OF_EARLY_DATA 256713498266Sopenharmony_ci case SSL3_MT_END_OF_EARLY_DATA: 256813498266Sopenharmony_ci return "End of early data"; 256913498266Sopenharmony_ci#endif 257013498266Sopenharmony_ci#ifdef SSL3_MT_KEY_UPDATE 257113498266Sopenharmony_ci case SSL3_MT_KEY_UPDATE: 257213498266Sopenharmony_ci return "Key update"; 257313498266Sopenharmony_ci#endif 257413498266Sopenharmony_ci#ifdef SSL3_MT_NEXT_PROTO 257513498266Sopenharmony_ci case SSL3_MT_NEXT_PROTO: 257613498266Sopenharmony_ci return "Next protocol"; 257713498266Sopenharmony_ci#endif 257813498266Sopenharmony_ci#ifdef SSL3_MT_MESSAGE_HASH 257913498266Sopenharmony_ci case SSL3_MT_MESSAGE_HASH: 258013498266Sopenharmony_ci return "Message hash"; 258113498266Sopenharmony_ci#endif 258213498266Sopenharmony_ci } 258313498266Sopenharmony_ci } 258413498266Sopenharmony_ci return "Unknown"; 258513498266Sopenharmony_ci} 258613498266Sopenharmony_ci 258713498266Sopenharmony_cistatic const char *tls_rt_type(int type) 258813498266Sopenharmony_ci{ 258913498266Sopenharmony_ci switch(type) { 259013498266Sopenharmony_ci#ifdef SSL3_RT_HEADER 259113498266Sopenharmony_ci case SSL3_RT_HEADER: 259213498266Sopenharmony_ci return "TLS header"; 259313498266Sopenharmony_ci#endif 259413498266Sopenharmony_ci case SSL3_RT_CHANGE_CIPHER_SPEC: 259513498266Sopenharmony_ci return "TLS change cipher"; 259613498266Sopenharmony_ci case SSL3_RT_ALERT: 259713498266Sopenharmony_ci return "TLS alert"; 259813498266Sopenharmony_ci case SSL3_RT_HANDSHAKE: 259913498266Sopenharmony_ci return "TLS handshake"; 260013498266Sopenharmony_ci case SSL3_RT_APPLICATION_DATA: 260113498266Sopenharmony_ci return "TLS app data"; 260213498266Sopenharmony_ci default: 260313498266Sopenharmony_ci return "TLS Unknown"; 260413498266Sopenharmony_ci } 260513498266Sopenharmony_ci} 260613498266Sopenharmony_ci 260713498266Sopenharmony_ci/* 260813498266Sopenharmony_ci * Our callback from the SSL/TLS layers. 260913498266Sopenharmony_ci */ 261013498266Sopenharmony_cistatic void ossl_trace(int direction, int ssl_ver, int content_type, 261113498266Sopenharmony_ci const void *buf, size_t len, SSL *ssl, 261213498266Sopenharmony_ci void *userp) 261313498266Sopenharmony_ci{ 261413498266Sopenharmony_ci const char *verstr = "???"; 261513498266Sopenharmony_ci struct Curl_cfilter *cf = userp; 261613498266Sopenharmony_ci struct Curl_easy *data = NULL; 261713498266Sopenharmony_ci char unknown[32]; 261813498266Sopenharmony_ci 261913498266Sopenharmony_ci if(!cf) 262013498266Sopenharmony_ci return; 262113498266Sopenharmony_ci data = CF_DATA_CURRENT(cf); 262213498266Sopenharmony_ci if(!data || !data->set.fdebug || (direction && direction != 1)) 262313498266Sopenharmony_ci return; 262413498266Sopenharmony_ci 262513498266Sopenharmony_ci switch(ssl_ver) { 262613498266Sopenharmony_ci#ifdef SSL2_VERSION /* removed in recent versions */ 262713498266Sopenharmony_ci case SSL2_VERSION: 262813498266Sopenharmony_ci verstr = "SSLv2"; 262913498266Sopenharmony_ci break; 263013498266Sopenharmony_ci#endif 263113498266Sopenharmony_ci#ifdef SSL3_VERSION 263213498266Sopenharmony_ci case SSL3_VERSION: 263313498266Sopenharmony_ci verstr = "SSLv3"; 263413498266Sopenharmony_ci break; 263513498266Sopenharmony_ci#endif 263613498266Sopenharmony_ci case TLS1_VERSION: 263713498266Sopenharmony_ci verstr = "TLSv1.0"; 263813498266Sopenharmony_ci break; 263913498266Sopenharmony_ci#ifdef TLS1_1_VERSION 264013498266Sopenharmony_ci case TLS1_1_VERSION: 264113498266Sopenharmony_ci verstr = "TLSv1.1"; 264213498266Sopenharmony_ci break; 264313498266Sopenharmony_ci#endif 264413498266Sopenharmony_ci#ifdef TLS1_2_VERSION 264513498266Sopenharmony_ci case TLS1_2_VERSION: 264613498266Sopenharmony_ci verstr = "TLSv1.2"; 264713498266Sopenharmony_ci break; 264813498266Sopenharmony_ci#endif 264913498266Sopenharmony_ci#ifdef TLS1_3_VERSION 265013498266Sopenharmony_ci case TLS1_3_VERSION: 265113498266Sopenharmony_ci verstr = "TLSv1.3"; 265213498266Sopenharmony_ci break; 265313498266Sopenharmony_ci#endif 265413498266Sopenharmony_ci case 0: 265513498266Sopenharmony_ci break; 265613498266Sopenharmony_ci default: 265713498266Sopenharmony_ci msnprintf(unknown, sizeof(unknown), "(%x)", ssl_ver); 265813498266Sopenharmony_ci verstr = unknown; 265913498266Sopenharmony_ci break; 266013498266Sopenharmony_ci } 266113498266Sopenharmony_ci 266213498266Sopenharmony_ci /* Log progress for interesting records only (like Handshake or Alert), skip 266313498266Sopenharmony_ci * all raw record headers (content_type == SSL3_RT_HEADER or ssl_ver == 0). 266413498266Sopenharmony_ci * For TLS 1.3, skip notification of the decrypted inner Content-Type. 266513498266Sopenharmony_ci */ 266613498266Sopenharmony_ci if(ssl_ver 266713498266Sopenharmony_ci#ifdef SSL3_RT_HEADER 266813498266Sopenharmony_ci && content_type != SSL3_RT_HEADER 266913498266Sopenharmony_ci#endif 267013498266Sopenharmony_ci#ifdef SSL3_RT_INNER_CONTENT_TYPE 267113498266Sopenharmony_ci && content_type != SSL3_RT_INNER_CONTENT_TYPE 267213498266Sopenharmony_ci#endif 267313498266Sopenharmony_ci ) { 267413498266Sopenharmony_ci const char *msg_name, *tls_rt_name; 267513498266Sopenharmony_ci char ssl_buf[1024]; 267613498266Sopenharmony_ci int msg_type, txt_len; 267713498266Sopenharmony_ci 267813498266Sopenharmony_ci /* the info given when the version is zero is not that useful for us */ 267913498266Sopenharmony_ci 268013498266Sopenharmony_ci ssl_ver >>= 8; /* check the upper 8 bits only below */ 268113498266Sopenharmony_ci 268213498266Sopenharmony_ci /* SSLv2 doesn't seem to have TLS record-type headers, so OpenSSL 268313498266Sopenharmony_ci * always pass-up content-type as 0. But the interesting message-type 268413498266Sopenharmony_ci * is at 'buf[0]'. 268513498266Sopenharmony_ci */ 268613498266Sopenharmony_ci if(ssl_ver == SSL3_VERSION_MAJOR && content_type) 268713498266Sopenharmony_ci tls_rt_name = tls_rt_type(content_type); 268813498266Sopenharmony_ci else 268913498266Sopenharmony_ci tls_rt_name = ""; 269013498266Sopenharmony_ci 269113498266Sopenharmony_ci if(content_type == SSL3_RT_CHANGE_CIPHER_SPEC) { 269213498266Sopenharmony_ci msg_type = *(char *)buf; 269313498266Sopenharmony_ci msg_name = "Change cipher spec"; 269413498266Sopenharmony_ci } 269513498266Sopenharmony_ci else if(content_type == SSL3_RT_ALERT) { 269613498266Sopenharmony_ci msg_type = (((char *)buf)[0] << 8) + ((char *)buf)[1]; 269713498266Sopenharmony_ci msg_name = SSL_alert_desc_string_long(msg_type); 269813498266Sopenharmony_ci } 269913498266Sopenharmony_ci else { 270013498266Sopenharmony_ci msg_type = *(char *)buf; 270113498266Sopenharmony_ci msg_name = ssl_msg_type(ssl_ver, msg_type); 270213498266Sopenharmony_ci } 270313498266Sopenharmony_ci 270413498266Sopenharmony_ci txt_len = msnprintf(ssl_buf, sizeof(ssl_buf), 270513498266Sopenharmony_ci "%s (%s), %s, %s (%d):\n", 270613498266Sopenharmony_ci verstr, direction?"OUT":"IN", 270713498266Sopenharmony_ci tls_rt_name, msg_name, msg_type); 270813498266Sopenharmony_ci if(0 <= txt_len && (unsigned)txt_len < sizeof(ssl_buf)) { 270913498266Sopenharmony_ci Curl_debug(data, CURLINFO_TEXT, ssl_buf, (size_t)txt_len); 271013498266Sopenharmony_ci } 271113498266Sopenharmony_ci } 271213498266Sopenharmony_ci 271313498266Sopenharmony_ci Curl_debug(data, (direction == 1) ? CURLINFO_SSL_DATA_OUT : 271413498266Sopenharmony_ci CURLINFO_SSL_DATA_IN, (char *)buf, len); 271513498266Sopenharmony_ci (void) ssl; 271613498266Sopenharmony_ci} 271713498266Sopenharmony_ci#endif 271813498266Sopenharmony_ci 271913498266Sopenharmony_ci#ifdef USE_OPENSSL 272013498266Sopenharmony_ci/* ====================================================== */ 272113498266Sopenharmony_ci 272213498266Sopenharmony_ci/* Check for OpenSSL 1.0.2 which has ALPN support. */ 272313498266Sopenharmony_ci#undef HAS_ALPN 272413498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x10002000L \ 272513498266Sopenharmony_ci && !defined(OPENSSL_NO_TLSEXT) 272613498266Sopenharmony_ci# define HAS_ALPN 1 272713498266Sopenharmony_ci#endif 272813498266Sopenharmony_ci 272913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ 273013498266Sopenharmony_cistatic CURLcode 273113498266Sopenharmony_ciossl_set_ssl_version_min_max(struct Curl_cfilter *cf, SSL_CTX *ctx) 273213498266Sopenharmony_ci{ 273313498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 273413498266Sopenharmony_ci /* first, TLS min version... */ 273513498266Sopenharmony_ci long curl_ssl_version_min = conn_config->version; 273613498266Sopenharmony_ci long curl_ssl_version_max; 273713498266Sopenharmony_ci 273813498266Sopenharmony_ci /* convert curl min SSL version option to OpenSSL constant */ 273913498266Sopenharmony_ci#if (defined(OPENSSL_IS_BORINGSSL) || \ 274013498266Sopenharmony_ci defined(OPENSSL_IS_AWSLC) || \ 274113498266Sopenharmony_ci defined(LIBRESSL_VERSION_NUMBER)) 274213498266Sopenharmony_ci uint16_t ossl_ssl_version_min = 0; 274313498266Sopenharmony_ci uint16_t ossl_ssl_version_max = 0; 274413498266Sopenharmony_ci#else 274513498266Sopenharmony_ci long ossl_ssl_version_min = 0; 274613498266Sopenharmony_ci long ossl_ssl_version_max = 0; 274713498266Sopenharmony_ci#endif 274813498266Sopenharmony_ci switch(curl_ssl_version_min) { 274913498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: /* TLS 1.x */ 275013498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 275113498266Sopenharmony_ci ossl_ssl_version_min = TLS1_VERSION; 275213498266Sopenharmony_ci break; 275313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 275413498266Sopenharmony_ci ossl_ssl_version_min = TLS1_1_VERSION; 275513498266Sopenharmony_ci break; 275613498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 275713498266Sopenharmony_ci ossl_ssl_version_min = TLS1_2_VERSION; 275813498266Sopenharmony_ci break; 275913498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 276013498266Sopenharmony_ci#ifdef TLS1_3_VERSION 276113498266Sopenharmony_ci ossl_ssl_version_min = TLS1_3_VERSION; 276213498266Sopenharmony_ci break; 276313498266Sopenharmony_ci#else 276413498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 276513498266Sopenharmony_ci#endif 276613498266Sopenharmony_ci } 276713498266Sopenharmony_ci 276813498266Sopenharmony_ci /* CURL_SSLVERSION_DEFAULT means that no option was selected. 276913498266Sopenharmony_ci We don't want to pass 0 to SSL_CTX_set_min_proto_version as 277013498266Sopenharmony_ci it would enable all versions down to the lowest supported by 277113498266Sopenharmony_ci the library. 277213498266Sopenharmony_ci So we skip this, and stay with the library default 277313498266Sopenharmony_ci */ 277413498266Sopenharmony_ci if(curl_ssl_version_min != CURL_SSLVERSION_DEFAULT) { 277513498266Sopenharmony_ci if(!SSL_CTX_set_min_proto_version(ctx, ossl_ssl_version_min)) { 277613498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 277713498266Sopenharmony_ci } 277813498266Sopenharmony_ci } 277913498266Sopenharmony_ci 278013498266Sopenharmony_ci /* ... then, TLS max version */ 278113498266Sopenharmony_ci curl_ssl_version_max = conn_config->version_max; 278213498266Sopenharmony_ci 278313498266Sopenharmony_ci /* convert curl max SSL version option to OpenSSL constant */ 278413498266Sopenharmony_ci switch(curl_ssl_version_max) { 278513498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_0: 278613498266Sopenharmony_ci ossl_ssl_version_max = TLS1_VERSION; 278713498266Sopenharmony_ci break; 278813498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_1: 278913498266Sopenharmony_ci ossl_ssl_version_max = TLS1_1_VERSION; 279013498266Sopenharmony_ci break; 279113498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_2: 279213498266Sopenharmony_ci ossl_ssl_version_max = TLS1_2_VERSION; 279313498266Sopenharmony_ci break; 279413498266Sopenharmony_ci#ifdef TLS1_3_VERSION 279513498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_3: 279613498266Sopenharmony_ci ossl_ssl_version_max = TLS1_3_VERSION; 279713498266Sopenharmony_ci break; 279813498266Sopenharmony_ci#endif 279913498266Sopenharmony_ci case CURL_SSLVERSION_MAX_NONE: /* none selected */ 280013498266Sopenharmony_ci case CURL_SSLVERSION_MAX_DEFAULT: /* max selected */ 280113498266Sopenharmony_ci default: 280213498266Sopenharmony_ci /* SSL_CTX_set_max_proto_version states that: 280313498266Sopenharmony_ci setting the maximum to 0 will enable 280413498266Sopenharmony_ci protocol versions up to the highest version 280513498266Sopenharmony_ci supported by the library */ 280613498266Sopenharmony_ci ossl_ssl_version_max = 0; 280713498266Sopenharmony_ci break; 280813498266Sopenharmony_ci } 280913498266Sopenharmony_ci 281013498266Sopenharmony_ci if(!SSL_CTX_set_max_proto_version(ctx, ossl_ssl_version_max)) { 281113498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 281213498266Sopenharmony_ci } 281313498266Sopenharmony_ci 281413498266Sopenharmony_ci return CURLE_OK; 281513498266Sopenharmony_ci} 281613498266Sopenharmony_ci#endif 281713498266Sopenharmony_ci 281813498266Sopenharmony_ci#if defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC) 281913498266Sopenharmony_citypedef uint32_t ctx_option_t; 282013498266Sopenharmony_ci#elif OPENSSL_VERSION_NUMBER >= 0x30000000L 282113498266Sopenharmony_citypedef uint64_t ctx_option_t; 282213498266Sopenharmony_ci#else 282313498266Sopenharmony_citypedef long ctx_option_t; 282413498266Sopenharmony_ci#endif 282513498266Sopenharmony_ci 282613498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER < 0x10100000L) /* 1.1.0 */ 282713498266Sopenharmony_cistatic CURLcode 282813498266Sopenharmony_ciossl_set_ssl_version_min_max_legacy(ctx_option_t *ctx_options, 282913498266Sopenharmony_ci struct Curl_cfilter *cf, 283013498266Sopenharmony_ci struct Curl_easy *data) 283113498266Sopenharmony_ci{ 283213498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 283313498266Sopenharmony_ci long ssl_version = conn_config->version; 283413498266Sopenharmony_ci long ssl_version_max = conn_config->version_max; 283513498266Sopenharmony_ci 283613498266Sopenharmony_ci (void) data; /* In case it's unused. */ 283713498266Sopenharmony_ci 283813498266Sopenharmony_ci switch(ssl_version) { 283913498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 284013498266Sopenharmony_ci#ifdef TLS1_3_VERSION 284113498266Sopenharmony_ci { 284213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 284313498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 284413498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 284513498266Sopenharmony_ci DEBUGASSERT(backend); 284613498266Sopenharmony_ci SSL_CTX_set_max_proto_version(backend->ctx, TLS1_3_VERSION); 284713498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1_2; 284813498266Sopenharmony_ci } 284913498266Sopenharmony_ci#else 285013498266Sopenharmony_ci (void)ctx_options; 285113498266Sopenharmony_ci failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); 285213498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 285313498266Sopenharmony_ci#endif 285413498266Sopenharmony_ci FALLTHROUGH(); 285513498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 285613498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1000100FL 285713498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1_1; 285813498266Sopenharmony_ci#else 285913498266Sopenharmony_ci failf(data, OSSL_PACKAGE " was built without TLS 1.2 support"); 286013498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 286113498266Sopenharmony_ci#endif 286213498266Sopenharmony_ci FALLTHROUGH(); 286313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 286413498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1000100FL 286513498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1; 286613498266Sopenharmony_ci#else 286713498266Sopenharmony_ci failf(data, OSSL_PACKAGE " was built without TLS 1.1 support"); 286813498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 286913498266Sopenharmony_ci#endif 287013498266Sopenharmony_ci FALLTHROUGH(); 287113498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 287213498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: 287313498266Sopenharmony_ci break; 287413498266Sopenharmony_ci } 287513498266Sopenharmony_ci 287613498266Sopenharmony_ci switch(ssl_version_max) { 287713498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_0: 287813498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1000100FL 287913498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1_1; 288013498266Sopenharmony_ci#endif 288113498266Sopenharmony_ci FALLTHROUGH(); 288213498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_1: 288313498266Sopenharmony_ci#if OPENSSL_VERSION_NUMBER >= 0x1000100FL 288413498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1_2; 288513498266Sopenharmony_ci#endif 288613498266Sopenharmony_ci FALLTHROUGH(); 288713498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_2: 288813498266Sopenharmony_ci#ifdef TLS1_3_VERSION 288913498266Sopenharmony_ci *ctx_options |= SSL_OP_NO_TLSv1_3; 289013498266Sopenharmony_ci#endif 289113498266Sopenharmony_ci break; 289213498266Sopenharmony_ci case CURL_SSLVERSION_MAX_TLSv1_3: 289313498266Sopenharmony_ci#ifdef TLS1_3_VERSION 289413498266Sopenharmony_ci break; 289513498266Sopenharmony_ci#else 289613498266Sopenharmony_ci failf(data, OSSL_PACKAGE " was built without TLS 1.3 support"); 289713498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 289813498266Sopenharmony_ci#endif 289913498266Sopenharmony_ci } 290013498266Sopenharmony_ci return CURLE_OK; 290113498266Sopenharmony_ci} 290213498266Sopenharmony_ci#endif 290313498266Sopenharmony_ci 290413498266Sopenharmony_ci/* The "new session" callback must return zero if the session can be removed 290513498266Sopenharmony_ci * or non-zero if the session has been put into the session cache. 290613498266Sopenharmony_ci */ 290713498266Sopenharmony_cistatic int ossl_new_session_cb(SSL *ssl, SSL_SESSION *ssl_sessionid) 290813498266Sopenharmony_ci{ 290913498266Sopenharmony_ci int res = 0; 291013498266Sopenharmony_ci struct Curl_easy *data; 291113498266Sopenharmony_ci struct Curl_cfilter *cf; 291213498266Sopenharmony_ci const struct ssl_config_data *config; 291313498266Sopenharmony_ci struct ssl_connect_data *connssl; 291413498266Sopenharmony_ci bool isproxy; 291513498266Sopenharmony_ci 291613498266Sopenharmony_ci cf = (struct Curl_cfilter*) SSL_get_app_data(ssl); 291713498266Sopenharmony_ci connssl = cf? cf->ctx : NULL; 291813498266Sopenharmony_ci data = connssl? CF_DATA_CURRENT(cf) : NULL; 291913498266Sopenharmony_ci /* The sockindex has been stored as a pointer to an array element */ 292013498266Sopenharmony_ci if(!cf || !data) 292113498266Sopenharmony_ci return 0; 292213498266Sopenharmony_ci 292313498266Sopenharmony_ci isproxy = Curl_ssl_cf_is_proxy(cf); 292413498266Sopenharmony_ci 292513498266Sopenharmony_ci config = Curl_ssl_cf_get_config(cf, data); 292613498266Sopenharmony_ci if(config->primary.sessionid) { 292713498266Sopenharmony_ci bool incache; 292813498266Sopenharmony_ci bool added = FALSE; 292913498266Sopenharmony_ci void *old_ssl_sessionid = NULL; 293013498266Sopenharmony_ci 293113498266Sopenharmony_ci Curl_ssl_sessionid_lock(data); 293213498266Sopenharmony_ci if(isproxy) 293313498266Sopenharmony_ci incache = FALSE; 293413498266Sopenharmony_ci else 293513498266Sopenharmony_ci incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL)); 293613498266Sopenharmony_ci if(incache) { 293713498266Sopenharmony_ci if(old_ssl_sessionid != ssl_sessionid) { 293813498266Sopenharmony_ci infof(data, "old SSL session ID is stale, removing"); 293913498266Sopenharmony_ci Curl_ssl_delsessionid(data, old_ssl_sessionid); 294013498266Sopenharmony_ci incache = FALSE; 294113498266Sopenharmony_ci } 294213498266Sopenharmony_ci } 294313498266Sopenharmony_ci 294413498266Sopenharmony_ci if(!incache) { 294513498266Sopenharmony_ci if(!Curl_ssl_addsessionid(cf, data, ssl_sessionid, 294613498266Sopenharmony_ci 0 /* unknown size */, &added)) { 294713498266Sopenharmony_ci if(added) { 294813498266Sopenharmony_ci /* the session has been put into the session cache */ 294913498266Sopenharmony_ci res = 1; 295013498266Sopenharmony_ci } 295113498266Sopenharmony_ci } 295213498266Sopenharmony_ci else 295313498266Sopenharmony_ci failf(data, "failed to store ssl session"); 295413498266Sopenharmony_ci } 295513498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 295613498266Sopenharmony_ci } 295713498266Sopenharmony_ci 295813498266Sopenharmony_ci return res; 295913498266Sopenharmony_ci} 296013498266Sopenharmony_ci 296113498266Sopenharmony_cistatic CURLcode load_cacert_from_memory(X509_STORE *store, 296213498266Sopenharmony_ci const struct curl_blob *ca_info_blob) 296313498266Sopenharmony_ci{ 296413498266Sopenharmony_ci /* these need to be freed at the end */ 296513498266Sopenharmony_ci BIO *cbio = NULL; 296613498266Sopenharmony_ci STACK_OF(X509_INFO) *inf = NULL; 296713498266Sopenharmony_ci 296813498266Sopenharmony_ci /* everything else is just a reference */ 296913498266Sopenharmony_ci int i, count = 0; 297013498266Sopenharmony_ci X509_INFO *itmp = NULL; 297113498266Sopenharmony_ci 297213498266Sopenharmony_ci if(ca_info_blob->len > (size_t)INT_MAX) 297313498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 297413498266Sopenharmony_ci 297513498266Sopenharmony_ci cbio = BIO_new_mem_buf(ca_info_blob->data, (int)ca_info_blob->len); 297613498266Sopenharmony_ci if(!cbio) 297713498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 297813498266Sopenharmony_ci 297913498266Sopenharmony_ci inf = PEM_X509_INFO_read_bio(cbio, NULL, NULL, NULL); 298013498266Sopenharmony_ci if(!inf) { 298113498266Sopenharmony_ci BIO_free(cbio); 298213498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 298313498266Sopenharmony_ci } 298413498266Sopenharmony_ci 298513498266Sopenharmony_ci /* add each entry from PEM file to x509_store */ 298613498266Sopenharmony_ci for(i = 0; i < (int)sk_X509_INFO_num(inf); ++i) { 298713498266Sopenharmony_ci itmp = sk_X509_INFO_value(inf, i); 298813498266Sopenharmony_ci if(itmp->x509) { 298913498266Sopenharmony_ci if(X509_STORE_add_cert(store, itmp->x509)) { 299013498266Sopenharmony_ci ++count; 299113498266Sopenharmony_ci } 299213498266Sopenharmony_ci else { 299313498266Sopenharmony_ci /* set count to 0 to return an error */ 299413498266Sopenharmony_ci count = 0; 299513498266Sopenharmony_ci break; 299613498266Sopenharmony_ci } 299713498266Sopenharmony_ci } 299813498266Sopenharmony_ci if(itmp->crl) { 299913498266Sopenharmony_ci if(X509_STORE_add_crl(store, itmp->crl)) { 300013498266Sopenharmony_ci ++count; 300113498266Sopenharmony_ci } 300213498266Sopenharmony_ci else { 300313498266Sopenharmony_ci /* set count to 0 to return an error */ 300413498266Sopenharmony_ci count = 0; 300513498266Sopenharmony_ci break; 300613498266Sopenharmony_ci } 300713498266Sopenharmony_ci } 300813498266Sopenharmony_ci } 300913498266Sopenharmony_ci 301013498266Sopenharmony_ci sk_X509_INFO_pop_free(inf, X509_INFO_free); 301113498266Sopenharmony_ci BIO_free(cbio); 301213498266Sopenharmony_ci 301313498266Sopenharmony_ci /* if we didn't end up importing anything, treat that as an error */ 301413498266Sopenharmony_ci return (count > 0) ? CURLE_OK : CURLE_SSL_CACERT_BADFILE; 301513498266Sopenharmony_ci} 301613498266Sopenharmony_ci 301713498266Sopenharmony_ci#if defined(USE_WIN32_CRYPTO) 301813498266Sopenharmony_cistatic CURLcode import_windows_cert_store(struct Curl_easy *data, 301913498266Sopenharmony_ci const char *name, 302013498266Sopenharmony_ci X509_STORE *store, 302113498266Sopenharmony_ci bool *imported) 302213498266Sopenharmony_ci{ 302313498266Sopenharmony_ci CURLcode result = CURLE_OK; 302413498266Sopenharmony_ci HCERTSTORE hStore; 302513498266Sopenharmony_ci 302613498266Sopenharmony_ci *imported = false; 302713498266Sopenharmony_ci 302813498266Sopenharmony_ci hStore = CertOpenSystemStoreA(0, name); 302913498266Sopenharmony_ci if(hStore) { 303013498266Sopenharmony_ci PCCERT_CONTEXT pContext = NULL; 303113498266Sopenharmony_ci /* The array of enhanced key usage OIDs will vary per certificate and 303213498266Sopenharmony_ci is declared outside of the loop so that rather than malloc/free each 303313498266Sopenharmony_ci iteration we can grow it with realloc, when necessary. */ 303413498266Sopenharmony_ci CERT_ENHKEY_USAGE *enhkey_usage = NULL; 303513498266Sopenharmony_ci DWORD enhkey_usage_size = 0; 303613498266Sopenharmony_ci 303713498266Sopenharmony_ci /* This loop makes a best effort to import all valid certificates from 303813498266Sopenharmony_ci the MS root store. If a certificate cannot be imported it is 303913498266Sopenharmony_ci skipped. 'result' is used to store only hard-fail conditions (such 304013498266Sopenharmony_ci as out of memory) that cause an early break. */ 304113498266Sopenharmony_ci result = CURLE_OK; 304213498266Sopenharmony_ci for(;;) { 304313498266Sopenharmony_ci X509 *x509; 304413498266Sopenharmony_ci FILETIME now; 304513498266Sopenharmony_ci BYTE key_usage[2]; 304613498266Sopenharmony_ci DWORD req_size; 304713498266Sopenharmony_ci const unsigned char *encoded_cert; 304813498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 304913498266Sopenharmony_ci char cert_name[256]; 305013498266Sopenharmony_ci#endif 305113498266Sopenharmony_ci 305213498266Sopenharmony_ci pContext = CertEnumCertificatesInStore(hStore, pContext); 305313498266Sopenharmony_ci if(!pContext) 305413498266Sopenharmony_ci break; 305513498266Sopenharmony_ci 305613498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 305713498266Sopenharmony_ci if(!CertGetNameStringA(pContext, CERT_NAME_SIMPLE_DISPLAY_TYPE, 0, 305813498266Sopenharmony_ci NULL, cert_name, sizeof(cert_name))) { 305913498266Sopenharmony_ci strcpy(cert_name, "Unknown"); 306013498266Sopenharmony_ci } 306113498266Sopenharmony_ci infof(data, "SSL: Checking cert \"%s\"", cert_name); 306213498266Sopenharmony_ci#endif 306313498266Sopenharmony_ci encoded_cert = (const unsigned char *)pContext->pbCertEncoded; 306413498266Sopenharmony_ci if(!encoded_cert) 306513498266Sopenharmony_ci continue; 306613498266Sopenharmony_ci 306713498266Sopenharmony_ci GetSystemTimeAsFileTime(&now); 306813498266Sopenharmony_ci if(CompareFileTime(&pContext->pCertInfo->NotBefore, &now) > 0 || 306913498266Sopenharmony_ci CompareFileTime(&now, &pContext->pCertInfo->NotAfter) > 0) 307013498266Sopenharmony_ci continue; 307113498266Sopenharmony_ci 307213498266Sopenharmony_ci /* If key usage exists check for signing attribute */ 307313498266Sopenharmony_ci if(CertGetIntendedKeyUsage(pContext->dwCertEncodingType, 307413498266Sopenharmony_ci pContext->pCertInfo, 307513498266Sopenharmony_ci key_usage, sizeof(key_usage))) { 307613498266Sopenharmony_ci if(!(key_usage[0] & CERT_KEY_CERT_SIGN_KEY_USAGE)) 307713498266Sopenharmony_ci continue; 307813498266Sopenharmony_ci } 307913498266Sopenharmony_ci else if(GetLastError()) 308013498266Sopenharmony_ci continue; 308113498266Sopenharmony_ci 308213498266Sopenharmony_ci /* If enhanced key usage exists check for server auth attribute. 308313498266Sopenharmony_ci * 308413498266Sopenharmony_ci * Note "In a Microsoft environment, a certificate might also have 308513498266Sopenharmony_ci * EKU extended properties that specify valid uses for the 308613498266Sopenharmony_ci * certificate." The call below checks both, and behavior varies 308713498266Sopenharmony_ci * depending on what is found. For more details see 308813498266Sopenharmony_ci * CertGetEnhancedKeyUsage doc. 308913498266Sopenharmony_ci */ 309013498266Sopenharmony_ci if(CertGetEnhancedKeyUsage(pContext, 0, NULL, &req_size)) { 309113498266Sopenharmony_ci if(req_size && req_size > enhkey_usage_size) { 309213498266Sopenharmony_ci void *tmp = realloc(enhkey_usage, req_size); 309313498266Sopenharmony_ci 309413498266Sopenharmony_ci if(!tmp) { 309513498266Sopenharmony_ci failf(data, "SSL: Out of memory allocating for OID list"); 309613498266Sopenharmony_ci result = CURLE_OUT_OF_MEMORY; 309713498266Sopenharmony_ci break; 309813498266Sopenharmony_ci } 309913498266Sopenharmony_ci 310013498266Sopenharmony_ci enhkey_usage = (CERT_ENHKEY_USAGE *)tmp; 310113498266Sopenharmony_ci enhkey_usage_size = req_size; 310213498266Sopenharmony_ci } 310313498266Sopenharmony_ci 310413498266Sopenharmony_ci if(CertGetEnhancedKeyUsage(pContext, 0, enhkey_usage, &req_size)) { 310513498266Sopenharmony_ci if(!enhkey_usage->cUsageIdentifier) { 310613498266Sopenharmony_ci /* "If GetLastError returns CRYPT_E_NOT_FOUND, the certificate 310713498266Sopenharmony_ci is good for all uses. If it returns zero, the certificate 310813498266Sopenharmony_ci has no valid uses." */ 310913498266Sopenharmony_ci if((HRESULT)GetLastError() != CRYPT_E_NOT_FOUND) 311013498266Sopenharmony_ci continue; 311113498266Sopenharmony_ci } 311213498266Sopenharmony_ci else { 311313498266Sopenharmony_ci DWORD i; 311413498266Sopenharmony_ci bool found = false; 311513498266Sopenharmony_ci 311613498266Sopenharmony_ci for(i = 0; i < enhkey_usage->cUsageIdentifier; ++i) { 311713498266Sopenharmony_ci if(!strcmp("1.3.6.1.5.5.7.3.1" /* OID server auth */, 311813498266Sopenharmony_ci enhkey_usage->rgpszUsageIdentifier[i])) { 311913498266Sopenharmony_ci found = true; 312013498266Sopenharmony_ci break; 312113498266Sopenharmony_ci } 312213498266Sopenharmony_ci } 312313498266Sopenharmony_ci 312413498266Sopenharmony_ci if(!found) 312513498266Sopenharmony_ci continue; 312613498266Sopenharmony_ci } 312713498266Sopenharmony_ci } 312813498266Sopenharmony_ci else 312913498266Sopenharmony_ci continue; 313013498266Sopenharmony_ci } 313113498266Sopenharmony_ci else 313213498266Sopenharmony_ci continue; 313313498266Sopenharmony_ci 313413498266Sopenharmony_ci x509 = d2i_X509(NULL, &encoded_cert, pContext->cbCertEncoded); 313513498266Sopenharmony_ci if(!x509) 313613498266Sopenharmony_ci continue; 313713498266Sopenharmony_ci 313813498266Sopenharmony_ci /* Try to import the certificate. This may fail for legitimate 313913498266Sopenharmony_ci reasons such as duplicate certificate, which is allowed by MS but 314013498266Sopenharmony_ci not OpenSSL. */ 314113498266Sopenharmony_ci if(X509_STORE_add_cert(store, x509) == 1) { 314213498266Sopenharmony_ci#if defined(DEBUGBUILD) && !defined(CURL_DISABLE_VERBOSE_STRINGS) 314313498266Sopenharmony_ci infof(data, "SSL: Imported cert \"%s\"", cert_name); 314413498266Sopenharmony_ci#endif 314513498266Sopenharmony_ci *imported = true; 314613498266Sopenharmony_ci } 314713498266Sopenharmony_ci X509_free(x509); 314813498266Sopenharmony_ci } 314913498266Sopenharmony_ci 315013498266Sopenharmony_ci free(enhkey_usage); 315113498266Sopenharmony_ci CertFreeCertificateContext(pContext); 315213498266Sopenharmony_ci CertCloseStore(hStore, 0); 315313498266Sopenharmony_ci 315413498266Sopenharmony_ci if(result) 315513498266Sopenharmony_ci return result; 315613498266Sopenharmony_ci } 315713498266Sopenharmony_ci 315813498266Sopenharmony_ci return result; 315913498266Sopenharmony_ci} 316013498266Sopenharmony_ci#endif 316113498266Sopenharmony_ci 316213498266Sopenharmony_cistatic CURLcode populate_x509_store(struct Curl_cfilter *cf, 316313498266Sopenharmony_ci struct Curl_easy *data, 316413498266Sopenharmony_ci X509_STORE *store) 316513498266Sopenharmony_ci{ 316613498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 316713498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 316813498266Sopenharmony_ci CURLcode result = CURLE_OK; 316913498266Sopenharmony_ci X509_LOOKUP *lookup = NULL; 317013498266Sopenharmony_ci const struct curl_blob *ca_info_blob = conn_config->ca_info_blob; 317113498266Sopenharmony_ci const char * const ssl_cafile = 317213498266Sopenharmony_ci /* CURLOPT_CAINFO_BLOB overrides CURLOPT_CAINFO */ 317313498266Sopenharmony_ci (ca_info_blob ? NULL : conn_config->CAfile); 317413498266Sopenharmony_ci const char * const ssl_capath = conn_config->CApath; 317513498266Sopenharmony_ci const char * const ssl_crlfile = ssl_config->primary.CRLfile; 317613498266Sopenharmony_ci const bool verifypeer = conn_config->verifypeer; 317713498266Sopenharmony_ci bool imported_native_ca = false; 317813498266Sopenharmony_ci bool imported_ca_info_blob = false; 317913498266Sopenharmony_ci 318013498266Sopenharmony_ci CURL_TRC_CF(data, cf, "populate_x509_store, path=%s, blob=%d", 318113498266Sopenharmony_ci ssl_cafile? ssl_cafile : "none", !!ca_info_blob); 318213498266Sopenharmony_ci if(!store) 318313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 318413498266Sopenharmony_ci 318513498266Sopenharmony_ci if(verifypeer) { 318613498266Sopenharmony_ci#if defined(USE_WIN32_CRYPTO) 318713498266Sopenharmony_ci /* Import certificates from the Windows root certificate store if 318813498266Sopenharmony_ci requested. 318913498266Sopenharmony_ci https://stackoverflow.com/questions/9507184/ 319013498266Sopenharmony_ci https://github.com/d3x0r/SACK/blob/master/src/netlib/ssl_layer.c#L1037 319113498266Sopenharmony_ci https://datatracker.ietf.org/doc/html/rfc5280 */ 319213498266Sopenharmony_ci if(ssl_config->native_ca_store) { 319313498266Sopenharmony_ci const char *storeNames[] = { 319413498266Sopenharmony_ci "ROOT", /* Trusted Root Certification Authorities */ 319513498266Sopenharmony_ci "CA" /* Intermediate Certification Authorities */ 319613498266Sopenharmony_ci }; 319713498266Sopenharmony_ci size_t i; 319813498266Sopenharmony_ci for(i = 0; i < ARRAYSIZE(storeNames); ++i) { 319913498266Sopenharmony_ci bool imported = false; 320013498266Sopenharmony_ci result = import_windows_cert_store(data, storeNames[i], store, 320113498266Sopenharmony_ci &imported); 320213498266Sopenharmony_ci if(result) 320313498266Sopenharmony_ci return result; 320413498266Sopenharmony_ci if(imported) { 320513498266Sopenharmony_ci infof(data, "successfully imported Windows %s store", storeNames[i]); 320613498266Sopenharmony_ci imported_native_ca = true; 320713498266Sopenharmony_ci } 320813498266Sopenharmony_ci else 320913498266Sopenharmony_ci infof(data, "error importing Windows %s store, continuing anyway", 321013498266Sopenharmony_ci storeNames[i]); 321113498266Sopenharmony_ci } 321213498266Sopenharmony_ci } 321313498266Sopenharmony_ci#endif 321413498266Sopenharmony_ci if(ca_info_blob) { 321513498266Sopenharmony_ci result = load_cacert_from_memory(store, ca_info_blob); 321613498266Sopenharmony_ci if(result) { 321713498266Sopenharmony_ci failf(data, "error importing CA certificate blob"); 321813498266Sopenharmony_ci return result; 321913498266Sopenharmony_ci } 322013498266Sopenharmony_ci else { 322113498266Sopenharmony_ci imported_ca_info_blob = true; 322213498266Sopenharmony_ci infof(data, "successfully imported CA certificate blob"); 322313498266Sopenharmony_ci } 322413498266Sopenharmony_ci } 322513498266Sopenharmony_ci 322613498266Sopenharmony_ci if(ssl_cafile || ssl_capath) { 322713498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) 322813498266Sopenharmony_ci /* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */ 322913498266Sopenharmony_ci if(ssl_cafile && !X509_STORE_load_file(store, ssl_cafile)) { 323013498266Sopenharmony_ci if(!imported_native_ca && !imported_ca_info_blob) { 323113498266Sopenharmony_ci /* Fail if we insist on successfully verifying the server. */ 323213498266Sopenharmony_ci failf(data, "error setting certificate file: %s", ssl_cafile); 323313498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 323413498266Sopenharmony_ci } 323513498266Sopenharmony_ci else 323613498266Sopenharmony_ci infof(data, "error setting certificate file, continuing anyway"); 323713498266Sopenharmony_ci } 323813498266Sopenharmony_ci if(ssl_capath && !X509_STORE_load_path(store, ssl_capath)) { 323913498266Sopenharmony_ci if(!imported_native_ca && !imported_ca_info_blob) { 324013498266Sopenharmony_ci /* Fail if we insist on successfully verifying the server. */ 324113498266Sopenharmony_ci failf(data, "error setting certificate path: %s", ssl_capath); 324213498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 324313498266Sopenharmony_ci } 324413498266Sopenharmony_ci else 324513498266Sopenharmony_ci infof(data, "error setting certificate path, continuing anyway"); 324613498266Sopenharmony_ci } 324713498266Sopenharmony_ci#else 324813498266Sopenharmony_ci /* tell OpenSSL where to find CA certificates that are used to verify the 324913498266Sopenharmony_ci server's certificate. */ 325013498266Sopenharmony_ci if(!X509_STORE_load_locations(store, ssl_cafile, ssl_capath)) { 325113498266Sopenharmony_ci if(!imported_native_ca && !imported_ca_info_blob) { 325213498266Sopenharmony_ci /* Fail if we insist on successfully verifying the server. */ 325313498266Sopenharmony_ci failf(data, "error setting certificate verify locations:" 325413498266Sopenharmony_ci " CAfile: %s CApath: %s", 325513498266Sopenharmony_ci ssl_cafile ? ssl_cafile : "none", 325613498266Sopenharmony_ci ssl_capath ? ssl_capath : "none"); 325713498266Sopenharmony_ci return CURLE_SSL_CACERT_BADFILE; 325813498266Sopenharmony_ci } 325913498266Sopenharmony_ci else { 326013498266Sopenharmony_ci infof(data, "error setting certificate verify locations," 326113498266Sopenharmony_ci " continuing anyway"); 326213498266Sopenharmony_ci } 326313498266Sopenharmony_ci } 326413498266Sopenharmony_ci#endif 326513498266Sopenharmony_ci infof(data, " CAfile: %s", ssl_cafile ? ssl_cafile : "none"); 326613498266Sopenharmony_ci infof(data, " CApath: %s", ssl_capath ? ssl_capath : "none"); 326713498266Sopenharmony_ci } 326813498266Sopenharmony_ci 326913498266Sopenharmony_ci#ifdef CURL_CA_FALLBACK 327013498266Sopenharmony_ci if(!ssl_cafile && !ssl_capath && 327113498266Sopenharmony_ci !imported_native_ca && !imported_ca_info_blob) { 327213498266Sopenharmony_ci /* verifying the peer without any CA certificates won't 327313498266Sopenharmony_ci work so use openssl's built-in default as fallback */ 327413498266Sopenharmony_ci X509_STORE_set_default_paths(store); 327513498266Sopenharmony_ci } 327613498266Sopenharmony_ci#endif 327713498266Sopenharmony_ci } 327813498266Sopenharmony_ci 327913498266Sopenharmony_ci if(ssl_crlfile) { 328013498266Sopenharmony_ci /* tell OpenSSL where to find CRL file that is used to check certificate 328113498266Sopenharmony_ci * revocation */ 328213498266Sopenharmony_ci lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()); 328313498266Sopenharmony_ci if(!lookup || 328413498266Sopenharmony_ci (!X509_load_crl_file(lookup, ssl_crlfile, X509_FILETYPE_PEM)) ) { 328513498266Sopenharmony_ci failf(data, "error loading CRL file: %s", ssl_crlfile); 328613498266Sopenharmony_ci return CURLE_SSL_CRL_BADFILE; 328713498266Sopenharmony_ci } 328813498266Sopenharmony_ci /* Everything is fine. */ 328913498266Sopenharmony_ci infof(data, "successfully loaded CRL file:"); 329013498266Sopenharmony_ci X509_STORE_set_flags(store, 329113498266Sopenharmony_ci X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL); 329213498266Sopenharmony_ci 329313498266Sopenharmony_ci infof(data, " CRLfile: %s", ssl_crlfile); 329413498266Sopenharmony_ci } 329513498266Sopenharmony_ci 329613498266Sopenharmony_ci if(verifypeer) { 329713498266Sopenharmony_ci /* Try building a chain using issuers in the trusted store first to avoid 329813498266Sopenharmony_ci problems with server-sent legacy intermediates. Newer versions of 329913498266Sopenharmony_ci OpenSSL do alternate chain checking by default but we do not know how to 330013498266Sopenharmony_ci determine that in a reliable manner. 330113498266Sopenharmony_ci https://rt.openssl.org/Ticket/Display.html?id=3621&user=guest&pass=guest 330213498266Sopenharmony_ci */ 330313498266Sopenharmony_ci#if defined(X509_V_FLAG_TRUSTED_FIRST) 330413498266Sopenharmony_ci X509_STORE_set_flags(store, X509_V_FLAG_TRUSTED_FIRST); 330513498266Sopenharmony_ci#endif 330613498266Sopenharmony_ci#ifdef X509_V_FLAG_PARTIAL_CHAIN 330713498266Sopenharmony_ci if(!ssl_config->no_partialchain && !ssl_crlfile) { 330813498266Sopenharmony_ci /* Have intermediate certificates in the trust store be treated as 330913498266Sopenharmony_ci trust-anchors, in the same way as self-signed root CA certificates 331013498266Sopenharmony_ci are. This allows users to verify servers using the intermediate cert 331113498266Sopenharmony_ci only, instead of needing the whole chain. 331213498266Sopenharmony_ci 331313498266Sopenharmony_ci Due to OpenSSL bug https://github.com/openssl/openssl/issues/5081 we 331413498266Sopenharmony_ci cannot do partial chains with a CRL check. 331513498266Sopenharmony_ci */ 331613498266Sopenharmony_ci X509_STORE_set_flags(store, X509_V_FLAG_PARTIAL_CHAIN); 331713498266Sopenharmony_ci } 331813498266Sopenharmony_ci#endif 331913498266Sopenharmony_ci } 332013498266Sopenharmony_ci 332113498266Sopenharmony_ci return result; 332213498266Sopenharmony_ci} 332313498266Sopenharmony_ci 332413498266Sopenharmony_ci#if defined(HAVE_SSL_X509_STORE_SHARE) 332513498266Sopenharmony_cistatic bool cached_x509_store_expired(const struct Curl_easy *data, 332613498266Sopenharmony_ci const struct multi_ssl_backend_data *mb) 332713498266Sopenharmony_ci{ 332813498266Sopenharmony_ci const struct ssl_general_config *cfg = &data->set.general_ssl; 332913498266Sopenharmony_ci struct curltime now = Curl_now(); 333013498266Sopenharmony_ci timediff_t elapsed_ms = Curl_timediff(now, mb->time); 333113498266Sopenharmony_ci timediff_t timeout_ms = cfg->ca_cache_timeout * (timediff_t)1000; 333213498266Sopenharmony_ci 333313498266Sopenharmony_ci if(timeout_ms < 0) 333413498266Sopenharmony_ci return false; 333513498266Sopenharmony_ci 333613498266Sopenharmony_ci return elapsed_ms >= timeout_ms; 333713498266Sopenharmony_ci} 333813498266Sopenharmony_ci 333913498266Sopenharmony_cistatic bool cached_x509_store_different( 334013498266Sopenharmony_ci struct Curl_cfilter *cf, 334113498266Sopenharmony_ci const struct multi_ssl_backend_data *mb) 334213498266Sopenharmony_ci{ 334313498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 334413498266Sopenharmony_ci if(!mb->CAfile || !conn_config->CAfile) 334513498266Sopenharmony_ci return mb->CAfile != conn_config->CAfile; 334613498266Sopenharmony_ci 334713498266Sopenharmony_ci return strcmp(mb->CAfile, conn_config->CAfile); 334813498266Sopenharmony_ci} 334913498266Sopenharmony_ci 335013498266Sopenharmony_cistatic X509_STORE *get_cached_x509_store(struct Curl_cfilter *cf, 335113498266Sopenharmony_ci const struct Curl_easy *data) 335213498266Sopenharmony_ci{ 335313498266Sopenharmony_ci struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; 335413498266Sopenharmony_ci X509_STORE *store = NULL; 335513498266Sopenharmony_ci 335613498266Sopenharmony_ci DEBUGASSERT(multi); 335713498266Sopenharmony_ci if(multi && 335813498266Sopenharmony_ci multi->ssl_backend_data && 335913498266Sopenharmony_ci multi->ssl_backend_data->store && 336013498266Sopenharmony_ci !cached_x509_store_expired(data, multi->ssl_backend_data) && 336113498266Sopenharmony_ci !cached_x509_store_different(cf, multi->ssl_backend_data)) { 336213498266Sopenharmony_ci store = multi->ssl_backend_data->store; 336313498266Sopenharmony_ci } 336413498266Sopenharmony_ci 336513498266Sopenharmony_ci return store; 336613498266Sopenharmony_ci} 336713498266Sopenharmony_ci 336813498266Sopenharmony_cistatic void set_cached_x509_store(struct Curl_cfilter *cf, 336913498266Sopenharmony_ci const struct Curl_easy *data, 337013498266Sopenharmony_ci X509_STORE *store) 337113498266Sopenharmony_ci{ 337213498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 337313498266Sopenharmony_ci struct Curl_multi *multi = data->multi_easy ? data->multi_easy : data->multi; 337413498266Sopenharmony_ci struct multi_ssl_backend_data *mbackend; 337513498266Sopenharmony_ci 337613498266Sopenharmony_ci DEBUGASSERT(multi); 337713498266Sopenharmony_ci if(!multi) 337813498266Sopenharmony_ci return; 337913498266Sopenharmony_ci 338013498266Sopenharmony_ci if(!multi->ssl_backend_data) { 338113498266Sopenharmony_ci multi->ssl_backend_data = calloc(1, sizeof(struct multi_ssl_backend_data)); 338213498266Sopenharmony_ci if(!multi->ssl_backend_data) 338313498266Sopenharmony_ci return; 338413498266Sopenharmony_ci } 338513498266Sopenharmony_ci 338613498266Sopenharmony_ci mbackend = multi->ssl_backend_data; 338713498266Sopenharmony_ci 338813498266Sopenharmony_ci if(X509_STORE_up_ref(store)) { 338913498266Sopenharmony_ci char *CAfile = NULL; 339013498266Sopenharmony_ci 339113498266Sopenharmony_ci if(conn_config->CAfile) { 339213498266Sopenharmony_ci CAfile = strdup(conn_config->CAfile); 339313498266Sopenharmony_ci if(!CAfile) { 339413498266Sopenharmony_ci X509_STORE_free(store); 339513498266Sopenharmony_ci return; 339613498266Sopenharmony_ci } 339713498266Sopenharmony_ci } 339813498266Sopenharmony_ci 339913498266Sopenharmony_ci if(mbackend->store) { 340013498266Sopenharmony_ci X509_STORE_free(mbackend->store); 340113498266Sopenharmony_ci free(mbackend->CAfile); 340213498266Sopenharmony_ci } 340313498266Sopenharmony_ci 340413498266Sopenharmony_ci mbackend->time = Curl_now(); 340513498266Sopenharmony_ci mbackend->store = store; 340613498266Sopenharmony_ci mbackend->CAfile = CAfile; 340713498266Sopenharmony_ci } 340813498266Sopenharmony_ci} 340913498266Sopenharmony_ci 341013498266Sopenharmony_ciCURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, 341113498266Sopenharmony_ci struct Curl_easy *data, 341213498266Sopenharmony_ci SSL_CTX *ssl_ctx) 341313498266Sopenharmony_ci{ 341413498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 341513498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 341613498266Sopenharmony_ci CURLcode result = CURLE_OK; 341713498266Sopenharmony_ci X509_STORE *cached_store; 341813498266Sopenharmony_ci bool cache_criteria_met; 341913498266Sopenharmony_ci 342013498266Sopenharmony_ci /* Consider the X509 store cacheable if it comes exclusively from a CAfile, 342113498266Sopenharmony_ci or no source is provided and we are falling back to openssl's built-in 342213498266Sopenharmony_ci default. */ 342313498266Sopenharmony_ci cache_criteria_met = (data->set.general_ssl.ca_cache_timeout != 0) && 342413498266Sopenharmony_ci conn_config->verifypeer && 342513498266Sopenharmony_ci !conn_config->CApath && 342613498266Sopenharmony_ci !conn_config->ca_info_blob && 342713498266Sopenharmony_ci !ssl_config->primary.CRLfile && 342813498266Sopenharmony_ci !ssl_config->native_ca_store; 342913498266Sopenharmony_ci 343013498266Sopenharmony_ci cached_store = get_cached_x509_store(cf, data); 343113498266Sopenharmony_ci if(cached_store && cache_criteria_met && X509_STORE_up_ref(cached_store)) { 343213498266Sopenharmony_ci SSL_CTX_set_cert_store(ssl_ctx, cached_store); 343313498266Sopenharmony_ci } 343413498266Sopenharmony_ci else { 343513498266Sopenharmony_ci X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); 343613498266Sopenharmony_ci 343713498266Sopenharmony_ci result = populate_x509_store(cf, data, store); 343813498266Sopenharmony_ci if(result == CURLE_OK && cache_criteria_met) { 343913498266Sopenharmony_ci set_cached_x509_store(cf, data, store); 344013498266Sopenharmony_ci } 344113498266Sopenharmony_ci } 344213498266Sopenharmony_ci 344313498266Sopenharmony_ci return result; 344413498266Sopenharmony_ci} 344513498266Sopenharmony_ci#else /* HAVE_SSL_X509_STORE_SHARE */ 344613498266Sopenharmony_ciCURLcode Curl_ssl_setup_x509_store(struct Curl_cfilter *cf, 344713498266Sopenharmony_ci struct Curl_easy *data, 344813498266Sopenharmony_ci SSL_CTX *ssl_ctx) 344913498266Sopenharmony_ci{ 345013498266Sopenharmony_ci X509_STORE *store = SSL_CTX_get_cert_store(ssl_ctx); 345113498266Sopenharmony_ci 345213498266Sopenharmony_ci return populate_x509_store(cf, data, store); 345313498266Sopenharmony_ci} 345413498266Sopenharmony_ci#endif /* HAVE_SSL_X509_STORE_SHARE */ 345513498266Sopenharmony_ci 345613498266Sopenharmony_cistatic CURLcode ossl_connect_step1(struct Curl_cfilter *cf, 345713498266Sopenharmony_ci struct Curl_easy *data) 345813498266Sopenharmony_ci{ 345913498266Sopenharmony_ci CURLcode result = CURLE_OK; 346013498266Sopenharmony_ci char *ciphers; 346113498266Sopenharmony_ci SSL_METHOD_QUAL SSL_METHOD *req_method = NULL; 346213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 346313498266Sopenharmony_ci ctx_option_t ctx_options = 0; 346413498266Sopenharmony_ci void *ssl_sessionid = NULL; 346513498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 346613498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 346713498266Sopenharmony_ci BIO *bio; 346813498266Sopenharmony_ci const long int ssl_version = conn_config->version; 346913498266Sopenharmony_ci char * const ssl_cert = ssl_config->primary.clientcert; 347013498266Sopenharmony_ci const struct curl_blob *ssl_cert_blob = ssl_config->primary.cert_blob; 347113498266Sopenharmony_ci const char * const ssl_cert_type = ssl_config->cert_type; 347213498266Sopenharmony_ci const bool verifypeer = conn_config->verifypeer; 347313498266Sopenharmony_ci char error_buffer[256]; 347413498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 347513498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 347613498266Sopenharmony_ci 347713498266Sopenharmony_ci DEBUGASSERT(ssl_connect_1 == connssl->connecting_state); 347813498266Sopenharmony_ci DEBUGASSERT(backend); 347913498266Sopenharmony_ci 348013498266Sopenharmony_ci /* Make funny stuff to get random input */ 348113498266Sopenharmony_ci result = ossl_seed(data); 348213498266Sopenharmony_ci if(result) 348313498266Sopenharmony_ci return result; 348413498266Sopenharmony_ci 348513498266Sopenharmony_ci ssl_config->certverifyresult = !X509_V_OK; 348613498266Sopenharmony_ci 348713498266Sopenharmony_ci /* check to see if we've been told to use an explicit SSL/TLS version */ 348813498266Sopenharmony_ci 348913498266Sopenharmony_ci switch(ssl_version) { 349013498266Sopenharmony_ci case CURL_SSLVERSION_DEFAULT: 349113498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: 349213498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: 349313498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: 349413498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: 349513498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: 349613498266Sopenharmony_ci /* it will be handled later with the context options */ 349713498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) 349813498266Sopenharmony_ci req_method = TLS_client_method(); 349913498266Sopenharmony_ci#else 350013498266Sopenharmony_ci req_method = SSLv23_client_method(); 350113498266Sopenharmony_ci#endif 350213498266Sopenharmony_ci break; 350313498266Sopenharmony_ci case CURL_SSLVERSION_SSLv2: 350413498266Sopenharmony_ci failf(data, "No SSLv2 support"); 350513498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 350613498266Sopenharmony_ci case CURL_SSLVERSION_SSLv3: 350713498266Sopenharmony_ci failf(data, "No SSLv3 support"); 350813498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 350913498266Sopenharmony_ci default: 351013498266Sopenharmony_ci failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 351113498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 351213498266Sopenharmony_ci } 351313498266Sopenharmony_ci 351413498266Sopenharmony_ci if(backend->ctx) { 351513498266Sopenharmony_ci /* This happens when an error was encountered before in this 351613498266Sopenharmony_ci * step and we are called to do it again. Get rid of any leftover 351713498266Sopenharmony_ci * from the previous call. */ 351813498266Sopenharmony_ci ossl_close(cf, data); 351913498266Sopenharmony_ci } 352013498266Sopenharmony_ci backend->ctx = SSL_CTX_new(req_method); 352113498266Sopenharmony_ci 352213498266Sopenharmony_ci if(!backend->ctx) { 352313498266Sopenharmony_ci failf(data, "SSL: couldn't create a context: %s", 352413498266Sopenharmony_ci ossl_strerror(ERR_peek_error(), error_buffer, sizeof(error_buffer))); 352513498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 352613498266Sopenharmony_ci } 352713498266Sopenharmony_ci 352813498266Sopenharmony_ci#ifdef SSL_MODE_RELEASE_BUFFERS 352913498266Sopenharmony_ci SSL_CTX_set_mode(backend->ctx, SSL_MODE_RELEASE_BUFFERS); 353013498266Sopenharmony_ci#endif 353113498266Sopenharmony_ci 353213498266Sopenharmony_ci#ifdef SSL_CTRL_SET_MSG_CALLBACK 353313498266Sopenharmony_ci if(data->set.fdebug && data->set.verbose) { 353413498266Sopenharmony_ci /* the SSL trace callback is only used for verbose logging */ 353513498266Sopenharmony_ci SSL_CTX_set_msg_callback(backend->ctx, ossl_trace); 353613498266Sopenharmony_ci SSL_CTX_set_msg_callback_arg(backend->ctx, cf); 353713498266Sopenharmony_ci } 353813498266Sopenharmony_ci#endif 353913498266Sopenharmony_ci 354013498266Sopenharmony_ci /* OpenSSL contains code to work around lots of bugs and flaws in various 354113498266Sopenharmony_ci SSL-implementations. SSL_CTX_set_options() is used to enabled those 354213498266Sopenharmony_ci work-arounds. The man page for this option states that SSL_OP_ALL enables 354313498266Sopenharmony_ci all the work-arounds and that "It is usually safe to use SSL_OP_ALL to 354413498266Sopenharmony_ci enable the bug workaround options if compatibility with somewhat broken 354513498266Sopenharmony_ci implementations is desired." 354613498266Sopenharmony_ci 354713498266Sopenharmony_ci The "-no_ticket" option was introduced in OpenSSL 0.9.8j. It's a flag to 354813498266Sopenharmony_ci disable "rfc4507bis session ticket support". rfc4507bis was later turned 354913498266Sopenharmony_ci into the proper RFC5077: https://datatracker.ietf.org/doc/html/rfc5077 355013498266Sopenharmony_ci 355113498266Sopenharmony_ci The enabled extension concerns the session management. I wonder how often 355213498266Sopenharmony_ci libcurl stops a connection and then resumes a TLS session. Also, sending 355313498266Sopenharmony_ci the session data is some overhead. I suggest that you just use your 355413498266Sopenharmony_ci proposed patch (which explicitly disables TICKET). 355513498266Sopenharmony_ci 355613498266Sopenharmony_ci If someone writes an application with libcurl and OpenSSL who wants to 355713498266Sopenharmony_ci enable the feature, one can do this in the SSL callback. 355813498266Sopenharmony_ci 355913498266Sopenharmony_ci SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG option enabling allowed proper 356013498266Sopenharmony_ci interoperability with web server Netscape Enterprise Server 2.0.1 which 356113498266Sopenharmony_ci was released back in 1996. 356213498266Sopenharmony_ci 356313498266Sopenharmony_ci Due to CVE-2010-4180, option SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG has 356413498266Sopenharmony_ci become ineffective as of OpenSSL 0.9.8q and 1.0.0c. In order to mitigate 356513498266Sopenharmony_ci CVE-2010-4180 when using previous OpenSSL versions we no longer enable 356613498266Sopenharmony_ci this option regardless of OpenSSL version and SSL_OP_ALL definition. 356713498266Sopenharmony_ci 356813498266Sopenharmony_ci OpenSSL added a work-around for a SSL 3.0/TLS 1.0 CBC vulnerability 356913498266Sopenharmony_ci (https://www.openssl.org/~bodo/tls-cbc.txt). In 0.9.6e they added a bit to 357013498266Sopenharmony_ci SSL_OP_ALL that _disables_ that work-around despite the fact that 357113498266Sopenharmony_ci SSL_OP_ALL is documented to do "rather harmless" workarounds. In order to 357213498266Sopenharmony_ci keep the secure work-around, the SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS bit 357313498266Sopenharmony_ci must not be set. 357413498266Sopenharmony_ci */ 357513498266Sopenharmony_ci 357613498266Sopenharmony_ci ctx_options = SSL_OP_ALL; 357713498266Sopenharmony_ci 357813498266Sopenharmony_ci#ifdef SSL_OP_NO_TICKET 357913498266Sopenharmony_ci ctx_options |= SSL_OP_NO_TICKET; 358013498266Sopenharmony_ci#endif 358113498266Sopenharmony_ci 358213498266Sopenharmony_ci#ifdef SSL_OP_NO_COMPRESSION 358313498266Sopenharmony_ci ctx_options |= SSL_OP_NO_COMPRESSION; 358413498266Sopenharmony_ci#endif 358513498266Sopenharmony_ci 358613498266Sopenharmony_ci#ifdef SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG 358713498266Sopenharmony_ci /* mitigate CVE-2010-4180 */ 358813498266Sopenharmony_ci ctx_options &= ~SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG; 358913498266Sopenharmony_ci#endif 359013498266Sopenharmony_ci 359113498266Sopenharmony_ci#ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS 359213498266Sopenharmony_ci /* unless the user explicitly asks to allow the protocol vulnerability we 359313498266Sopenharmony_ci use the work-around */ 359413498266Sopenharmony_ci if(!ssl_config->enable_beast) 359513498266Sopenharmony_ci ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; 359613498266Sopenharmony_ci#endif 359713498266Sopenharmony_ci 359813498266Sopenharmony_ci switch(ssl_version) { 359913498266Sopenharmony_ci case CURL_SSLVERSION_SSLv2: 360013498266Sopenharmony_ci case CURL_SSLVERSION_SSLv3: 360113498266Sopenharmony_ci return CURLE_NOT_BUILT_IN; 360213498266Sopenharmony_ci 360313498266Sopenharmony_ci /* "--tlsv<x.y>" options mean TLS >= version <x.y> */ 360413498266Sopenharmony_ci case CURL_SSLVERSION_DEFAULT: 360513498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1: /* TLS >= version 1.0 */ 360613498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_0: /* TLS >= version 1.0 */ 360713498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_1: /* TLS >= version 1.1 */ 360813498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_2: /* TLS >= version 1.2 */ 360913498266Sopenharmony_ci case CURL_SSLVERSION_TLSv1_3: /* TLS >= version 1.3 */ 361013498266Sopenharmony_ci /* asking for any TLS version as the minimum, means no SSL versions 361113498266Sopenharmony_ci allowed */ 361213498266Sopenharmony_ci ctx_options |= SSL_OP_NO_SSLv2; 361313498266Sopenharmony_ci ctx_options |= SSL_OP_NO_SSLv3; 361413498266Sopenharmony_ci 361513498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) /* 1.1.0 */ 361613498266Sopenharmony_ci result = ossl_set_ssl_version_min_max(cf, backend->ctx); 361713498266Sopenharmony_ci#else 361813498266Sopenharmony_ci result = ossl_set_ssl_version_min_max_legacy(&ctx_options, cf, data); 361913498266Sopenharmony_ci#endif 362013498266Sopenharmony_ci if(result != CURLE_OK) 362113498266Sopenharmony_ci return result; 362213498266Sopenharmony_ci break; 362313498266Sopenharmony_ci 362413498266Sopenharmony_ci default: 362513498266Sopenharmony_ci failf(data, "Unrecognized parameter passed via CURLOPT_SSLVERSION"); 362613498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 362713498266Sopenharmony_ci } 362813498266Sopenharmony_ci 362913498266Sopenharmony_ci SSL_CTX_set_options(backend->ctx, ctx_options); 363013498266Sopenharmony_ci 363113498266Sopenharmony_ci#ifdef HAS_ALPN 363213498266Sopenharmony_ci if(connssl->alpn) { 363313498266Sopenharmony_ci struct alpn_proto_buf proto; 363413498266Sopenharmony_ci 363513498266Sopenharmony_ci result = Curl_alpn_to_proto_buf(&proto, connssl->alpn); 363613498266Sopenharmony_ci if(result || 363713498266Sopenharmony_ci SSL_CTX_set_alpn_protos(backend->ctx, proto.data, proto.len)) { 363813498266Sopenharmony_ci failf(data, "Error setting ALPN"); 363913498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 364013498266Sopenharmony_ci } 364113498266Sopenharmony_ci Curl_alpn_to_proto_str(&proto, connssl->alpn); 364213498266Sopenharmony_ci infof(data, VTLS_INFOF_ALPN_OFFER_1STR, proto.data); 364313498266Sopenharmony_ci } 364413498266Sopenharmony_ci#endif 364513498266Sopenharmony_ci 364613498266Sopenharmony_ci if(ssl_cert || ssl_cert_blob || ssl_cert_type) { 364713498266Sopenharmony_ci if(!result && 364813498266Sopenharmony_ci !cert_stuff(data, backend->ctx, 364913498266Sopenharmony_ci ssl_cert, ssl_cert_blob, ssl_cert_type, 365013498266Sopenharmony_ci ssl_config->key, ssl_config->key_blob, 365113498266Sopenharmony_ci ssl_config->key_type, ssl_config->key_passwd)) 365213498266Sopenharmony_ci result = CURLE_SSL_CERTPROBLEM; 365313498266Sopenharmony_ci if(result) 365413498266Sopenharmony_ci /* failf() is already done in cert_stuff() */ 365513498266Sopenharmony_ci return result; 365613498266Sopenharmony_ci } 365713498266Sopenharmony_ci 365813498266Sopenharmony_ci ciphers = conn_config->cipher_list; 365913498266Sopenharmony_ci if(!ciphers) 366013498266Sopenharmony_ci ciphers = (char *)DEFAULT_CIPHER_SELECTION; 366113498266Sopenharmony_ci if(ciphers) { 366213498266Sopenharmony_ci if(!SSL_CTX_set_cipher_list(backend->ctx, ciphers)) { 366313498266Sopenharmony_ci failf(data, "failed setting cipher list: %s", ciphers); 366413498266Sopenharmony_ci return CURLE_SSL_CIPHER; 366513498266Sopenharmony_ci } 366613498266Sopenharmony_ci infof(data, "Cipher selection: %s", ciphers); 366713498266Sopenharmony_ci } 366813498266Sopenharmony_ci 366913498266Sopenharmony_ci#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES 367013498266Sopenharmony_ci { 367113498266Sopenharmony_ci char *ciphers13 = conn_config->cipher_list13; 367213498266Sopenharmony_ci if(ciphers13) { 367313498266Sopenharmony_ci if(!SSL_CTX_set_ciphersuites(backend->ctx, ciphers13)) { 367413498266Sopenharmony_ci failf(data, "failed setting TLS 1.3 cipher suite: %s", ciphers13); 367513498266Sopenharmony_ci return CURLE_SSL_CIPHER; 367613498266Sopenharmony_ci } 367713498266Sopenharmony_ci infof(data, "TLS 1.3 cipher selection: %s", ciphers13); 367813498266Sopenharmony_ci } 367913498266Sopenharmony_ci } 368013498266Sopenharmony_ci#endif 368113498266Sopenharmony_ci 368213498266Sopenharmony_ci#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH 368313498266Sopenharmony_ci /* OpenSSL 1.1.1 requires clients to opt-in for PHA */ 368413498266Sopenharmony_ci SSL_CTX_set_post_handshake_auth(backend->ctx, 1); 368513498266Sopenharmony_ci#endif 368613498266Sopenharmony_ci 368713498266Sopenharmony_ci#ifdef HAVE_SSL_CTX_SET_EC_CURVES 368813498266Sopenharmony_ci { 368913498266Sopenharmony_ci char *curves = conn_config->curves; 369013498266Sopenharmony_ci if(curves) { 369113498266Sopenharmony_ci if(!SSL_CTX_set1_curves_list(backend->ctx, curves)) { 369213498266Sopenharmony_ci failf(data, "failed setting curves list: '%s'", curves); 369313498266Sopenharmony_ci return CURLE_SSL_CIPHER; 369413498266Sopenharmony_ci } 369513498266Sopenharmony_ci } 369613498266Sopenharmony_ci } 369713498266Sopenharmony_ci#endif 369813498266Sopenharmony_ci 369913498266Sopenharmony_ci#ifdef USE_OPENSSL_SRP 370013498266Sopenharmony_ci if(ssl_config->primary.username && Curl_auth_allowed_to_host(data)) { 370113498266Sopenharmony_ci char * const ssl_username = ssl_config->primary.username; 370213498266Sopenharmony_ci char * const ssl_password = ssl_config->primary.password; 370313498266Sopenharmony_ci infof(data, "Using TLS-SRP username: %s", ssl_username); 370413498266Sopenharmony_ci 370513498266Sopenharmony_ci if(!SSL_CTX_set_srp_username(backend->ctx, ssl_username)) { 370613498266Sopenharmony_ci failf(data, "Unable to set SRP user name"); 370713498266Sopenharmony_ci return CURLE_BAD_FUNCTION_ARGUMENT; 370813498266Sopenharmony_ci } 370913498266Sopenharmony_ci if(!SSL_CTX_set_srp_password(backend->ctx, ssl_password)) { 371013498266Sopenharmony_ci failf(data, "failed setting SRP password"); 371113498266Sopenharmony_ci return CURLE_BAD_FUNCTION_ARGUMENT; 371213498266Sopenharmony_ci } 371313498266Sopenharmony_ci if(!conn_config->cipher_list) { 371413498266Sopenharmony_ci infof(data, "Setting cipher list SRP"); 371513498266Sopenharmony_ci 371613498266Sopenharmony_ci if(!SSL_CTX_set_cipher_list(backend->ctx, "SRP")) { 371713498266Sopenharmony_ci failf(data, "failed setting SRP cipher list"); 371813498266Sopenharmony_ci return CURLE_SSL_CIPHER; 371913498266Sopenharmony_ci } 372013498266Sopenharmony_ci } 372113498266Sopenharmony_ci } 372213498266Sopenharmony_ci#endif 372313498266Sopenharmony_ci 372413498266Sopenharmony_ci /* OpenSSL always tries to verify the peer, this only says whether it should 372513498266Sopenharmony_ci * fail to connect if the verification fails, or if it should continue 372613498266Sopenharmony_ci * anyway. In the latter case the result of the verification is checked with 372713498266Sopenharmony_ci * SSL_get_verify_result() below. */ 372813498266Sopenharmony_ci SSL_CTX_set_verify(backend->ctx, 372913498266Sopenharmony_ci verifypeer ? SSL_VERIFY_PEER : SSL_VERIFY_NONE, NULL); 373013498266Sopenharmony_ci 373113498266Sopenharmony_ci /* Enable logging of secrets to the file specified in env SSLKEYLOGFILE. */ 373213498266Sopenharmony_ci#ifdef HAVE_KEYLOG_CALLBACK 373313498266Sopenharmony_ci if(Curl_tls_keylog_enabled()) { 373413498266Sopenharmony_ci SSL_CTX_set_keylog_callback(backend->ctx, ossl_keylog_callback); 373513498266Sopenharmony_ci } 373613498266Sopenharmony_ci#endif 373713498266Sopenharmony_ci 373813498266Sopenharmony_ci /* Enable the session cache because it's a prerequisite for the "new session" 373913498266Sopenharmony_ci * callback. Use the "external storage" mode to prevent OpenSSL from creating 374013498266Sopenharmony_ci * an internal session cache. 374113498266Sopenharmony_ci */ 374213498266Sopenharmony_ci SSL_CTX_set_session_cache_mode(backend->ctx, 374313498266Sopenharmony_ci SSL_SESS_CACHE_CLIENT | 374413498266Sopenharmony_ci SSL_SESS_CACHE_NO_INTERNAL); 374513498266Sopenharmony_ci SSL_CTX_sess_set_new_cb(backend->ctx, ossl_new_session_cb); 374613498266Sopenharmony_ci 374713498266Sopenharmony_ci /* give application a chance to interfere with SSL set up. */ 374813498266Sopenharmony_ci if(data->set.ssl.fsslctx) { 374913498266Sopenharmony_ci /* When a user callback is installed to modify the SSL_CTX, 375013498266Sopenharmony_ci * we need to do the full initialization before calling it. 375113498266Sopenharmony_ci * See: #11800 */ 375213498266Sopenharmony_ci if(!backend->x509_store_setup) { 375313498266Sopenharmony_ci result = Curl_ssl_setup_x509_store(cf, data, backend->ctx); 375413498266Sopenharmony_ci if(result) 375513498266Sopenharmony_ci return result; 375613498266Sopenharmony_ci backend->x509_store_setup = TRUE; 375713498266Sopenharmony_ci } 375813498266Sopenharmony_ci Curl_set_in_callback(data, true); 375913498266Sopenharmony_ci result = (*data->set.ssl.fsslctx)(data, backend->ctx, 376013498266Sopenharmony_ci data->set.ssl.fsslctxp); 376113498266Sopenharmony_ci Curl_set_in_callback(data, false); 376213498266Sopenharmony_ci if(result) { 376313498266Sopenharmony_ci failf(data, "error signaled by ssl ctx callback"); 376413498266Sopenharmony_ci return result; 376513498266Sopenharmony_ci } 376613498266Sopenharmony_ci } 376713498266Sopenharmony_ci 376813498266Sopenharmony_ci /* Let's make an SSL structure */ 376913498266Sopenharmony_ci if(backend->handle) 377013498266Sopenharmony_ci SSL_free(backend->handle); 377113498266Sopenharmony_ci backend->handle = SSL_new(backend->ctx); 377213498266Sopenharmony_ci if(!backend->handle) { 377313498266Sopenharmony_ci failf(data, "SSL: couldn't create a context (handle)"); 377413498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 377513498266Sopenharmony_ci } 377613498266Sopenharmony_ci 377713498266Sopenharmony_ci SSL_set_app_data(backend->handle, cf); 377813498266Sopenharmony_ci 377913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ 378013498266Sopenharmony_ci !defined(OPENSSL_NO_OCSP) 378113498266Sopenharmony_ci if(conn_config->verifystatus) 378213498266Sopenharmony_ci SSL_set_tlsext_status_type(backend->handle, TLSEXT_STATUSTYPE_ocsp); 378313498266Sopenharmony_ci#endif 378413498266Sopenharmony_ci 378513498266Sopenharmony_ci#if (defined(OPENSSL_IS_BORINGSSL) || defined(OPENSSL_IS_AWSLC)) && \ 378613498266Sopenharmony_ci defined(ALLOW_RENEG) 378713498266Sopenharmony_ci SSL_set_renegotiate_mode(backend->handle, ssl_renegotiate_freely); 378813498266Sopenharmony_ci#endif 378913498266Sopenharmony_ci 379013498266Sopenharmony_ci SSL_set_connect_state(backend->handle); 379113498266Sopenharmony_ci 379213498266Sopenharmony_ci backend->server_cert = 0x0; 379313498266Sopenharmony_ci#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME 379413498266Sopenharmony_ci if(connssl->peer.sni) { 379513498266Sopenharmony_ci if(!SSL_set_tlsext_host_name(backend->handle, connssl->peer.sni)) { 379613498266Sopenharmony_ci failf(data, "Failed set SNI"); 379713498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 379813498266Sopenharmony_ci } 379913498266Sopenharmony_ci } 380013498266Sopenharmony_ci#endif 380113498266Sopenharmony_ci 380213498266Sopenharmony_ci SSL_set_app_data(backend->handle, cf); 380313498266Sopenharmony_ci 380413498266Sopenharmony_ci connssl->reused_session = FALSE; 380513498266Sopenharmony_ci if(ssl_config->primary.sessionid) { 380613498266Sopenharmony_ci Curl_ssl_sessionid_lock(data); 380713498266Sopenharmony_ci if(!Curl_ssl_getsessionid(cf, data, &ssl_sessionid, NULL)) { 380813498266Sopenharmony_ci /* we got a session id, use it! */ 380913498266Sopenharmony_ci if(!SSL_set_session(backend->handle, ssl_sessionid)) { 381013498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 381113498266Sopenharmony_ci failf(data, "SSL: SSL_set_session failed: %s", 381213498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 381313498266Sopenharmony_ci sizeof(error_buffer))); 381413498266Sopenharmony_ci return CURLE_SSL_CONNECT_ERROR; 381513498266Sopenharmony_ci } 381613498266Sopenharmony_ci /* Informational message */ 381713498266Sopenharmony_ci infof(data, "SSL reusing session ID"); 381813498266Sopenharmony_ci connssl->reused_session = TRUE; 381913498266Sopenharmony_ci } 382013498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 382113498266Sopenharmony_ci } 382213498266Sopenharmony_ci 382313498266Sopenharmony_ci backend->bio_method = ossl_bio_cf_method_create(); 382413498266Sopenharmony_ci if(!backend->bio_method) 382513498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 382613498266Sopenharmony_ci bio = BIO_new(backend->bio_method); 382713498266Sopenharmony_ci if(!bio) 382813498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 382913498266Sopenharmony_ci 383013498266Sopenharmony_ci BIO_set_data(bio, cf); 383113498266Sopenharmony_ci#ifdef HAVE_SSL_SET0_WBIO 383213498266Sopenharmony_ci /* with OpenSSL v1.1.1 we get an alternative to SSL_set_bio() that works 383313498266Sopenharmony_ci * without backward compat quirks. Every call takes one reference, so we 383413498266Sopenharmony_ci * up it and pass. SSL* then owns it and will free. 383513498266Sopenharmony_ci * We check on the function in configure, since libressl and friends 383613498266Sopenharmony_ci * each have their own versions to add support for this. */ 383713498266Sopenharmony_ci BIO_up_ref(bio); 383813498266Sopenharmony_ci SSL_set0_rbio(backend->handle, bio); 383913498266Sopenharmony_ci SSL_set0_wbio(backend->handle, bio); 384013498266Sopenharmony_ci#else 384113498266Sopenharmony_ci SSL_set_bio(backend->handle, bio, bio); 384213498266Sopenharmony_ci#endif 384313498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2; 384413498266Sopenharmony_ci 384513498266Sopenharmony_ci return CURLE_OK; 384613498266Sopenharmony_ci} 384713498266Sopenharmony_ci 384813498266Sopenharmony_cistatic CURLcode ossl_connect_step2(struct Curl_cfilter *cf, 384913498266Sopenharmony_ci struct Curl_easy *data) 385013498266Sopenharmony_ci{ 385113498266Sopenharmony_ci int err; 385213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 385313498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 385413498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 385513498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 385613498266Sopenharmony_ci DEBUGASSERT(ssl_connect_2 == connssl->connecting_state 385713498266Sopenharmony_ci || ssl_connect_2_reading == connssl->connecting_state 385813498266Sopenharmony_ci || ssl_connect_2_writing == connssl->connecting_state); 385913498266Sopenharmony_ci DEBUGASSERT(backend); 386013498266Sopenharmony_ci 386113498266Sopenharmony_ci ERR_clear_error(); 386213498266Sopenharmony_ci 386313498266Sopenharmony_ci err = SSL_connect(backend->handle); 386413498266Sopenharmony_ci 386513498266Sopenharmony_ci if(!backend->x509_store_setup) { 386613498266Sopenharmony_ci /* After having send off the ClientHello, we prepare the x509 386713498266Sopenharmony_ci * store to verify the coming certificate from the server */ 386813498266Sopenharmony_ci CURLcode result = Curl_ssl_setup_x509_store(cf, data, backend->ctx); 386913498266Sopenharmony_ci if(result) 387013498266Sopenharmony_ci return result; 387113498266Sopenharmony_ci backend->x509_store_setup = TRUE; 387213498266Sopenharmony_ci } 387313498266Sopenharmony_ci 387413498266Sopenharmony_ci#ifndef HAVE_KEYLOG_CALLBACK 387513498266Sopenharmony_ci if(Curl_tls_keylog_enabled()) { 387613498266Sopenharmony_ci /* If key logging is enabled, wait for the handshake to complete and then 387713498266Sopenharmony_ci * proceed with logging secrets (for TLS 1.2 or older). 387813498266Sopenharmony_ci */ 387913498266Sopenharmony_ci ossl_log_tls12_secret(backend->handle, &backend->keylog_done); 388013498266Sopenharmony_ci } 388113498266Sopenharmony_ci#endif 388213498266Sopenharmony_ci 388313498266Sopenharmony_ci /* 1 is fine 388413498266Sopenharmony_ci 0 is "not successful but was shut down controlled" 388513498266Sopenharmony_ci <0 is "handshake was not successful, because a fatal error occurred" */ 388613498266Sopenharmony_ci if(1 != err) { 388713498266Sopenharmony_ci int detail = SSL_get_error(backend->handle, err); 388813498266Sopenharmony_ci 388913498266Sopenharmony_ci if(SSL_ERROR_WANT_READ == detail) { 389013498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2_reading; 389113498266Sopenharmony_ci return CURLE_OK; 389213498266Sopenharmony_ci } 389313498266Sopenharmony_ci if(SSL_ERROR_WANT_WRITE == detail) { 389413498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2_writing; 389513498266Sopenharmony_ci return CURLE_OK; 389613498266Sopenharmony_ci } 389713498266Sopenharmony_ci#ifdef SSL_ERROR_WANT_ASYNC 389813498266Sopenharmony_ci if(SSL_ERROR_WANT_ASYNC == detail) { 389913498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2; 390013498266Sopenharmony_ci return CURLE_OK; 390113498266Sopenharmony_ci } 390213498266Sopenharmony_ci#endif 390313498266Sopenharmony_ci#ifdef SSL_ERROR_WANT_RETRY_VERIFY 390413498266Sopenharmony_ci if(SSL_ERROR_WANT_RETRY_VERIFY == detail) { 390513498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2; 390613498266Sopenharmony_ci return CURLE_OK; 390713498266Sopenharmony_ci } 390813498266Sopenharmony_ci#endif 390913498266Sopenharmony_ci if(backend->io_result == CURLE_AGAIN) { 391013498266Sopenharmony_ci return CURLE_OK; 391113498266Sopenharmony_ci } 391213498266Sopenharmony_ci else { 391313498266Sopenharmony_ci /* untreated error */ 391413498266Sopenharmony_ci sslerr_t errdetail; 391513498266Sopenharmony_ci char error_buffer[256]=""; 391613498266Sopenharmony_ci CURLcode result; 391713498266Sopenharmony_ci long lerr; 391813498266Sopenharmony_ci int lib; 391913498266Sopenharmony_ci int reason; 392013498266Sopenharmony_ci 392113498266Sopenharmony_ci /* the connection failed, we're not waiting for anything else. */ 392213498266Sopenharmony_ci connssl->connecting_state = ssl_connect_2; 392313498266Sopenharmony_ci 392413498266Sopenharmony_ci /* Get the earliest error code from the thread's error queue and remove 392513498266Sopenharmony_ci the entry. */ 392613498266Sopenharmony_ci errdetail = ERR_get_error(); 392713498266Sopenharmony_ci 392813498266Sopenharmony_ci /* Extract which lib and reason */ 392913498266Sopenharmony_ci lib = ERR_GET_LIB(errdetail); 393013498266Sopenharmony_ci reason = ERR_GET_REASON(errdetail); 393113498266Sopenharmony_ci 393213498266Sopenharmony_ci if((lib == ERR_LIB_SSL) && 393313498266Sopenharmony_ci ((reason == SSL_R_CERTIFICATE_VERIFY_FAILED) || 393413498266Sopenharmony_ci (reason == SSL_R_SSLV3_ALERT_CERTIFICATE_EXPIRED))) { 393513498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 393613498266Sopenharmony_ci 393713498266Sopenharmony_ci lerr = SSL_get_verify_result(backend->handle); 393813498266Sopenharmony_ci if(lerr != X509_V_OK) { 393913498266Sopenharmony_ci ssl_config->certverifyresult = lerr; 394013498266Sopenharmony_ci msnprintf(error_buffer, sizeof(error_buffer), 394113498266Sopenharmony_ci "SSL certificate problem: %s", 394213498266Sopenharmony_ci X509_verify_cert_error_string(lerr)); 394313498266Sopenharmony_ci } 394413498266Sopenharmony_ci else 394513498266Sopenharmony_ci /* strcpy() is fine here as long as the string fits within 394613498266Sopenharmony_ci error_buffer */ 394713498266Sopenharmony_ci strcpy(error_buffer, "SSL certificate verification failed"); 394813498266Sopenharmony_ci } 394913498266Sopenharmony_ci#if defined(SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED) 395013498266Sopenharmony_ci /* SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED is only available on 395113498266Sopenharmony_ci OpenSSL version above v1.1.1, not LibreSSL, BoringSSL, or AWS-LC */ 395213498266Sopenharmony_ci else if((lib == ERR_LIB_SSL) && 395313498266Sopenharmony_ci (reason == SSL_R_TLSV13_ALERT_CERTIFICATE_REQUIRED)) { 395413498266Sopenharmony_ci /* If client certificate is required, communicate the 395513498266Sopenharmony_ci error to client */ 395613498266Sopenharmony_ci result = CURLE_SSL_CLIENTCERT; 395713498266Sopenharmony_ci ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); 395813498266Sopenharmony_ci } 395913498266Sopenharmony_ci#endif 396013498266Sopenharmony_ci else { 396113498266Sopenharmony_ci result = CURLE_SSL_CONNECT_ERROR; 396213498266Sopenharmony_ci ossl_strerror(errdetail, error_buffer, sizeof(error_buffer)); 396313498266Sopenharmony_ci } 396413498266Sopenharmony_ci 396513498266Sopenharmony_ci /* detail is already set to the SSL error above */ 396613498266Sopenharmony_ci 396713498266Sopenharmony_ci /* If we e.g. use SSLv2 request-method and the server doesn't like us 396813498266Sopenharmony_ci * (RST connection, etc.), OpenSSL gives no explanation whatsoever and 396913498266Sopenharmony_ci * the SO_ERROR is also lost. 397013498266Sopenharmony_ci */ 397113498266Sopenharmony_ci if(CURLE_SSL_CONNECT_ERROR == result && errdetail == 0) { 397213498266Sopenharmony_ci char extramsg[80]=""; 397313498266Sopenharmony_ci int sockerr = SOCKERRNO; 397413498266Sopenharmony_ci 397513498266Sopenharmony_ci if(sockerr && detail == SSL_ERROR_SYSCALL) 397613498266Sopenharmony_ci Curl_strerror(sockerr, extramsg, sizeof(extramsg)); 397713498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_connect: %s in connection to %s:%d ", 397813498266Sopenharmony_ci extramsg[0] ? extramsg : SSL_ERROR_to_str(detail), 397913498266Sopenharmony_ci connssl->peer.hostname, connssl->port); 398013498266Sopenharmony_ci return result; 398113498266Sopenharmony_ci } 398213498266Sopenharmony_ci 398313498266Sopenharmony_ci /* Could be a CERT problem */ 398413498266Sopenharmony_ci failf(data, "%s", error_buffer); 398513498266Sopenharmony_ci 398613498266Sopenharmony_ci return result; 398713498266Sopenharmony_ci } 398813498266Sopenharmony_ci } 398913498266Sopenharmony_ci else { 399013498266Sopenharmony_ci int psigtype_nid = NID_undef; 399113498266Sopenharmony_ci const char *negotiated_group_name = NULL; 399213498266Sopenharmony_ci 399313498266Sopenharmony_ci /* we connected fine, we're not waiting for anything else. */ 399413498266Sopenharmony_ci connssl->connecting_state = ssl_connect_3; 399513498266Sopenharmony_ci 399613498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) 399713498266Sopenharmony_ci SSL_get_peer_signature_type_nid(backend->handle, &psigtype_nid); 399813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x30200000L) 399913498266Sopenharmony_ci negotiated_group_name = SSL_get0_group_name(backend->handle); 400013498266Sopenharmony_ci#else 400113498266Sopenharmony_ci negotiated_group_name = 400213498266Sopenharmony_ci OBJ_nid2sn(SSL_get_negotiated_group(backend->handle) & 0x0000FFFF); 400313498266Sopenharmony_ci#endif 400413498266Sopenharmony_ci#endif 400513498266Sopenharmony_ci 400613498266Sopenharmony_ci /* Informational message */ 400713498266Sopenharmony_ci infof(data, "SSL connection using %s / %s / %s / %s", 400813498266Sopenharmony_ci SSL_get_version(backend->handle), 400913498266Sopenharmony_ci SSL_get_cipher(backend->handle), 401013498266Sopenharmony_ci negotiated_group_name? negotiated_group_name : "[blank]", 401113498266Sopenharmony_ci OBJ_nid2sn(psigtype_nid)); 401213498266Sopenharmony_ci 401313498266Sopenharmony_ci#ifdef HAS_ALPN 401413498266Sopenharmony_ci /* Sets data and len to negotiated protocol, len is 0 if no protocol was 401513498266Sopenharmony_ci * negotiated 401613498266Sopenharmony_ci */ 401713498266Sopenharmony_ci if(connssl->alpn) { 401813498266Sopenharmony_ci const unsigned char *neg_protocol; 401913498266Sopenharmony_ci unsigned int len; 402013498266Sopenharmony_ci SSL_get0_alpn_selected(backend->handle, &neg_protocol, &len); 402113498266Sopenharmony_ci 402213498266Sopenharmony_ci return Curl_alpn_set_negotiated(cf, data, neg_protocol, len); 402313498266Sopenharmony_ci } 402413498266Sopenharmony_ci#endif 402513498266Sopenharmony_ci 402613498266Sopenharmony_ci return CURLE_OK; 402713498266Sopenharmony_ci } 402813498266Sopenharmony_ci} 402913498266Sopenharmony_ci 403013498266Sopenharmony_ci/* 403113498266Sopenharmony_ci * Heavily modified from: 403213498266Sopenharmony_ci * https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning#OpenSSL 403313498266Sopenharmony_ci */ 403413498266Sopenharmony_cistatic CURLcode ossl_pkp_pin_peer_pubkey(struct Curl_easy *data, X509* cert, 403513498266Sopenharmony_ci const char *pinnedpubkey) 403613498266Sopenharmony_ci{ 403713498266Sopenharmony_ci /* Scratch */ 403813498266Sopenharmony_ci int len1 = 0, len2 = 0; 403913498266Sopenharmony_ci unsigned char *buff1 = NULL, *temp = NULL; 404013498266Sopenharmony_ci 404113498266Sopenharmony_ci /* Result is returned to caller */ 404213498266Sopenharmony_ci CURLcode result = CURLE_SSL_PINNEDPUBKEYNOTMATCH; 404313498266Sopenharmony_ci 404413498266Sopenharmony_ci /* if a path wasn't specified, don't pin */ 404513498266Sopenharmony_ci if(!pinnedpubkey) 404613498266Sopenharmony_ci return CURLE_OK; 404713498266Sopenharmony_ci 404813498266Sopenharmony_ci if(!cert) 404913498266Sopenharmony_ci return result; 405013498266Sopenharmony_ci 405113498266Sopenharmony_ci do { 405213498266Sopenharmony_ci /* Begin Gyrations to get the subjectPublicKeyInfo */ 405313498266Sopenharmony_ci /* Thanks to Viktor Dukhovni on the OpenSSL mailing list */ 405413498266Sopenharmony_ci 405513498266Sopenharmony_ci /* https://groups.google.com/group/mailing.openssl.users/browse_thread 405613498266Sopenharmony_ci /thread/d61858dae102c6c7 */ 405713498266Sopenharmony_ci len1 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), NULL); 405813498266Sopenharmony_ci if(len1 < 1) 405913498266Sopenharmony_ci break; /* failed */ 406013498266Sopenharmony_ci 406113498266Sopenharmony_ci buff1 = temp = malloc(len1); 406213498266Sopenharmony_ci if(!buff1) 406313498266Sopenharmony_ci break; /* failed */ 406413498266Sopenharmony_ci 406513498266Sopenharmony_ci /* https://www.openssl.org/docs/crypto/d2i_X509.html */ 406613498266Sopenharmony_ci len2 = i2d_X509_PUBKEY(X509_get_X509_PUBKEY(cert), &temp); 406713498266Sopenharmony_ci 406813498266Sopenharmony_ci /* 406913498266Sopenharmony_ci * These checks are verifying we got back the same values as when we 407013498266Sopenharmony_ci * sized the buffer. It's pretty weak since they should always be the 407113498266Sopenharmony_ci * same. But it gives us something to test. 407213498266Sopenharmony_ci */ 407313498266Sopenharmony_ci if((len1 != len2) || !temp || ((temp - buff1) != len1)) 407413498266Sopenharmony_ci break; /* failed */ 407513498266Sopenharmony_ci 407613498266Sopenharmony_ci /* End Gyrations */ 407713498266Sopenharmony_ci 407813498266Sopenharmony_ci /* The one good exit point */ 407913498266Sopenharmony_ci result = Curl_pin_peer_pubkey(data, pinnedpubkey, buff1, len1); 408013498266Sopenharmony_ci } while(0); 408113498266Sopenharmony_ci 408213498266Sopenharmony_ci if(buff1) 408313498266Sopenharmony_ci free(buff1); 408413498266Sopenharmony_ci 408513498266Sopenharmony_ci return result; 408613498266Sopenharmony_ci} 408713498266Sopenharmony_ci 408813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && \ 408913498266Sopenharmony_ci !(defined(LIBRESSL_VERSION_NUMBER) && \ 409013498266Sopenharmony_ci LIBRESSL_VERSION_NUMBER < 0x3060000fL) && \ 409113498266Sopenharmony_ci !defined(OPENSSL_IS_BORINGSSL) && \ 409213498266Sopenharmony_ci !defined(OPENSSL_IS_AWSLC) && \ 409313498266Sopenharmony_ci !defined(CURL_DISABLE_VERBOSE_STRINGS) 409413498266Sopenharmony_cistatic void infof_certstack(struct Curl_easy *data, const SSL *ssl) 409513498266Sopenharmony_ci{ 409613498266Sopenharmony_ci STACK_OF(X509) *certstack; 409713498266Sopenharmony_ci long verify_result; 409813498266Sopenharmony_ci int num_cert_levels; 409913498266Sopenharmony_ci int cert_level; 410013498266Sopenharmony_ci 410113498266Sopenharmony_ci verify_result = SSL_get_verify_result(ssl); 410213498266Sopenharmony_ci if(verify_result != X509_V_OK) 410313498266Sopenharmony_ci certstack = SSL_get_peer_cert_chain(ssl); 410413498266Sopenharmony_ci else 410513498266Sopenharmony_ci certstack = SSL_get0_verified_chain(ssl); 410613498266Sopenharmony_ci num_cert_levels = sk_X509_num(certstack); 410713498266Sopenharmony_ci 410813498266Sopenharmony_ci for(cert_level = 0; cert_level < num_cert_levels; cert_level++) { 410913498266Sopenharmony_ci char cert_algorithm[80] = ""; 411013498266Sopenharmony_ci char group_name_final[80] = ""; 411113498266Sopenharmony_ci const X509_ALGOR *palg_cert = NULL; 411213498266Sopenharmony_ci const ASN1_OBJECT *paobj_cert = NULL; 411313498266Sopenharmony_ci X509 *current_cert; 411413498266Sopenharmony_ci EVP_PKEY *current_pkey; 411513498266Sopenharmony_ci int key_bits; 411613498266Sopenharmony_ci int key_sec_bits; 411713498266Sopenharmony_ci int get_group_name; 411813498266Sopenharmony_ci const char *type_name; 411913498266Sopenharmony_ci 412013498266Sopenharmony_ci current_cert = sk_X509_value(certstack, cert_level); 412113498266Sopenharmony_ci 412213498266Sopenharmony_ci X509_get0_signature(NULL, &palg_cert, current_cert); 412313498266Sopenharmony_ci X509_ALGOR_get0(&paobj_cert, NULL, NULL, palg_cert); 412413498266Sopenharmony_ci OBJ_obj2txt(cert_algorithm, sizeof(cert_algorithm), paobj_cert, 0); 412513498266Sopenharmony_ci 412613498266Sopenharmony_ci current_pkey = X509_get0_pubkey(current_cert); 412713498266Sopenharmony_ci key_bits = EVP_PKEY_bits(current_pkey); 412813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER < 0x30000000L) 412913498266Sopenharmony_ci#define EVP_PKEY_get_security_bits EVP_PKEY_security_bits 413013498266Sopenharmony_ci#endif 413113498266Sopenharmony_ci key_sec_bits = EVP_PKEY_get_security_bits(current_pkey); 413213498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x30000000L) 413313498266Sopenharmony_ci { 413413498266Sopenharmony_ci char group_name[80] = ""; 413513498266Sopenharmony_ci get_group_name = EVP_PKEY_get_group_name(current_pkey, group_name, 413613498266Sopenharmony_ci sizeof(group_name), NULL); 413713498266Sopenharmony_ci msnprintf(group_name_final, sizeof(group_name_final), "/%s", group_name); 413813498266Sopenharmony_ci } 413913498266Sopenharmony_ci type_name = EVP_PKEY_get0_type_name(current_pkey); 414013498266Sopenharmony_ci#else 414113498266Sopenharmony_ci get_group_name = 0; 414213498266Sopenharmony_ci type_name = NULL; 414313498266Sopenharmony_ci#endif 414413498266Sopenharmony_ci 414513498266Sopenharmony_ci infof(data, 414613498266Sopenharmony_ci " Certificate level %d: " 414713498266Sopenharmony_ci "Public key type %s%s (%d/%d Bits/secBits), signed using %s", 414813498266Sopenharmony_ci cert_level, type_name ? type_name : "?", 414913498266Sopenharmony_ci get_group_name == 0 ? "" : group_name_final, 415013498266Sopenharmony_ci key_bits, key_sec_bits, cert_algorithm); 415113498266Sopenharmony_ci } 415213498266Sopenharmony_ci} 415313498266Sopenharmony_ci#else 415413498266Sopenharmony_ci#define infof_certstack(data, ssl) 415513498266Sopenharmony_ci#endif 415613498266Sopenharmony_ci 415713498266Sopenharmony_ci/* 415813498266Sopenharmony_ci * Get the server cert, verify it and show it, etc., only call failf() if the 415913498266Sopenharmony_ci * 'strict' argument is TRUE as otherwise all this is for informational 416013498266Sopenharmony_ci * purposes only! 416113498266Sopenharmony_ci * 416213498266Sopenharmony_ci * We check certificates to authenticate the server; otherwise we risk 416313498266Sopenharmony_ci * man-in-the-middle attack. 416413498266Sopenharmony_ci */ 416513498266Sopenharmony_cistatic CURLcode servercert(struct Curl_cfilter *cf, 416613498266Sopenharmony_ci struct Curl_easy *data, 416713498266Sopenharmony_ci bool strict) 416813498266Sopenharmony_ci{ 416913498266Sopenharmony_ci struct connectdata *conn = cf->conn; 417013498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 417113498266Sopenharmony_ci struct ssl_config_data *ssl_config = Curl_ssl_cf_get_config(cf, data); 417213498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 417313498266Sopenharmony_ci CURLcode result = CURLE_OK; 417413498266Sopenharmony_ci int rc; 417513498266Sopenharmony_ci long lerr; 417613498266Sopenharmony_ci X509 *issuer; 417713498266Sopenharmony_ci BIO *fp = NULL; 417813498266Sopenharmony_ci char error_buffer[256]=""; 417913498266Sopenharmony_ci char buffer[2048]; 418013498266Sopenharmony_ci const char *ptr; 418113498266Sopenharmony_ci BIO *mem = BIO_new(BIO_s_mem()); 418213498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 418313498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 418413498266Sopenharmony_ci 418513498266Sopenharmony_ci DEBUGASSERT(backend); 418613498266Sopenharmony_ci 418713498266Sopenharmony_ci if(!mem) { 418813498266Sopenharmony_ci failf(data, 418913498266Sopenharmony_ci "BIO_new return NULL, " OSSL_PACKAGE 419013498266Sopenharmony_ci " error %s", 419113498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 419213498266Sopenharmony_ci sizeof(error_buffer)) ); 419313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 419413498266Sopenharmony_ci } 419513498266Sopenharmony_ci 419613498266Sopenharmony_ci if(data->set.ssl.certinfo) 419713498266Sopenharmony_ci /* asked to gather certificate info */ 419813498266Sopenharmony_ci (void)Curl_ossl_certchain(data, backend->handle); 419913498266Sopenharmony_ci 420013498266Sopenharmony_ci backend->server_cert = SSL_get1_peer_certificate(backend->handle); 420113498266Sopenharmony_ci if(!backend->server_cert) { 420213498266Sopenharmony_ci BIO_free(mem); 420313498266Sopenharmony_ci if(!strict) 420413498266Sopenharmony_ci return CURLE_OK; 420513498266Sopenharmony_ci 420613498266Sopenharmony_ci failf(data, "SSL: couldn't get peer certificate"); 420713498266Sopenharmony_ci return CURLE_PEER_FAILED_VERIFICATION; 420813498266Sopenharmony_ci } 420913498266Sopenharmony_ci 421013498266Sopenharmony_ci infof(data, "%s certificate:", 421113498266Sopenharmony_ci Curl_ssl_cf_is_proxy(cf)? "Proxy" : "Server"); 421213498266Sopenharmony_ci 421313498266Sopenharmony_ci rc = x509_name_oneline(X509_get_subject_name(backend->server_cert), 421413498266Sopenharmony_ci buffer, sizeof(buffer)); 421513498266Sopenharmony_ci infof(data, " subject: %s", rc?"[NONE]":buffer); 421613498266Sopenharmony_ci 421713498266Sopenharmony_ci#ifndef CURL_DISABLE_VERBOSE_STRINGS 421813498266Sopenharmony_ci { 421913498266Sopenharmony_ci long len; 422013498266Sopenharmony_ci ASN1_TIME_print(mem, X509_get0_notBefore(backend->server_cert)); 422113498266Sopenharmony_ci len = BIO_get_mem_data(mem, (char **) &ptr); 422213498266Sopenharmony_ci infof(data, " start date: %.*s", (int)len, ptr); 422313498266Sopenharmony_ci (void)BIO_reset(mem); 422413498266Sopenharmony_ci 422513498266Sopenharmony_ci ASN1_TIME_print(mem, X509_get0_notAfter(backend->server_cert)); 422613498266Sopenharmony_ci len = BIO_get_mem_data(mem, (char **) &ptr); 422713498266Sopenharmony_ci infof(data, " expire date: %.*s", (int)len, ptr); 422813498266Sopenharmony_ci (void)BIO_reset(mem); 422913498266Sopenharmony_ci } 423013498266Sopenharmony_ci#endif 423113498266Sopenharmony_ci 423213498266Sopenharmony_ci BIO_free(mem); 423313498266Sopenharmony_ci 423413498266Sopenharmony_ci if(conn_config->verifyhost) { 423513498266Sopenharmony_ci result = Curl_ossl_verifyhost(data, conn, &connssl->peer, 423613498266Sopenharmony_ci backend->server_cert); 423713498266Sopenharmony_ci if(result) { 423813498266Sopenharmony_ci X509_free(backend->server_cert); 423913498266Sopenharmony_ci backend->server_cert = NULL; 424013498266Sopenharmony_ci return result; 424113498266Sopenharmony_ci } 424213498266Sopenharmony_ci } 424313498266Sopenharmony_ci 424413498266Sopenharmony_ci rc = x509_name_oneline(X509_get_issuer_name(backend->server_cert), 424513498266Sopenharmony_ci buffer, sizeof(buffer)); 424613498266Sopenharmony_ci if(rc) { 424713498266Sopenharmony_ci if(strict) 424813498266Sopenharmony_ci failf(data, "SSL: couldn't get X509-issuer name"); 424913498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 425013498266Sopenharmony_ci } 425113498266Sopenharmony_ci else { 425213498266Sopenharmony_ci infof(data, " issuer: %s", buffer); 425313498266Sopenharmony_ci 425413498266Sopenharmony_ci /* We could do all sorts of certificate verification stuff here before 425513498266Sopenharmony_ci deallocating the certificate. */ 425613498266Sopenharmony_ci 425713498266Sopenharmony_ci /* e.g. match issuer name with provided issuer certificate */ 425813498266Sopenharmony_ci if(conn_config->issuercert || conn_config->issuercert_blob) { 425913498266Sopenharmony_ci if(conn_config->issuercert_blob) { 426013498266Sopenharmony_ci fp = BIO_new_mem_buf(conn_config->issuercert_blob->data, 426113498266Sopenharmony_ci (int)conn_config->issuercert_blob->len); 426213498266Sopenharmony_ci if(!fp) { 426313498266Sopenharmony_ci failf(data, 426413498266Sopenharmony_ci "BIO_new_mem_buf NULL, " OSSL_PACKAGE 426513498266Sopenharmony_ci " error %s", 426613498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 426713498266Sopenharmony_ci sizeof(error_buffer)) ); 426813498266Sopenharmony_ci X509_free(backend->server_cert); 426913498266Sopenharmony_ci backend->server_cert = NULL; 427013498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 427113498266Sopenharmony_ci } 427213498266Sopenharmony_ci } 427313498266Sopenharmony_ci else { 427413498266Sopenharmony_ci fp = BIO_new(BIO_s_file()); 427513498266Sopenharmony_ci if(!fp) { 427613498266Sopenharmony_ci failf(data, 427713498266Sopenharmony_ci "BIO_new return NULL, " OSSL_PACKAGE 427813498266Sopenharmony_ci " error %s", 427913498266Sopenharmony_ci ossl_strerror(ERR_get_error(), error_buffer, 428013498266Sopenharmony_ci sizeof(error_buffer)) ); 428113498266Sopenharmony_ci X509_free(backend->server_cert); 428213498266Sopenharmony_ci backend->server_cert = NULL; 428313498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 428413498266Sopenharmony_ci } 428513498266Sopenharmony_ci 428613498266Sopenharmony_ci if(BIO_read_filename(fp, conn_config->issuercert) <= 0) { 428713498266Sopenharmony_ci if(strict) 428813498266Sopenharmony_ci failf(data, "SSL: Unable to open issuer cert (%s)", 428913498266Sopenharmony_ci conn_config->issuercert); 429013498266Sopenharmony_ci BIO_free(fp); 429113498266Sopenharmony_ci X509_free(backend->server_cert); 429213498266Sopenharmony_ci backend->server_cert = NULL; 429313498266Sopenharmony_ci return CURLE_SSL_ISSUER_ERROR; 429413498266Sopenharmony_ci } 429513498266Sopenharmony_ci } 429613498266Sopenharmony_ci 429713498266Sopenharmony_ci issuer = PEM_read_bio_X509(fp, NULL, ZERO_NULL, NULL); 429813498266Sopenharmony_ci if(!issuer) { 429913498266Sopenharmony_ci if(strict) 430013498266Sopenharmony_ci failf(data, "SSL: Unable to read issuer cert (%s)", 430113498266Sopenharmony_ci conn_config->issuercert); 430213498266Sopenharmony_ci BIO_free(fp); 430313498266Sopenharmony_ci X509_free(issuer); 430413498266Sopenharmony_ci X509_free(backend->server_cert); 430513498266Sopenharmony_ci backend->server_cert = NULL; 430613498266Sopenharmony_ci return CURLE_SSL_ISSUER_ERROR; 430713498266Sopenharmony_ci } 430813498266Sopenharmony_ci 430913498266Sopenharmony_ci if(X509_check_issued(issuer, backend->server_cert) != X509_V_OK) { 431013498266Sopenharmony_ci if(strict) 431113498266Sopenharmony_ci failf(data, "SSL: Certificate issuer check failed (%s)", 431213498266Sopenharmony_ci conn_config->issuercert); 431313498266Sopenharmony_ci BIO_free(fp); 431413498266Sopenharmony_ci X509_free(issuer); 431513498266Sopenharmony_ci X509_free(backend->server_cert); 431613498266Sopenharmony_ci backend->server_cert = NULL; 431713498266Sopenharmony_ci return CURLE_SSL_ISSUER_ERROR; 431813498266Sopenharmony_ci } 431913498266Sopenharmony_ci 432013498266Sopenharmony_ci infof(data, " SSL certificate issuer check ok (%s)", 432113498266Sopenharmony_ci conn_config->issuercert); 432213498266Sopenharmony_ci BIO_free(fp); 432313498266Sopenharmony_ci X509_free(issuer); 432413498266Sopenharmony_ci } 432513498266Sopenharmony_ci 432613498266Sopenharmony_ci lerr = SSL_get_verify_result(backend->handle); 432713498266Sopenharmony_ci ssl_config->certverifyresult = lerr; 432813498266Sopenharmony_ci if(lerr != X509_V_OK) { 432913498266Sopenharmony_ci if(conn_config->verifypeer) { 433013498266Sopenharmony_ci /* We probably never reach this, because SSL_connect() will fail 433113498266Sopenharmony_ci and we return earlier if verifypeer is set? */ 433213498266Sopenharmony_ci if(strict) 433313498266Sopenharmony_ci failf(data, "SSL certificate verify result: %s (%ld)", 433413498266Sopenharmony_ci X509_verify_cert_error_string(lerr), lerr); 433513498266Sopenharmony_ci result = CURLE_PEER_FAILED_VERIFICATION; 433613498266Sopenharmony_ci } 433713498266Sopenharmony_ci else 433813498266Sopenharmony_ci infof(data, " SSL certificate verify result: %s (%ld)," 433913498266Sopenharmony_ci " continuing anyway.", 434013498266Sopenharmony_ci X509_verify_cert_error_string(lerr), lerr); 434113498266Sopenharmony_ci } 434213498266Sopenharmony_ci else 434313498266Sopenharmony_ci infof(data, " SSL certificate verify ok."); 434413498266Sopenharmony_ci } 434513498266Sopenharmony_ci 434613498266Sopenharmony_ci infof_certstack(data, backend->handle); 434713498266Sopenharmony_ci 434813498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ 434913498266Sopenharmony_ci !defined(OPENSSL_NO_OCSP) 435013498266Sopenharmony_ci if(conn_config->verifystatus && !connssl->reused_session) { 435113498266Sopenharmony_ci /* don't do this after Session ID reuse */ 435213498266Sopenharmony_ci result = verifystatus(cf, data); 435313498266Sopenharmony_ci if(result) { 435413498266Sopenharmony_ci /* when verifystatus failed, remove the session id from the cache again 435513498266Sopenharmony_ci if present */ 435613498266Sopenharmony_ci if(!Curl_ssl_cf_is_proxy(cf)) { 435713498266Sopenharmony_ci void *old_ssl_sessionid = NULL; 435813498266Sopenharmony_ci bool incache; 435913498266Sopenharmony_ci Curl_ssl_sessionid_lock(data); 436013498266Sopenharmony_ci incache = !(Curl_ssl_getsessionid(cf, data, &old_ssl_sessionid, NULL)); 436113498266Sopenharmony_ci if(incache) { 436213498266Sopenharmony_ci infof(data, "Remove session ID again from cache"); 436313498266Sopenharmony_ci Curl_ssl_delsessionid(data, old_ssl_sessionid); 436413498266Sopenharmony_ci } 436513498266Sopenharmony_ci Curl_ssl_sessionid_unlock(data); 436613498266Sopenharmony_ci } 436713498266Sopenharmony_ci 436813498266Sopenharmony_ci X509_free(backend->server_cert); 436913498266Sopenharmony_ci backend->server_cert = NULL; 437013498266Sopenharmony_ci return result; 437113498266Sopenharmony_ci } 437213498266Sopenharmony_ci } 437313498266Sopenharmony_ci#endif 437413498266Sopenharmony_ci 437513498266Sopenharmony_ci if(!strict) 437613498266Sopenharmony_ci /* when not strict, we don't bother about the verify cert problems */ 437713498266Sopenharmony_ci result = CURLE_OK; 437813498266Sopenharmony_ci 437913498266Sopenharmony_ci ptr = Curl_ssl_cf_is_proxy(cf)? 438013498266Sopenharmony_ci data->set.str[STRING_SSL_PINNEDPUBLICKEY_PROXY]: 438113498266Sopenharmony_ci data->set.str[STRING_SSL_PINNEDPUBLICKEY]; 438213498266Sopenharmony_ci if(!result && ptr) { 438313498266Sopenharmony_ci result = ossl_pkp_pin_peer_pubkey(data, backend->server_cert, ptr); 438413498266Sopenharmony_ci if(result) 438513498266Sopenharmony_ci failf(data, "SSL: public key does not match pinned public key"); 438613498266Sopenharmony_ci } 438713498266Sopenharmony_ci 438813498266Sopenharmony_ci X509_free(backend->server_cert); 438913498266Sopenharmony_ci backend->server_cert = NULL; 439013498266Sopenharmony_ci connssl->connecting_state = ssl_connect_done; 439113498266Sopenharmony_ci 439213498266Sopenharmony_ci return result; 439313498266Sopenharmony_ci} 439413498266Sopenharmony_ci 439513498266Sopenharmony_cistatic CURLcode ossl_connect_step3(struct Curl_cfilter *cf, 439613498266Sopenharmony_ci struct Curl_easy *data) 439713498266Sopenharmony_ci{ 439813498266Sopenharmony_ci CURLcode result = CURLE_OK; 439913498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 440013498266Sopenharmony_ci struct ssl_primary_config *conn_config = Curl_ssl_cf_get_primary_config(cf); 440113498266Sopenharmony_ci 440213498266Sopenharmony_ci DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); 440313498266Sopenharmony_ci 440413498266Sopenharmony_ci /* 440513498266Sopenharmony_ci * We check certificates to authenticate the server; otherwise we risk 440613498266Sopenharmony_ci * man-in-the-middle attack; NEVERTHELESS, if we're told explicitly not to 440713498266Sopenharmony_ci * verify the peer, ignore faults and failures from the server cert 440813498266Sopenharmony_ci * operations. 440913498266Sopenharmony_ci */ 441013498266Sopenharmony_ci 441113498266Sopenharmony_ci result = servercert(cf, data, conn_config->verifypeer || 441213498266Sopenharmony_ci conn_config->verifyhost); 441313498266Sopenharmony_ci 441413498266Sopenharmony_ci if(!result) 441513498266Sopenharmony_ci connssl->connecting_state = ssl_connect_done; 441613498266Sopenharmony_ci 441713498266Sopenharmony_ci return result; 441813498266Sopenharmony_ci} 441913498266Sopenharmony_ci 442013498266Sopenharmony_cistatic CURLcode ossl_connect_common(struct Curl_cfilter *cf, 442113498266Sopenharmony_ci struct Curl_easy *data, 442213498266Sopenharmony_ci bool nonblocking, 442313498266Sopenharmony_ci bool *done) 442413498266Sopenharmony_ci{ 442513498266Sopenharmony_ci CURLcode result = CURLE_OK; 442613498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 442713498266Sopenharmony_ci curl_socket_t sockfd = Curl_conn_cf_get_socket(cf, data); 442813498266Sopenharmony_ci int what; 442913498266Sopenharmony_ci 443013498266Sopenharmony_ci /* check if the connection has already been established */ 443113498266Sopenharmony_ci if(ssl_connection_complete == connssl->state) { 443213498266Sopenharmony_ci *done = TRUE; 443313498266Sopenharmony_ci return CURLE_OK; 443413498266Sopenharmony_ci } 443513498266Sopenharmony_ci 443613498266Sopenharmony_ci if(ssl_connect_1 == connssl->connecting_state) { 443713498266Sopenharmony_ci /* Find out how much more time we're allowed */ 443813498266Sopenharmony_ci const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); 443913498266Sopenharmony_ci 444013498266Sopenharmony_ci if(timeout_ms < 0) { 444113498266Sopenharmony_ci /* no need to continue if time is already up */ 444213498266Sopenharmony_ci failf(data, "SSL connection timeout"); 444313498266Sopenharmony_ci return CURLE_OPERATION_TIMEDOUT; 444413498266Sopenharmony_ci } 444513498266Sopenharmony_ci 444613498266Sopenharmony_ci result = ossl_connect_step1(cf, data); 444713498266Sopenharmony_ci if(result) 444813498266Sopenharmony_ci goto out; 444913498266Sopenharmony_ci } 445013498266Sopenharmony_ci 445113498266Sopenharmony_ci while(ssl_connect_2 == connssl->connecting_state || 445213498266Sopenharmony_ci ssl_connect_2_reading == connssl->connecting_state || 445313498266Sopenharmony_ci ssl_connect_2_writing == connssl->connecting_state) { 445413498266Sopenharmony_ci 445513498266Sopenharmony_ci /* check allowed time left */ 445613498266Sopenharmony_ci const timediff_t timeout_ms = Curl_timeleft(data, NULL, TRUE); 445713498266Sopenharmony_ci 445813498266Sopenharmony_ci if(timeout_ms < 0) { 445913498266Sopenharmony_ci /* no need to continue if time already is up */ 446013498266Sopenharmony_ci failf(data, "SSL connection timeout"); 446113498266Sopenharmony_ci result = CURLE_OPERATION_TIMEDOUT; 446213498266Sopenharmony_ci goto out; 446313498266Sopenharmony_ci } 446413498266Sopenharmony_ci 446513498266Sopenharmony_ci /* if ssl is expecting something, check if it's available. */ 446613498266Sopenharmony_ci if(!nonblocking && 446713498266Sopenharmony_ci (connssl->connecting_state == ssl_connect_2_reading || 446813498266Sopenharmony_ci connssl->connecting_state == ssl_connect_2_writing)) { 446913498266Sopenharmony_ci 447013498266Sopenharmony_ci curl_socket_t writefd = ssl_connect_2_writing == 447113498266Sopenharmony_ci connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 447213498266Sopenharmony_ci curl_socket_t readfd = ssl_connect_2_reading == 447313498266Sopenharmony_ci connssl->connecting_state?sockfd:CURL_SOCKET_BAD; 447413498266Sopenharmony_ci 447513498266Sopenharmony_ci what = Curl_socket_check(readfd, CURL_SOCKET_BAD, writefd, 447613498266Sopenharmony_ci timeout_ms); 447713498266Sopenharmony_ci if(what < 0) { 447813498266Sopenharmony_ci /* fatal error */ 447913498266Sopenharmony_ci failf(data, "select/poll on SSL socket, errno: %d", SOCKERRNO); 448013498266Sopenharmony_ci result = CURLE_SSL_CONNECT_ERROR; 448113498266Sopenharmony_ci goto out; 448213498266Sopenharmony_ci } 448313498266Sopenharmony_ci if(0 == what) { 448413498266Sopenharmony_ci /* timeout */ 448513498266Sopenharmony_ci failf(data, "SSL connection timeout"); 448613498266Sopenharmony_ci result = CURLE_OPERATION_TIMEDOUT; 448713498266Sopenharmony_ci goto out; 448813498266Sopenharmony_ci } 448913498266Sopenharmony_ci /* socket is readable or writable */ 449013498266Sopenharmony_ci } 449113498266Sopenharmony_ci 449213498266Sopenharmony_ci /* Run transaction, and return to the caller if it failed or if this 449313498266Sopenharmony_ci * connection is done nonblocking and this loop would execute again. This 449413498266Sopenharmony_ci * permits the owner of a multi handle to abort a connection attempt 449513498266Sopenharmony_ci * before step2 has completed while ensuring that a client using select() 449613498266Sopenharmony_ci * or epoll() will always have a valid fdset to wait on. 449713498266Sopenharmony_ci */ 449813498266Sopenharmony_ci result = ossl_connect_step2(cf, data); 449913498266Sopenharmony_ci if(result || (nonblocking && 450013498266Sopenharmony_ci (ssl_connect_2 == connssl->connecting_state || 450113498266Sopenharmony_ci ssl_connect_2_reading == connssl->connecting_state || 450213498266Sopenharmony_ci ssl_connect_2_writing == connssl->connecting_state))) 450313498266Sopenharmony_ci goto out; 450413498266Sopenharmony_ci 450513498266Sopenharmony_ci } /* repeat step2 until all transactions are done. */ 450613498266Sopenharmony_ci 450713498266Sopenharmony_ci if(ssl_connect_3 == connssl->connecting_state) { 450813498266Sopenharmony_ci result = ossl_connect_step3(cf, data); 450913498266Sopenharmony_ci if(result) 451013498266Sopenharmony_ci goto out; 451113498266Sopenharmony_ci } 451213498266Sopenharmony_ci 451313498266Sopenharmony_ci if(ssl_connect_done == connssl->connecting_state) { 451413498266Sopenharmony_ci connssl->state = ssl_connection_complete; 451513498266Sopenharmony_ci *done = TRUE; 451613498266Sopenharmony_ci } 451713498266Sopenharmony_ci else 451813498266Sopenharmony_ci *done = FALSE; 451913498266Sopenharmony_ci 452013498266Sopenharmony_ci /* Reset our connect state machine */ 452113498266Sopenharmony_ci connssl->connecting_state = ssl_connect_1; 452213498266Sopenharmony_ci 452313498266Sopenharmony_ciout: 452413498266Sopenharmony_ci return result; 452513498266Sopenharmony_ci} 452613498266Sopenharmony_ci 452713498266Sopenharmony_cistatic CURLcode ossl_connect_nonblocking(struct Curl_cfilter *cf, 452813498266Sopenharmony_ci struct Curl_easy *data, 452913498266Sopenharmony_ci bool *done) 453013498266Sopenharmony_ci{ 453113498266Sopenharmony_ci return ossl_connect_common(cf, data, TRUE, done); 453213498266Sopenharmony_ci} 453313498266Sopenharmony_ci 453413498266Sopenharmony_cistatic CURLcode ossl_connect(struct Curl_cfilter *cf, 453513498266Sopenharmony_ci struct Curl_easy *data) 453613498266Sopenharmony_ci{ 453713498266Sopenharmony_ci CURLcode result; 453813498266Sopenharmony_ci bool done = FALSE; 453913498266Sopenharmony_ci 454013498266Sopenharmony_ci result = ossl_connect_common(cf, data, FALSE, &done); 454113498266Sopenharmony_ci if(result) 454213498266Sopenharmony_ci return result; 454313498266Sopenharmony_ci 454413498266Sopenharmony_ci DEBUGASSERT(done); 454513498266Sopenharmony_ci 454613498266Sopenharmony_ci return CURLE_OK; 454713498266Sopenharmony_ci} 454813498266Sopenharmony_ci 454913498266Sopenharmony_cistatic bool ossl_data_pending(struct Curl_cfilter *cf, 455013498266Sopenharmony_ci const struct Curl_easy *data) 455113498266Sopenharmony_ci{ 455213498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 455313498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 455413498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 455513498266Sopenharmony_ci 455613498266Sopenharmony_ci (void)data; 455713498266Sopenharmony_ci DEBUGASSERT(connssl && backend); 455813498266Sopenharmony_ci if(backend->handle && SSL_pending(backend->handle)) 455913498266Sopenharmony_ci return TRUE; 456013498266Sopenharmony_ci return FALSE; 456113498266Sopenharmony_ci} 456213498266Sopenharmony_ci 456313498266Sopenharmony_cistatic ssize_t ossl_send(struct Curl_cfilter *cf, 456413498266Sopenharmony_ci struct Curl_easy *data, 456513498266Sopenharmony_ci const void *mem, 456613498266Sopenharmony_ci size_t len, 456713498266Sopenharmony_ci CURLcode *curlcode) 456813498266Sopenharmony_ci{ 456913498266Sopenharmony_ci /* SSL_write() is said to return 'int' while write() and send() returns 457013498266Sopenharmony_ci 'size_t' */ 457113498266Sopenharmony_ci int err; 457213498266Sopenharmony_ci char error_buffer[256]; 457313498266Sopenharmony_ci sslerr_t sslerror; 457413498266Sopenharmony_ci int memlen; 457513498266Sopenharmony_ci int rc; 457613498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 457713498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 457813498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 457913498266Sopenharmony_ci 458013498266Sopenharmony_ci (void)data; 458113498266Sopenharmony_ci DEBUGASSERT(backend); 458213498266Sopenharmony_ci 458313498266Sopenharmony_ci ERR_clear_error(); 458413498266Sopenharmony_ci 458513498266Sopenharmony_ci memlen = (len > (size_t)INT_MAX) ? INT_MAX : (int)len; 458613498266Sopenharmony_ci rc = SSL_write(backend->handle, mem, memlen); 458713498266Sopenharmony_ci 458813498266Sopenharmony_ci if(rc <= 0) { 458913498266Sopenharmony_ci err = SSL_get_error(backend->handle, rc); 459013498266Sopenharmony_ci 459113498266Sopenharmony_ci switch(err) { 459213498266Sopenharmony_ci case SSL_ERROR_WANT_READ: 459313498266Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 459413498266Sopenharmony_ci /* The operation did not complete; the same TLS/SSL I/O function 459513498266Sopenharmony_ci should be called again later. This is basically an EWOULDBLOCK 459613498266Sopenharmony_ci equivalent. */ 459713498266Sopenharmony_ci *curlcode = CURLE_AGAIN; 459813498266Sopenharmony_ci rc = -1; 459913498266Sopenharmony_ci goto out; 460013498266Sopenharmony_ci case SSL_ERROR_SYSCALL: 460113498266Sopenharmony_ci { 460213498266Sopenharmony_ci int sockerr = SOCKERRNO; 460313498266Sopenharmony_ci 460413498266Sopenharmony_ci if(backend->io_result == CURLE_AGAIN) { 460513498266Sopenharmony_ci *curlcode = CURLE_AGAIN; 460613498266Sopenharmony_ci rc = -1; 460713498266Sopenharmony_ci goto out; 460813498266Sopenharmony_ci } 460913498266Sopenharmony_ci sslerror = ERR_get_error(); 461013498266Sopenharmony_ci if(sslerror) 461113498266Sopenharmony_ci ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)); 461213498266Sopenharmony_ci else if(sockerr) 461313498266Sopenharmony_ci Curl_strerror(sockerr, error_buffer, sizeof(error_buffer)); 461413498266Sopenharmony_ci else 461513498266Sopenharmony_ci msnprintf(error_buffer, sizeof(error_buffer), "%s", 461613498266Sopenharmony_ci SSL_ERROR_to_str(err)); 461713498266Sopenharmony_ci 461813498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", 461913498266Sopenharmony_ci error_buffer, sockerr); 462013498266Sopenharmony_ci *curlcode = CURLE_SEND_ERROR; 462113498266Sopenharmony_ci rc = -1; 462213498266Sopenharmony_ci goto out; 462313498266Sopenharmony_ci } 462413498266Sopenharmony_ci case SSL_ERROR_SSL: { 462513498266Sopenharmony_ci /* A failure in the SSL library occurred, usually a protocol error. 462613498266Sopenharmony_ci The OpenSSL error queue contains more information on the error. */ 462713498266Sopenharmony_ci sslerror = ERR_get_error(); 462813498266Sopenharmony_ci failf(data, "SSL_write() error: %s", 462913498266Sopenharmony_ci ossl_strerror(sslerror, error_buffer, sizeof(error_buffer))); 463013498266Sopenharmony_ci *curlcode = CURLE_SEND_ERROR; 463113498266Sopenharmony_ci rc = -1; 463213498266Sopenharmony_ci goto out; 463313498266Sopenharmony_ci } 463413498266Sopenharmony_ci default: 463513498266Sopenharmony_ci /* a true error */ 463613498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_write: %s, errno %d", 463713498266Sopenharmony_ci SSL_ERROR_to_str(err), SOCKERRNO); 463813498266Sopenharmony_ci *curlcode = CURLE_SEND_ERROR; 463913498266Sopenharmony_ci rc = -1; 464013498266Sopenharmony_ci goto out; 464113498266Sopenharmony_ci } 464213498266Sopenharmony_ci } 464313498266Sopenharmony_ci *curlcode = CURLE_OK; 464413498266Sopenharmony_ci 464513498266Sopenharmony_ciout: 464613498266Sopenharmony_ci return (ssize_t)rc; /* number of bytes */ 464713498266Sopenharmony_ci} 464813498266Sopenharmony_ci 464913498266Sopenharmony_cistatic ssize_t ossl_recv(struct Curl_cfilter *cf, 465013498266Sopenharmony_ci struct Curl_easy *data, /* transfer */ 465113498266Sopenharmony_ci char *buf, /* store read data here */ 465213498266Sopenharmony_ci size_t buffersize, /* max amount to read */ 465313498266Sopenharmony_ci CURLcode *curlcode) 465413498266Sopenharmony_ci{ 465513498266Sopenharmony_ci char error_buffer[256]; 465613498266Sopenharmony_ci unsigned long sslerror; 465713498266Sopenharmony_ci ssize_t nread; 465813498266Sopenharmony_ci int buffsize; 465913498266Sopenharmony_ci struct connectdata *conn = cf->conn; 466013498266Sopenharmony_ci struct ssl_connect_data *connssl = cf->ctx; 466113498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 466213498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 466313498266Sopenharmony_ci 466413498266Sopenharmony_ci (void)data; 466513498266Sopenharmony_ci DEBUGASSERT(backend); 466613498266Sopenharmony_ci 466713498266Sopenharmony_ci ERR_clear_error(); 466813498266Sopenharmony_ci 466913498266Sopenharmony_ci buffsize = (buffersize > (size_t)INT_MAX) ? INT_MAX : (int)buffersize; 467013498266Sopenharmony_ci nread = (ssize_t)SSL_read(backend->handle, buf, buffsize); 467113498266Sopenharmony_ci 467213498266Sopenharmony_ci if(nread <= 0) { 467313498266Sopenharmony_ci /* failed SSL_read */ 467413498266Sopenharmony_ci int err = SSL_get_error(backend->handle, (int)nread); 467513498266Sopenharmony_ci 467613498266Sopenharmony_ci switch(err) { 467713498266Sopenharmony_ci case SSL_ERROR_NONE: /* this is not an error */ 467813498266Sopenharmony_ci break; 467913498266Sopenharmony_ci case SSL_ERROR_ZERO_RETURN: /* no more data */ 468013498266Sopenharmony_ci /* close_notify alert */ 468113498266Sopenharmony_ci if(cf->sockindex == FIRSTSOCKET) 468213498266Sopenharmony_ci /* mark the connection for close if it is indeed the control 468313498266Sopenharmony_ci connection */ 468413498266Sopenharmony_ci connclose(conn, "TLS close_notify"); 468513498266Sopenharmony_ci break; 468613498266Sopenharmony_ci case SSL_ERROR_WANT_READ: 468713498266Sopenharmony_ci case SSL_ERROR_WANT_WRITE: 468813498266Sopenharmony_ci /* there's data pending, re-invoke SSL_read() */ 468913498266Sopenharmony_ci *curlcode = CURLE_AGAIN; 469013498266Sopenharmony_ci nread = -1; 469113498266Sopenharmony_ci goto out; 469213498266Sopenharmony_ci default: 469313498266Sopenharmony_ci /* openssl/ssl.h for SSL_ERROR_SYSCALL says "look at error stack/return 469413498266Sopenharmony_ci value/errno" */ 469513498266Sopenharmony_ci /* https://www.openssl.org/docs/crypto/ERR_get_error.html */ 469613498266Sopenharmony_ci if(backend->io_result == CURLE_AGAIN) { 469713498266Sopenharmony_ci *curlcode = CURLE_AGAIN; 469813498266Sopenharmony_ci nread = -1; 469913498266Sopenharmony_ci goto out; 470013498266Sopenharmony_ci } 470113498266Sopenharmony_ci sslerror = ERR_get_error(); 470213498266Sopenharmony_ci if((nread < 0) || sslerror) { 470313498266Sopenharmony_ci /* If the return code was negative or there actually is an error in the 470413498266Sopenharmony_ci queue */ 470513498266Sopenharmony_ci int sockerr = SOCKERRNO; 470613498266Sopenharmony_ci if(sslerror) 470713498266Sopenharmony_ci ossl_strerror(sslerror, error_buffer, sizeof(error_buffer)); 470813498266Sopenharmony_ci else if(sockerr && err == SSL_ERROR_SYSCALL) 470913498266Sopenharmony_ci Curl_strerror(sockerr, error_buffer, sizeof(error_buffer)); 471013498266Sopenharmony_ci else 471113498266Sopenharmony_ci msnprintf(error_buffer, sizeof(error_buffer), "%s", 471213498266Sopenharmony_ci SSL_ERROR_to_str(err)); 471313498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d", 471413498266Sopenharmony_ci error_buffer, sockerr); 471513498266Sopenharmony_ci *curlcode = CURLE_RECV_ERROR; 471613498266Sopenharmony_ci nread = -1; 471713498266Sopenharmony_ci goto out; 471813498266Sopenharmony_ci } 471913498266Sopenharmony_ci /* For debug builds be a little stricter and error on any 472013498266Sopenharmony_ci SSL_ERROR_SYSCALL. For example a server may have closed the connection 472113498266Sopenharmony_ci abruptly without a close_notify alert. For compatibility with older 472213498266Sopenharmony_ci peers we don't do this by default. #4624 472313498266Sopenharmony_ci 472413498266Sopenharmony_ci We can use this to gauge how many users may be affected, and 472513498266Sopenharmony_ci if it goes ok eventually transition to allow in dev and release with 472613498266Sopenharmony_ci the newest OpenSSL: #if (OPENSSL_VERSION_NUMBER >= 0x10101000L) */ 472713498266Sopenharmony_ci#ifdef DEBUGBUILD 472813498266Sopenharmony_ci if(err == SSL_ERROR_SYSCALL) { 472913498266Sopenharmony_ci int sockerr = SOCKERRNO; 473013498266Sopenharmony_ci if(sockerr) 473113498266Sopenharmony_ci Curl_strerror(sockerr, error_buffer, sizeof(error_buffer)); 473213498266Sopenharmony_ci else { 473313498266Sopenharmony_ci msnprintf(error_buffer, sizeof(error_buffer), 473413498266Sopenharmony_ci "Connection closed abruptly"); 473513498266Sopenharmony_ci } 473613498266Sopenharmony_ci failf(data, OSSL_PACKAGE " SSL_read: %s, errno %d" 473713498266Sopenharmony_ci " (Fatal because this is a curl debug build)", 473813498266Sopenharmony_ci error_buffer, sockerr); 473913498266Sopenharmony_ci *curlcode = CURLE_RECV_ERROR; 474013498266Sopenharmony_ci nread = -1; 474113498266Sopenharmony_ci goto out; 474213498266Sopenharmony_ci } 474313498266Sopenharmony_ci#endif 474413498266Sopenharmony_ci } 474513498266Sopenharmony_ci } 474613498266Sopenharmony_ci 474713498266Sopenharmony_ciout: 474813498266Sopenharmony_ci return nread; 474913498266Sopenharmony_ci} 475013498266Sopenharmony_ci 475113498266Sopenharmony_cistatic size_t ossl_version(char *buffer, size_t size) 475213498266Sopenharmony_ci{ 475313498266Sopenharmony_ci#ifdef LIBRESSL_VERSION_NUMBER 475413498266Sopenharmony_ci#ifdef HAVE_OPENSSL_VERSION 475513498266Sopenharmony_ci char *p; 475613498266Sopenharmony_ci int count; 475713498266Sopenharmony_ci const char *ver = OpenSSL_version(OPENSSL_VERSION); 475813498266Sopenharmony_ci const char expected[] = OSSL_PACKAGE " "; /* ie "LibreSSL " */ 475913498266Sopenharmony_ci if(strncasecompare(ver, expected, sizeof(expected) - 1)) { 476013498266Sopenharmony_ci ver += sizeof(expected) - 1; 476113498266Sopenharmony_ci } 476213498266Sopenharmony_ci count = msnprintf(buffer, size, "%s/%s", OSSL_PACKAGE, ver); 476313498266Sopenharmony_ci for(p = buffer; *p; ++p) { 476413498266Sopenharmony_ci if(ISBLANK(*p)) 476513498266Sopenharmony_ci *p = '_'; 476613498266Sopenharmony_ci } 476713498266Sopenharmony_ci return count; 476813498266Sopenharmony_ci#else 476913498266Sopenharmony_ci return msnprintf(buffer, size, "%s/%lx.%lx.%lx", 477013498266Sopenharmony_ci OSSL_PACKAGE, 477113498266Sopenharmony_ci (LIBRESSL_VERSION_NUMBER>>28)&0xf, 477213498266Sopenharmony_ci (LIBRESSL_VERSION_NUMBER>>20)&0xff, 477313498266Sopenharmony_ci (LIBRESSL_VERSION_NUMBER>>12)&0xff); 477413498266Sopenharmony_ci#endif 477513498266Sopenharmony_ci#elif defined(OPENSSL_IS_BORINGSSL) 477613498266Sopenharmony_ci#ifdef CURL_BORINGSSL_VERSION 477713498266Sopenharmony_ci return msnprintf(buffer, size, "%s/%s", 477813498266Sopenharmony_ci OSSL_PACKAGE, 477913498266Sopenharmony_ci CURL_BORINGSSL_VERSION); 478013498266Sopenharmony_ci#else 478113498266Sopenharmony_ci return msnprintf(buffer, size, OSSL_PACKAGE); 478213498266Sopenharmony_ci#endif 478313498266Sopenharmony_ci#elif defined(OPENSSL_IS_AWSLC) 478413498266Sopenharmony_ci return msnprintf(buffer, size, "%s/%s", 478513498266Sopenharmony_ci OSSL_PACKAGE, 478613498266Sopenharmony_ci AWSLC_VERSION_NUMBER_STRING); 478713498266Sopenharmony_ci#elif defined(HAVE_OPENSSL_VERSION) && defined(OPENSSL_VERSION_STRING) 478813498266Sopenharmony_ci return msnprintf(buffer, size, "%s/%s", 478913498266Sopenharmony_ci OSSL_PACKAGE, OpenSSL_version(OPENSSL_VERSION_STRING)); 479013498266Sopenharmony_ci#else 479113498266Sopenharmony_ci /* not LibreSSL, BoringSSL and not using OpenSSL_version */ 479213498266Sopenharmony_ci 479313498266Sopenharmony_ci char sub[3]; 479413498266Sopenharmony_ci unsigned long ssleay_value; 479513498266Sopenharmony_ci sub[2]='\0'; 479613498266Sopenharmony_ci sub[1]='\0'; 479713498266Sopenharmony_ci ssleay_value = OpenSSL_version_num(); 479813498266Sopenharmony_ci if(ssleay_value < 0x906000) { 479913498266Sopenharmony_ci ssleay_value = SSLEAY_VERSION_NUMBER; 480013498266Sopenharmony_ci sub[0]='\0'; 480113498266Sopenharmony_ci } 480213498266Sopenharmony_ci else { 480313498266Sopenharmony_ci if(ssleay_value&0xff0) { 480413498266Sopenharmony_ci int minor_ver = (ssleay_value >> 4) & 0xff; 480513498266Sopenharmony_ci if(minor_ver > 26) { 480613498266Sopenharmony_ci /* handle extended version introduced for 0.9.8za */ 480713498266Sopenharmony_ci sub[1] = (char) ((minor_ver - 1) % 26 + 'a' + 1); 480813498266Sopenharmony_ci sub[0] = 'z'; 480913498266Sopenharmony_ci } 481013498266Sopenharmony_ci else { 481113498266Sopenharmony_ci sub[0] = (char) (minor_ver + 'a' - 1); 481213498266Sopenharmony_ci } 481313498266Sopenharmony_ci } 481413498266Sopenharmony_ci else 481513498266Sopenharmony_ci sub[0]='\0'; 481613498266Sopenharmony_ci } 481713498266Sopenharmony_ci 481813498266Sopenharmony_ci return msnprintf(buffer, size, "%s/%lx.%lx.%lx%s" 481913498266Sopenharmony_ci#ifdef OPENSSL_FIPS 482013498266Sopenharmony_ci "-fips" 482113498266Sopenharmony_ci#endif 482213498266Sopenharmony_ci , 482313498266Sopenharmony_ci OSSL_PACKAGE, 482413498266Sopenharmony_ci (ssleay_value>>28)&0xf, 482513498266Sopenharmony_ci (ssleay_value>>20)&0xff, 482613498266Sopenharmony_ci (ssleay_value>>12)&0xff, 482713498266Sopenharmony_ci sub); 482813498266Sopenharmony_ci#endif /* OPENSSL_IS_BORINGSSL */ 482913498266Sopenharmony_ci} 483013498266Sopenharmony_ci 483113498266Sopenharmony_ci/* can be called with data == NULL */ 483213498266Sopenharmony_cistatic CURLcode ossl_random(struct Curl_easy *data, 483313498266Sopenharmony_ci unsigned char *entropy, size_t length) 483413498266Sopenharmony_ci{ 483513498266Sopenharmony_ci int rc; 483613498266Sopenharmony_ci if(data) { 483713498266Sopenharmony_ci if(ossl_seed(data)) /* Initiate the seed if not already done */ 483813498266Sopenharmony_ci return CURLE_FAILED_INIT; /* couldn't seed for some reason */ 483913498266Sopenharmony_ci } 484013498266Sopenharmony_ci else { 484113498266Sopenharmony_ci if(!rand_enough()) 484213498266Sopenharmony_ci return CURLE_FAILED_INIT; 484313498266Sopenharmony_ci } 484413498266Sopenharmony_ci /* RAND_bytes() returns 1 on success, 0 otherwise. */ 484513498266Sopenharmony_ci rc = RAND_bytes(entropy, curlx_uztosi(length)); 484613498266Sopenharmony_ci return (rc == 1 ? CURLE_OK : CURLE_FAILED_INIT); 484713498266Sopenharmony_ci} 484813498266Sopenharmony_ci 484913498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) 485013498266Sopenharmony_cistatic CURLcode ossl_sha256sum(const unsigned char *tmp, /* input */ 485113498266Sopenharmony_ci size_t tmplen, 485213498266Sopenharmony_ci unsigned char *sha256sum /* output */, 485313498266Sopenharmony_ci size_t unused) 485413498266Sopenharmony_ci{ 485513498266Sopenharmony_ci EVP_MD_CTX *mdctx; 485613498266Sopenharmony_ci unsigned int len = 0; 485713498266Sopenharmony_ci (void) unused; 485813498266Sopenharmony_ci 485913498266Sopenharmony_ci mdctx = EVP_MD_CTX_create(); 486013498266Sopenharmony_ci if(!mdctx) 486113498266Sopenharmony_ci return CURLE_OUT_OF_MEMORY; 486213498266Sopenharmony_ci if(!EVP_DigestInit(mdctx, EVP_sha256())) { 486313498266Sopenharmony_ci EVP_MD_CTX_destroy(mdctx); 486413498266Sopenharmony_ci return CURLE_FAILED_INIT; 486513498266Sopenharmony_ci } 486613498266Sopenharmony_ci EVP_DigestUpdate(mdctx, tmp, tmplen); 486713498266Sopenharmony_ci EVP_DigestFinal_ex(mdctx, sha256sum, &len); 486813498266Sopenharmony_ci EVP_MD_CTX_destroy(mdctx); 486913498266Sopenharmony_ci return CURLE_OK; 487013498266Sopenharmony_ci} 487113498266Sopenharmony_ci#endif 487213498266Sopenharmony_ci 487313498266Sopenharmony_cistatic bool ossl_cert_status_request(void) 487413498266Sopenharmony_ci{ 487513498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090808fL) && !defined(OPENSSL_NO_TLSEXT) && \ 487613498266Sopenharmony_ci !defined(OPENSSL_NO_OCSP) 487713498266Sopenharmony_ci return TRUE; 487813498266Sopenharmony_ci#else 487913498266Sopenharmony_ci return FALSE; 488013498266Sopenharmony_ci#endif 488113498266Sopenharmony_ci} 488213498266Sopenharmony_ci 488313498266Sopenharmony_cistatic void *ossl_get_internals(struct ssl_connect_data *connssl, 488413498266Sopenharmony_ci CURLINFO info) 488513498266Sopenharmony_ci{ 488613498266Sopenharmony_ci /* Legacy: CURLINFO_TLS_SESSION must return an SSL_CTX pointer. */ 488713498266Sopenharmony_ci struct ossl_ssl_backend_data *backend = 488813498266Sopenharmony_ci (struct ossl_ssl_backend_data *)connssl->backend; 488913498266Sopenharmony_ci DEBUGASSERT(backend); 489013498266Sopenharmony_ci return info == CURLINFO_TLS_SESSION ? 489113498266Sopenharmony_ci (void *)backend->ctx : (void *)backend->handle; 489213498266Sopenharmony_ci} 489313498266Sopenharmony_ci 489413498266Sopenharmony_cistatic void ossl_free_multi_ssl_backend_data( 489513498266Sopenharmony_ci struct multi_ssl_backend_data *mbackend) 489613498266Sopenharmony_ci{ 489713498266Sopenharmony_ci#if defined(HAVE_SSL_X509_STORE_SHARE) 489813498266Sopenharmony_ci if(mbackend->store) { 489913498266Sopenharmony_ci X509_STORE_free(mbackend->store); 490013498266Sopenharmony_ci } 490113498266Sopenharmony_ci free(mbackend->CAfile); 490213498266Sopenharmony_ci free(mbackend); 490313498266Sopenharmony_ci#else /* HAVE_SSL_X509_STORE_SHARE */ 490413498266Sopenharmony_ci (void)mbackend; 490513498266Sopenharmony_ci#endif /* HAVE_SSL_X509_STORE_SHARE */ 490613498266Sopenharmony_ci} 490713498266Sopenharmony_ci 490813498266Sopenharmony_ciconst struct Curl_ssl Curl_ssl_openssl = { 490913498266Sopenharmony_ci { CURLSSLBACKEND_OPENSSL, "openssl" }, /* info */ 491013498266Sopenharmony_ci 491113498266Sopenharmony_ci SSLSUPP_CA_PATH | 491213498266Sopenharmony_ci SSLSUPP_CAINFO_BLOB | 491313498266Sopenharmony_ci SSLSUPP_CERTINFO | 491413498266Sopenharmony_ci SSLSUPP_PINNEDPUBKEY | 491513498266Sopenharmony_ci SSLSUPP_SSL_CTX | 491613498266Sopenharmony_ci#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES 491713498266Sopenharmony_ci SSLSUPP_TLS13_CIPHERSUITES | 491813498266Sopenharmony_ci#endif 491913498266Sopenharmony_ci SSLSUPP_HTTPS_PROXY, 492013498266Sopenharmony_ci 492113498266Sopenharmony_ci sizeof(struct ossl_ssl_backend_data), 492213498266Sopenharmony_ci 492313498266Sopenharmony_ci ossl_init, /* init */ 492413498266Sopenharmony_ci ossl_cleanup, /* cleanup */ 492513498266Sopenharmony_ci ossl_version, /* version */ 492613498266Sopenharmony_ci Curl_none_check_cxn, /* check_cxn */ 492713498266Sopenharmony_ci ossl_shutdown, /* shutdown */ 492813498266Sopenharmony_ci ossl_data_pending, /* data_pending */ 492913498266Sopenharmony_ci ossl_random, /* random */ 493013498266Sopenharmony_ci ossl_cert_status_request, /* cert_status_request */ 493113498266Sopenharmony_ci ossl_connect, /* connect */ 493213498266Sopenharmony_ci ossl_connect_nonblocking, /* connect_nonblocking */ 493313498266Sopenharmony_ci Curl_ssl_adjust_pollset, /* adjust_pollset */ 493413498266Sopenharmony_ci ossl_get_internals, /* get_internals */ 493513498266Sopenharmony_ci ossl_close, /* close_one */ 493613498266Sopenharmony_ci ossl_close_all, /* close_all */ 493713498266Sopenharmony_ci ossl_session_free, /* session_free */ 493813498266Sopenharmony_ci ossl_set_engine, /* set_engine */ 493913498266Sopenharmony_ci ossl_set_engine_default, /* set_engine_default */ 494013498266Sopenharmony_ci ossl_engines_list, /* engines_list */ 494113498266Sopenharmony_ci Curl_none_false_start, /* false_start */ 494213498266Sopenharmony_ci#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) && !defined(OPENSSL_NO_SHA256) 494313498266Sopenharmony_ci ossl_sha256sum, /* sha256sum */ 494413498266Sopenharmony_ci#else 494513498266Sopenharmony_ci NULL, /* sha256sum */ 494613498266Sopenharmony_ci#endif 494713498266Sopenharmony_ci NULL, /* use of data in this connection */ 494813498266Sopenharmony_ci NULL, /* remote of data from this connection */ 494913498266Sopenharmony_ci ossl_free_multi_ssl_backend_data, /* free_multi_ssl_backend_data */ 495013498266Sopenharmony_ci ossl_recv, /* recv decrypted data */ 495113498266Sopenharmony_ci ossl_send, /* send data to encrypt */ 495213498266Sopenharmony_ci}; 495313498266Sopenharmony_ci 495413498266Sopenharmony_ci#endif /* USE_OPENSSL */ 4955