]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Bug 5133: OpenSSL 3.0 support (#694)
authorAmos Jeffries <yadij@users.noreply.github.com>
Sat, 16 Jul 2022 11:44:16 +0000 (11:44 +0000)
committerSquid Anubis <squid-anubis@squid-cache.org>
Sun, 17 Jul 2022 13:07:21 +0000 (13:07 +0000)
This TLS update includes:

* Fix build with OpenSSL v3.
* Refactor RSA key generation to avoid deprecated RSA_*() APIs.
* Refactor DH parameter and key config to avoid deprecated DH_*() APIs.
* Refactor ECDH key creation to avoid deprecated EC_*() APIs.
* Deprecate ssl_engine support in builds with OpenSSL v1-.
* Disable ssl_engine support in builds OpenSSL v3+.

We deprecated/removed ssl_engine support (as summarized in the last two
bullets above) without providing an OpenSSL Providers-based alternative
because of the following factors:

1. We do not have the resources to update ssl_engine code to build
   (without deprecation warnings) with OpenSSL v3 when the feature is
   unused.

2. We do not have the resources to create an OpenSSL v3 Provider-based
   replacement for ssl_engine code that uses deprecated Engine APIs.

3. OpenSSL v3 deprecated Engine support (triggering deprecation warnings
   in applications that use Engine APIs with OpenSSL v3). Since Squid
   default builds use -Werror, doing nothing would break such builds.

4. Squid ssl_engine does not appear to be a popular feature.

configure.ac
doc/release-notes/release-6.sgml
src/cf.data.pre
src/main.cc
src/security/PeerOptions.cc
src/security/ServerOptions.cc
src/security/forward.h
src/ssl/gadgets.cc
src/ssl/gadgets.h
src/ssl/support.cc

index d3f8f21d852862cb579094e0a646456cff1f34dc..2d65559ea9396d3e8f7899053cbaed5b6c99457b 100644 (file)
@@ -1283,6 +1283,7 @@ if test "x$with_openssl" = "xyes"; then
     openssl/bio.h \
     openssl/bn.h \
     openssl/crypto.h \
+    openssl/decoder.h \
     openssl/dh.h \
     openssl/err.h \
     openssl/evp.h \
index 0e193a9155be057fd5493ff69224506b6ccc47af..8faa0159f0686a71729b6d0814799fdd63234666 100644 (file)
@@ -63,7 +63,9 @@ This section gives an account of those changes in three categories:
 <sect1>Changes to existing directives<label id="modifieddirectives">
 <p>
 <descrip>
-       <p>There have been no directives changed.
+       <tag>ssl_engine</tag>
+       <p>OpenSSL 3.0.0 deprecates the Engine feature. This directive is
+          only supported when Squid is built for older OpenSSL versions.
 
 </descrip>
 
index 493fb7cbeff8a71a11d2c74cca51cd014a3a7663..97b23a31dd45e7ea7b1447d3f044b11003b03e57 100644 (file)
@@ -3061,6 +3061,8 @@ DEFAULT: none
 DOC_START
        The OpenSSL engine to use. You will need to set this if you
        would like to use hardware SSL acceleration for example.
+
+       Not supported in builds with OpenSSL v3 or newer.
 DOC_END
 
 NAME: sslproxy_session_ttl
index 99bad6ea7403accc1e5fd56ae3b4edd47ce67ab2..c1e665232f5c9c85ea1e5658a55ad00cd365ce8a 100644 (file)
@@ -671,7 +671,9 @@ mainHandleCommandLineOption(const int optId, const char *optValue)
             printf("%s\n",SQUID_BUILD_INFO);
 #if USE_OPENSSL
         printf("\nThis binary uses %s. ", OpenSSL_version(OPENSSL_VERSION));
+#if OPENSSL_VERSION_MAJOR < 3
         printf("For legal restrictions on distribution see https://www.openssl.org/source/license.html\n\n");
+#endif
 #endif
         printf( "configure options: %s\n", SQUID_CONFIGURE_OPTIONS);
 
index 95e5a2eddc4536166f647c96196df025ff4e9c93..257ad28d27ebc60c3ac0823bfcfa30950e49c7c3 100644 (file)
@@ -293,134 +293,134 @@ Security::PeerOptions::createClientContext(bool setOptions)
 /// set of options we can parse and what they map to
 static struct ssl_option {
     const char *name;
-    long value;
+    Security::ParsedOptions value;
 
 } ssl_options[] = {
 
-#if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
+#if defined(SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG)
     {
         "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
     },
 #endif
-#if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
+#if defined(SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG)
     {
         "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
     },
 #endif
-#if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
+#if defined(SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER)
     {
         "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
     },
 #endif
-#if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
+#if defined(SSL_OP_SSLEAY_080_CLIENT_DH_BUG)
     {
         "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
     },
 #endif
-#if SSL_OP_TLS_D5_BUG
+#if defined(SSL_OP_TLS_D5_BUG)
     {
         "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
     },
 #endif
-#if SSL_OP_TLS_BLOCK_PADDING_BUG
+#if defined(SSL_OP_TLS_BLOCK_PADDING_BUG)
     {
         "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
     },
 #endif
-#if SSL_OP_TLS_ROLLBACK_BUG
+#if defined(SSL_OP_TLS_ROLLBACK_BUG)
     {
         "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
     },
 #endif
-#if SSL_OP_ALL
+#if defined(SSL_OP_ALL)
     {
         "ALL", (long)SSL_OP_ALL
     },
 #endif
-#if SSL_OP_SINGLE_DH_USE
+#if defined(SSL_OP_SINGLE_DH_USE)
     {
         "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
     },
 #endif
-#if SSL_OP_EPHEMERAL_RSA
+#if defined(SSL_OP_EPHEMERAL_RSA)
     {
         "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
     },
 #endif
-#if SSL_OP_PKCS1_CHECK_1
+#if defined(SSL_OP_PKCS1_CHECK_1)
     {
         "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
     },
 #endif
-#if SSL_OP_PKCS1_CHECK_2
+#if defined(SSL_OP_PKCS1_CHECK_2)
     {
         "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
     },
 #endif
-#if SSL_OP_NETSCAPE_CA_DN_BUG
+#if defined(SSL_OP_NETSCAPE_CA_DN_BUG)
     {
         "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
     },
 #endif
-#if SSL_OP_NON_EXPORT_FIRST
+#if defined(SSL_OP_NON_EXPORT_FIRST)
     {
         "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
     },
 #endif
-#if SSL_OP_CIPHER_SERVER_PREFERENCE
+#if defined(SSL_OP_CIPHER_SERVER_PREFERENCE)
     {
         "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
     },
 #endif
-#if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
+#if defined(SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG)
     {
         "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
     },
 #endif
-#if SSL_OP_NO_SSLv3
+#if defined(SSL_OP_NO_SSLv3)
     {
         "NO_SSLv3", SSL_OP_NO_SSLv3
     },
 #endif
-#if SSL_OP_NO_TLSv1
+#if defined(SSL_OP_NO_TLSv1)
     {
         "NO_TLSv1", SSL_OP_NO_TLSv1
     },
 #else
     { "NO_TLSv1", 0 },
 #endif
-#if SSL_OP_NO_TLSv1_1
+#if defined(SSL_OP_NO_TLSv1_1)
     {
         "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
     },
 #else
     { "NO_TLSv1_1", 0 },
 #endif
-#if SSL_OP_NO_TLSv1_2
+#if defined(SSL_OP_NO_TLSv1_2)
     {
         "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
     },
 #else
     { "NO_TLSv1_2", 0 },
 #endif
-#if SSL_OP_NO_TLSv1_3
+#if defined(SSL_OP_NO_TLSv1_3)
     {
         "NO_TLSv1_3", SSL_OP_NO_TLSv1_3
     },
 #else
     { "NO_TLSv1_3", 0 },
 #endif
-#if SSL_OP_NO_COMPRESSION
+#if defined(SSL_OP_NO_COMPRESSION)
     {
         "No_Compression", SSL_OP_NO_COMPRESSION
     },
 #endif
-#if SSL_OP_NO_TICKET
+#if defined(SSL_OP_NO_TICKET)
     {
         "NO_TICKET", SSL_OP_NO_TICKET
     },
 #endif
-#if SSL_OP_SINGLE_ECDH_USE
+#if defined(SSL_OP_SINGLE_ECDH_USE)
     {
         "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
     },
@@ -455,7 +455,7 @@ Security::PeerOptions::parseOptions()
 
 #if USE_OPENSSL
     ::Parser::Tokenizer tok(str);
-    long op = 0;
+    ParsedOptions op = 0;
 
     while (!tok.atEnd()) {
         enum {
@@ -472,7 +472,8 @@ Security::PeerOptions::parseOptions()
         static const CharacterSet optChars = CharacterSet("TLS-option", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
         int64_t hex = 0;
         SBuf option;
-        long value = 0;
+        ParsedOptions value = 0;
+        bool found = false;
 
         // Bug 4429: identify the full option name before determining text or numeric
         if (tok.prefix(option, optChars)) {
@@ -481,14 +482,16 @@ Security::PeerOptions::parseOptions()
             for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) {
                 if (option.cmp(opttmp->name) == 0) {
                     value = opttmp->value;
+                    found = true;
                     break;
                 }
             }
 
             // Special case.. hex specification
             ::Parser::Tokenizer tmp(option);
-            if (!value && tmp.int64(hex, 16, false) && tmp.atEnd()) {
+            if (!found && tmp.int64(hex, 16, false) && tmp.atEnd()) {
                 value = hex;
+                found = true;
             }
         }
 
@@ -502,7 +505,7 @@ Security::PeerOptions::parseOptions()
                 break;
             }
         } else {
-            debugs(83, DBG_PARSE_NOTE(1), "ERROR: Unknown TLS option " << option);
+            debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "ERROR: " << (found?"Unsupported":"Unknown") << " TLS option " << option);
         }
 
         static const CharacterSet delims("TLS-option-delim",":,");
@@ -512,9 +515,10 @@ Security::PeerOptions::parseOptions()
 
     }
 
-#if SSL_OP_NO_SSLv2
+#if defined(SSL_OP_NO_SSLv2)
     // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
-    op = op | SSL_OP_NO_SSLv2;
+    if (SSL_OP_NO_SSLv2)
+        op |= SSL_OP_NO_SSLv2;
 #endif
     parsedOptions = op;
 
index 5cf0c6e13f0b171fd372939ed5add1ec8d86c230..b2f55d6028aa49f014bf86ca34fe98016508e9d3 100644 (file)
@@ -10,6 +10,7 @@
 #include "anyp/PortCfg.h"
 #include "base/Packable.h"
 #include "cache_cf.h"
+#include "error/SysErrorDetail.h"
 #include "fatal.h"
 #include "globals.h"
 #include "security/ServerOptions.h"
@@ -19,6 +20,9 @@
 #include "compat/openssl.h"
 #include "ssl/support.h"
 
+#if HAVE_OPENSSL_DECODER_H
+#include <openssl/decoder.h>
+#endif
 #if HAVE_OPENSSL_ERR_H
 #include <openssl/err.h>
 #endif
@@ -352,11 +356,20 @@ Security::ServerOptions::loadDhParams()
     if (dhParamsFile.isEmpty())
         return;
 
+    // TODO: After loading and validating parameters, also validate that "the
+    // public and private components have the correct mathematical
+    // relationship". See EVP_PKEY_check().
+
 #if USE_OPENSSL
+#if OPENSSL_VERSION_MAJOR < 3
     DH *dhp = nullptr;
     if (FILE *in = fopen(dhParamsFile.c_str(), "r")) {
         dhp = PEM_read_DHparams(in, nullptr, nullptr, nullptr);
         fclose(in);
+    } else {
+        const auto xerrno = errno;
+        debugs(83, DBG_IMPORTANT, "WARNING: Failed to open '" << dhParamsFile << "'" << ReportSysError(xerrno));
+        return;
     }
 
     if (!dhp) {
@@ -374,7 +387,65 @@ Security::ServerOptions::loadDhParams()
     }
 
     parsedDhParams.resetWithoutLocking(dhp);
+
+#else // OpenSSL 3.0+
+    const auto type = eecdhCurve.isEmpty() ? "DH" : "EC";
+
+    Ssl::ForgetErrors();
+    EVP_PKEY *rawPkey = nullptr;
+    using DecoderContext = std::unique_ptr<OSSL_DECODER_CTX, HardFun<void, OSSL_DECODER_CTX*, &OSSL_DECODER_CTX_free> >;
+    if (const DecoderContext dctx{OSSL_DECODER_CTX_new_for_pkey(&rawPkey, "PEM", nullptr, type, 0, nullptr, nullptr)}) {
+
+        // OpenSSL documentation is vague on this, but OpenSSL code and our
+        // tests suggest that rawPkey remains nil here while rawCtx keeps
+        // rawPkey _address_ for use by the decoder (see OSSL_DECODER_from_fp()
+        // below). Thus, we must not move *rawPkey into a smart pointer until
+        // decoding is over. For cleanup code simplicity, we assert nil rawPkey.
+        assert(!rawPkey);
+
+        if (OSSL_DECODER_CTX_get_num_decoders(dctx.get()) == 0) {
+            debugs(83, DBG_IMPORTANT, "WARNING: No suitable decoders found for " << type << " parameters" << Ssl::ReportAndForgetErrors);
+            return;
+        }
+
+        if (const auto in = fopen(dhParamsFile.c_str(), "r")) {
+            if (OSSL_DECODER_from_fp(dctx.get(), in)) {
+                assert(rawPkey);
+                const Security::DhePointer pkey(rawPkey);
+                // TODO: verify that the loaded parameters match the curve named in eecdhCurve
+
+                if (const Ssl::EVP_PKEY_CTX_Pointer pkeyCtx{EVP_PKEY_CTX_new_from_pkey(nullptr, pkey.get(), nullptr)}) {
+                    switch (EVP_PKEY_param_check(pkeyCtx.get())) {
+                    case 1: // success
+                        parsedDhParams = pkey;
+                        break;
+                    case -2:
+                        debugs(83, DBG_PARSE_NOTE(2), "WARNING: OpenSSL does not support " << type << " parameters check: " << dhParamsFile << Ssl::ReportAndForgetErrors);
+                        break;
+                    default:
+                        debugs(83, DBG_IMPORTANT, "ERROR: Failed to verify " << type << " parameters in " << dhParamsFile << Ssl::ReportAndForgetErrors);
+                        break;
+                    }
+                } else {
+                    // TODO: Reduce error reporting code duplication.
+                    debugs(83, DBG_IMPORTANT, "ERROR: Cannot check " << type << " parameters in " << dhParamsFile << Ssl::ReportAndForgetErrors);
+                }
+            } else {
+                debugs(83, DBG_IMPORTANT, "WARNING: Failed to decode " << type << " parameters '" << dhParamsFile << "'" << Ssl::ReportAndForgetErrors);
+                EVP_PKEY_free(rawPkey); // probably still nil, but just in case
+            }
+            fclose(in);
+        } else {
+            const auto xerrno = errno;
+            debugs(83, DBG_IMPORTANT, "WARNING: Failed to open '" << dhParamsFile << "'" << ReportSysError(xerrno));
+        }
+
+    } else {
+        debugs(83, DBG_IMPORTANT, "WARNING: Unable to create decode context for " << type << " parameters" << Ssl::ReportAndForgetErrors);
+        return;
+    }
 #endif
+#endif // USE_OPENSSL
 }
 
 bool
