summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp19
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_openssl.cpp72
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp7
-rw-r--r--src/network/ssl/qsslsocket_openssl_p.h2
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols.cpp20
-rw-r--r--src/network/ssl/qsslsocket_openssl_symbols_p.h12
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);