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, &params, 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