@@ -454,12 +525,16 @@ Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx)
         debugs(83, 9, "Setting Ephemeral ECDH curve to " << eecdhCurve << ".");
 
 #if USE_OPENSSL && OPENSSL_VERSION_NUMBER >= 0x0090800fL && !defined(OPENSSL_NO_ECDH)
+
+        Ssl::ForgetErrors();
+
         int nid = OBJ_sn2nid(eecdhCurve.c_str());
         if (!nid) {
             debugs(83, DBG_CRITICAL, "ERROR: Unknown EECDH curve '" << eecdhCurve << "'");
             return;
         }
 
+#if OPENSSL_VERSION_MAJOR < 3
         auto ecdh = EC_KEY_new_by_curve_name(nid);
         if (!ecdh) {
             const auto x = ERR_get_error();
@@ -473,6 +548,13 @@ Security::ServerOptions::updateContextEecdh(Security::ContextPointer &ctx)
         }
         EC_KEY_free(ecdh);
 
+#else
+        // TODO: Support multiple group names via SSL_CTX_set1_groups_list().
+        if (!SSL_CTX_set1_groups(ctx.get(), &nid, 1)) {
+            debugs(83, DBG_CRITICAL, "ERROR: Unable to set Ephemeral ECDH: " << Ssl::ReportAndForgetErrors);
+            return;
+        }
+#endif
 #else
         debugs(83, DBG_CRITICAL, "ERROR: EECDH is not available in this build." <<
                " Please link against OpenSSL>=0.9.8 and ensure OPENSSL_NO_ECDH is not set.");
