diff options
-rw-r--r-- | src/network/ssl/qsslcontext_openssl.cpp | 19 | ||||
-rw-r--r-- | src/network/ssl/qssldiffiehellmanparameters_openssl.cpp | 72 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl.cpp | 7 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_p.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols.cpp | 20 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols_p.h | 12 |
6 files changed, 112 insertions, 20 deletions
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index 78e37460c8..c59666e2f2 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -508,8 +508,23 @@ init_context: if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) { // tell OpenSSL the directories where to look up the root certs on demand const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories(); - for (const QByteArray &unixDir : unixDirs) - q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData()); + int success = 1; +#if OPENSSL_VERSION_MAJOR < 3 + for (const QByteArray &unixDir : unixDirs) { + if ((success = q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData())) != 1) + break; + } +#else + for (const QByteArray &unixDir : unixDirs) { + if ((success = q_SSL_CTX_load_verify_dir(sslContext->ctx, unixDir.constData())) != 1) + break; + } +#endif // OPENSSL_VERSION_MAJOR + if (success != 1) { + const auto qtErrors = QSslSocketBackendPrivate::getErrorsFromOpenSsl(); + qCWarning(lcSsl) << "An error encountered while to set root certificates location:" + << qtErrors; + } } if (!sslContext->sslConfiguration.localCertificate().isNull()) { diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp index c36482329a..aaf8741130 100644 --- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp +++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp @@ -44,9 +44,12 @@ #include "qsslsocket.h" #include "qsslsocket_p.h" +#include "private/qssl_p.h" + #include <QtCore/qatomic.h> #include <QtCore/qbytearray.h> #include <QtCore/qiodevice.h> +#include <QtCore/qscopeguard.h> #ifndef QT_NO_DEBUG_STREAM #include <QtCore/qdebug.h> #endif @@ -56,6 +59,57 @@ QT_BEGIN_NAMESPACE +#ifdef OPENSSL_NO_DEPRECATED_3_0 + +static int q_DH_check(DH *dh, int *status) +{ + // DH_check was first deprecated in OpenSSL 3.0.0, as low-level + // API; the EVP_PKEY family of functions was advised as an alternative. + // As of now EVP_PKEY_params_check ends up calling ... DH_check, + // which is good enough. + + Q_ASSERT(dh); + Q_ASSERT(status); + + EVP_PKEY *key = q_EVP_PKEY_new(); + if (!key) { + qCWarning(lcSsl, "EVP_PKEY_new failed"); + QSslSocketBackendPrivate::logAndClearErrorQueue(); + return 0; + } + const auto keyDeleter = qScopeGuard([key](){ + q_EVP_PKEY_free(key); + }); + if (!q_EVP_PKEY_set1_DH(key, dh)) { + qCWarning(lcSsl, "EVP_PKEY_set1_DH failed"); + QSslSocketBackendPrivate::logAndClearErrorQueue(); + return 0; + } + + EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); + if (!keyCtx) { + qCWarning(lcSsl, "EVP_PKEY_CTX_new failed"); + QSslSocketBackendPrivate::logAndClearErrorQueue(); + return 0; + } + const auto ctxDeleter = qScopeGuard([keyCtx]{ + q_EVP_PKEY_CTX_free(keyCtx); + }); + + const int result = q_EVP_PKEY_param_check(keyCtx); + QSslSocketBackendPrivate::logAndClearErrorQueue(); + // Note: unlike DH_check, we cannot obtain the 'status', + // if the 'result' is 0 (actually the result is 1 only + // if this 'status' was 0). We could probably check the + // errors from the error queue, but it's not needed anyway + // - see the 'isSafeDH' below, how it returns immediately + // on 0. + Q_UNUSED(status) + + return result; +} +#endif // OPENSSL_NO_DEPRECATED_3_0 + static bool isSafeDH(DH *dh) { int status = 0; @@ -75,7 +129,6 @@ static bool isSafeDH(DH *dh) // Without the test, the IETF parameters would // fail validation. For details, see Diffie-Hellman // Parameter Check (when g = 2, must p mod 24 == 11?). -#if QT_CONFIG(opensslv11) // Mark p < 1024 bits as unsafe. if (q_DH_bits(dh) < 1024) return false; @@ -89,25 +142,10 @@ static bool isSafeDH(DH *dh) q_DH_get0_pqg(dh, &p, &q, &g); if (q_BN_is_word(const_cast<BIGNUM *>(g), DH_GENERATOR_2)) { - long residue = q_BN_mod_word(p, 24); - if (residue == 11 || residue == 23) - status &= ~DH_NOT_SUITABLE_GENERATOR; - } - -#else - // Mark p < 1024 bits as unsafe. - if (q_BN_num_bits(dh->p) < 1024) - return false; - - if (q_DH_check(dh, &status) != 1) - return false; - - if (q_BN_is_word(dh->g, DH_GENERATOR_2)) { - long residue = q_BN_mod_word(dh->p, 24); + const unsigned long residue = q_BN_mod_word(p, 24); if (residue == 11 || residue == 23) status &= ~DH_NOT_SUITABLE_GENERATOR; } -#endif bad |= DH_CHECK_P_NOT_PRIME; bad |= DH_CHECK_P_NOT_SAFE_PRIME; diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index b6570e2bdd..324ca6eea6 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -236,6 +236,13 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl() return errorString; } +void QSslSocketBackendPrivate::logAndClearErrorQueue() +{ + const auto errors = getErrorsFromOpenSsl(); + if (errors.size()) + qCWarning(lcSsl) << "Discarding errors:" << errors; +} + extern "C" { #ifndef OPENSSL_NO_PSK diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 6c1ffb7237..04feec9f45 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -182,11 +182,11 @@ public: static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509); static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName); static QString getErrorsFromOpenSsl(); + static void logAndClearErrorQueue(); static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, QList<QSslCertificate> *caCertificates, const QByteArray &passPhrase); - static QString msgErrorsDuringHandshake(); }; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index 777dc70565..6ba8ba9db0 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -145,6 +145,9 @@ DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return nullptr, return DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return) DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return) DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) +DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) +DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, return) DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) @@ -436,7 +439,13 @@ DEFINEFUNC(X509_STORE *, X509_STORE_CTX_get0_store, X509_STORE_CTX *ctx, ctx, re DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC2(void *, X509_STORE_CTX_get_ex_data, X509_STORE_CTX *ctx, ctx, int idx, idx, return nullptr, return) DEFINEFUNC(int, SSL_get_ex_data_X509_STORE_CTX_idx, DUMMYARG, DUMMYARG, return -1, return) + +#if OPENSSL_VERSION_MAJOR < 3 DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return) +#else +DEFINEFUNC2(int, SSL_CTX_load_verify_dir, SSL_CTX *ctx, ctx, const char *CApath, CApath, return 0, return) +#endif // OPENSSL_VERSION_MAJOR + DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return) DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) @@ -482,7 +491,9 @@ DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) +#ifndef OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) +#endif // OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) #ifndef OPENSSL_NO_EC @@ -836,6 +847,9 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ASN1_STRING_get0_data) RESOLVEFUNC(EVP_CIPHER_CTX_reset) RESOLVEFUNC(EVP_PKEY_up_ref) + RESOLVEFUNC(EVP_PKEY_CTX_new) + RESOLVEFUNC(EVP_PKEY_param_check) + RESOLVEFUNC(EVP_PKEY_CTX_free) RESOLVEFUNC(EVP_PKEY_base_id) RESOLVEFUNC(RSA_bits) RESOLVEFUNC(OPENSSL_sk_new_null) @@ -1132,7 +1146,11 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(X509_verify_cert) RESOLVEFUNC(d2i_X509) RESOLVEFUNC(i2d_X509) +#if OPENSSL_VERSION_MAJOR < 3 RESOLVEFUNC(SSL_CTX_load_verify_locations) +#else + RESOLVEFUNC(SSL_CTX_load_verify_dir) +#endif // OPENSSL_VERSION_MAJOR RESOLVEFUNC(i2d_SSL_SESSION) RESOLVEFUNC(d2i_SSL_SESSION) @@ -1157,7 +1175,9 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(DH_free) RESOLVEFUNC(d2i_DHparams) RESOLVEFUNC(i2d_DHparams) +#ifndef OPENSSL_NO_DEPRECATED_3_0 RESOLVEFUNC(DH_check) +#endif // OPENSSL_NO_DEPRECATED_3_0 RESOLVEFUNC(BN_bin2bn) #ifndef OPENSSL_NO_EC diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index 78b097fad6..481c1ce0c7 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -233,6 +233,9 @@ Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem(); int q_DSA_bits(DSA *a); int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); Q_AUTOTEST_EXPORT int q_EVP_PKEY_up_ref(EVP_PKEY *a); +EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); +void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); +int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); int q_EVP_PKEY_base_id(EVP_PKEY *a); int q_RSA_bits(RSA *a); Q_AUTOTEST_EXPORT int q_OPENSSL_sk_num(OPENSSL_STACK *a); @@ -578,7 +581,10 @@ DH *q_DH_new(); void q_DH_free(DH *dh); DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); int q_i2d_DHparams(DH *a, unsigned char **p); + +#ifndef OPENSSL_NO_DEPRECATED_3_0 int q_DH_check(DH *dh, int *codes); +#endif // OPENSSL_NO_DEPRECATED_3_0 BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) @@ -621,7 +627,13 @@ void q_GENERAL_NAME_free(GENERAL_NAME *a); #define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\ (char *)(dsa)) #define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf() + +#if OPENSSL_VERSION_MAJOR < 3 int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath); +#else +int q_SSL_CTX_load_verify_dir(SSL_CTX *ctx, const char *CApath); +#endif // OPENSSL_VERSION_MAJOR + int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp); SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length); |