index d0d745efb02dc8b4918897eaccc3233a3cb78973..997c38ec473d032138e6f059ee15cfd7f146e619 100644 (file)
@@ -101,10 +101,25 @@ typedef std::list<Security::CertPointer> CertList;
 typedef std::list<Security::CrlPointer> CertRevokeList;
 
 #if USE_OPENSSL
+CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
+using PrivateKeyPointer = Security::LockingPointer<EVP_PKEY, EVP_PKEY_free_cpp, HardFun<int, EVP_PKEY *, EVP_PKEY_up_ref>>;
+#elif USE_GNUTLS
+using PrivateKeyPointer = std::shared_ptr<struct gnutls_x509_privkey_int>;
+#else
+using PrivateKeyPointer = std::shared_ptr<void>;
+#endif
+
+#if USE_OPENSSL
+#if OPENSSL_VERSION_MAJOR < 3
 CtoCpp1(DH_free, DH *);
 typedef Security::LockingPointer<DH, DH_free_cpp, HardFun<int, DH *, DH_up_ref> > DhePointer;
 #else
-typedef void *DhePointer;
+using DhePointer = PrivateKeyPointer;
+#endif
+#elif USE_GNUTLS
+using DhePointer = void *;
+#else
+using DhePointer = void *;
 #endif
 
 class EncryptorAnswer;
@@ -170,7 +185,7 @@ class KeyData;
 class KeyLog;
 
 #if USE_OPENSSL
-typedef long ParsedOptions;
+using ParsedOptions = uint64_t;
 #elif USE_GNUTLS
 typedef std::shared_ptr<struct gnutls_priority_st> ParsedOptions;
 #else
@@ -186,15 +201,6 @@ class PeerConnector;
 class BlindPeerConnector;
 class PeerOptions;
 
-#if USE_OPENSSL
-CtoCpp1(EVP_PKEY_free, EVP_PKEY *)
-typedef Security::LockingPointer<EVP_PKEY, EVP_PKEY_free_cpp, HardFun<int, EVP_PKEY *, EVP_PKEY_up_ref> > PrivateKeyPointer;
-#elif USE_GNUTLS
-typedef std::shared_ptr<struct gnutls_x509_privkey_int> PrivateKeyPointer;
-#else
-typedef std::shared_ptr<void> PrivateKeyPointer;
-#endif
-
 class ServerOptions;
 
 class ErrorDetail;
index 4eff48bf7d244ab121c83b036c1baf6dbb712cde..fab53b00cfa4f74caf835abb9dcc86c963b1431e 100644 (file)
@@ -48,33 +48,26 @@ ThrowErrors(const char * const problem, const int savedErrno, const SourceLocati
                         where);
 }
 
-EVP_PKEY * Ssl::createSslPrivateKey()
+static Security::PrivateKeyPointer
+CreateRsaPrivateKey()
 {
-    Security::PrivateKeyPointer pkey(EVP_PKEY_new());
-
-    if (!pkey)
-        return nullptr;
-
-    BIGNUM_Pointer bn(BN_new());
-    if (!bn)
-        return nullptr;
-
-    if (!BN_set_word(bn.get(), RSA_F4))
+    Ssl::EVP_PKEY_CTX_Pointer rsa(EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, nullptr));
+    if (!rsa)
         return nullptr;
 
-    Ssl::RSA_Pointer rsa(RSA_new());
-    if (!rsa)
+    if (EVP_PKEY_keygen_init(rsa.get()) <= 0)
         return nullptr;
 
     int num = 2048; // Maybe use 4096 RSA keys, or better make it configurable?
-    if (!RSA_generate_key_ex(rsa.get(), num, bn.get(), nullptr))
+    if (EVP_PKEY_CTX_set_rsa_keygen_bits(rsa.get(), num) <= 0)
         return nullptr;
 
-    if (!EVP_PKEY_assign_RSA(pkey.get(), (rsa.get())))
+    /* Generate key */
+    EVP_PKEY *pkey = nullptr;
+    if (EVP_PKEY_keygen(rsa.get(), &pkey) <= 0)
         return nullptr;
 
-    rsa.release();
-    return pkey.release();
+    return Security::PrivateKeyPointer(pkey);
 }
 
 /**
@@ -92,7 +85,7 @@ static bool setSerialNumber(ASN1_INTEGER *ai, BIGNUM const* serial)
         if (!bn)
             return false;
 
-        if (!BN_pseudo_rand(bn.get(), 64, 0, 0))
+        if (!BN_rand(bn.get(), 64, 0, 0))
             return false;
     }
 
@@ -421,7 +414,11 @@ mimicExtensions(Security::CertPointer & cert, Security::CertPointer const &mimic
     // XXX: Add PublicKeyPointer. In OpenSSL, public and private keys are
     // internally represented by EVP_PKEY pair, but GnuTLS uses distinct types.
     const Security::PrivateKeyPointer certKey(X509_get_pubkey(mimicCert.get()));
+#if OPENSSL_VERSION_MAJOR < 3
     const auto rsaPkey = EVP_PKEY_get0_RSA(certKey.get()) != nullptr;
+#else
+    const auto rsaPkey = EVP_PKEY_is_a(certKey.get(), "RSA") == 1;
+#endif
 
     int added = 0;
     int nid;
@@ -590,13 +587,8 @@ static bool buildCertificate(Security::CertPointer & cert, Ssl::CertificatePrope
 
 static bool generateFakeSslCertificate(Security::CertPointer & certToStore, Security::PrivateKeyPointer & pkeyToStore, Ssl::CertificateProperties const &properties,  Ssl::BIGNUM_Pointer const &serial)
 {
-    Security::PrivateKeyPointer pkey;
     // Use signing certificates private key as generated certificate private key
-    if (properties.signWithPkey.get())
-        pkey.resetAndLock(properties.signWithPkey.get());
-    else // if not exist generate one
-        pkey.resetWithoutLocking(Ssl::createSslPrivateKey());
-
+    const auto pkey = properties.signWithPkey ? properties.signWithPkey : CreateRsaPrivateKey();
     if (!pkey)
         return false;
 
index df45f5d3d0db62382a52dbfefd69205ac3d48c80..5be795744de3c26184e5febd596b6d3c61b52b89 100644 (file)
@@ -58,7 +58,7 @@ typedef std::unique_ptr<TXT_DB, HardFun<void, TXT_DB*, &TXT_DB_free>> TXT_DB_Poi
 
 typedef std::unique_ptr<X509_NAME, HardFun<void, X509_NAME*, &X509_NAME_free>> X509_NAME_Pointer;
 
-typedef std::unique_ptr<RSA, HardFun<void, RSA*, &RSA_free>> RSA_Pointer;
+using EVP_PKEY_CTX_Pointer = std::unique_ptr<EVP_PKEY_CTX, HardFun<void, EVP_PKEY_CTX*, &EVP_PKEY_CTX_free>>;
 
 typedef std::unique_ptr<X509_REQ, HardFun<void, X509_REQ*, &X509_REQ_free>> X509_REQ_Pointer;
 
@@ -86,12 +86,6 @@ void ForgetErrors();
 /// Also clears all reported errors.
 std::ostream &ReportAndForgetErrors(std::ostream &);
 
-/**
- \ingroup SslCrtdSslAPI
- * Create 1024 bits rsa key.
- */
-EVP_PKEY * createSslPrivateKey();
-
 /**
  \ingroup SslCrtdSslAPI
  * Write private key and SSL certificate to memory.
index 99c4087b688f55a7931f6980e60b174de3e19156..8e6dda270efc87e4a728c671c956998ebc4e16d6 100644 (file)
@@ -556,7 +556,11 @@ Ssl::VerifyCallbackParameters::At(Security::Connection &sconn)
 }
 
 // "dup" function for SSL_get_ex_new_index("cert_err_check")
-#if SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
+#if OPENSSL_VERSION_MAJOR >= 3
+static int
+ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void **,
+                    int, long, void *)
+#elif SQUID_USE_CONST_CRYPTO_EX_DATA_DUP
 static int
 ssl_dupAclChecklist(CRYPTO_EX_DATA *, const CRYPTO_EX_DATA *, void *,
                     int, long, void *)
@@ -653,8 +657,12 @@ Ssl::Initialize(void)
 
     SQUID_OPENSSL_init_ssl();
 
-#if !defined(OPENSSL_NO_ENGINE)
     if (::Config.SSL.ssl_engine) {
+#if OPENSSL_VERSION_MAJOR < 3
+    debugs(83, DBG_PARSE_NOTE(DBG_IMPORTANT), "WARNING: Support for ssl_engine is deprecated " <<
+           "in Squids built with OpenSSL v1 (like this Squid). " <<
+           "It is removed in Squids built with OpenSSL v3+.");
+#if !defined(OPENSSL_NO_ENGINE)
         ENGINE_load_builtin_engines();
         ENGINE *e;
         if (!(e = ENGINE_by_id(::Config.SSL.ssl_engine)))
@@ -664,11 +672,14 @@ Ssl::Initialize(void)
             const auto ssl_error = ERR_get_error();
             fatalf("Failed to initialise SSL engine: %s\n", Security::ErrorString(ssl_error));
         }
-    }
-#else
-    if (::Config.SSL.ssl_engine)
-        fatalf("Your OpenSSL has no SSL engine support\n");
+#else /* OPENSSL_NO_ENGINE */
+        throw TextException("Cannot use ssl_engine in Squid built with OpenSSL configured to disable SSL engine support", Here());
+#endif
+
+#else /* OPENSSL_VERSION_MAJOR */
+        throw TextException("Cannot use ssl_engine in Squid built with OpenSSL v3+", Here());
 #endif
+    }
 
     const char *defName = ::Config.SSL.certSignHash ? ::Config.SSL.certSignHash : SQUID_SSL_SIGN_HASH_IF_NONE;
     Ssl::DefaultSignHash = EVP_get_digestbyname(defName);