summaryrefslogtreecommitdiffstats
path: root/src/network/ssl
diff options
context:
space:
mode:
authorTimur Pocheptsov <timur.pocheptsov@qt.io>2021-02-23 11:40:50 +0100
committerTimur Pocheptsov <timur.pocheptsov@qt.io>2021-03-03 14:52:16 +0100
commitff76599b594d75c9f5a0d40ec598c8be355ba54f (patch)
tree2b714d8e217cd2137b9c289fa642c6b56a92dffa /src/network/ssl
parentafde5faf856078d34542da1d4d4db8a0237bfc67 (diff)
Convert elliptic curves and DH params to work with QTlsBackend
The corresponding API is becoming a part of QTlsBackend interface, since it's too minimalistic and does not require additional interfaces, unlike certificates or keys. Fixes: QTBUG-91177 Fixes: QTBUG-91175 Task-number: QTBUG-65922 Change-Id: I44dd0adbdf2427962451998664efe234d59fae24 Reviewed-by: Edward Welbourne <edward.welbourne@qt.io> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> (cherry picked from commit cdf4976b5a01bc5b65aed746acc9cc7f87b0fd97) Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
Diffstat (limited to 'src/network/ssl')
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters.cpp26
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_dummy.cpp57
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_openssl.cpp90
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters_p.h13
-rw-r--r--src/network/ssl/qsslellipticcurve.cpp60
-rw-r--r--src/network/ssl/qsslellipticcurve_dummy.cpp71
-rw-r--r--src/network/ssl/qsslellipticcurve_openssl.cpp177
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp26
-rw-r--r--src/network/ssl/qtlsbackend.cpp78
-rw-r--r--src/network/ssl/qtlsbackend_openssl.cpp129
-rw-r--r--src/network/ssl/qtlsbackend_openssl_p.h14
-rw-r--r--src/network/ssl/qtlsbackend_p.h22
12 files changed, 372 insertions, 391 deletions
diff --git a/src/network/ssl/qssldiffiehellmanparameters.cpp b/src/network/ssl/qssldiffiehellmanparameters.cpp
index e5574b2e09..bea0f26742 100644
--- a/src/network/ssl/qssldiffiehellmanparameters.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters.cpp
@@ -56,6 +56,7 @@
#include "qssldiffiehellmanparameters.h"
#include "qssldiffiehellmanparameters_p.h"
+#include "qtlsbackend_p.h"
#include "qsslsocket.h"
#include "qsslsocket_p.h"
@@ -117,12 +118,15 @@ QSslDiffieHellmanParameters::QSslDiffieHellmanParameters()
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(const QByteArray &encoded, QSsl::EncodingFormat encoding)
{
QSslDiffieHellmanParameters result;
+ const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse();
+ if (!tlsBackend)
+ return result;
switch (encoding) {
case QSsl::Der:
- result.d->decodeDer(encoded);
+ result.d->initFromDer(encoded);
break;
case QSsl::Pem:
- result.d->decodePem(encoded);
+ result.d->initFromPem(encoded);
break;
}
return result;
@@ -299,6 +303,24 @@ bool QSslDiffieHellmanParameters::isEqual(const QSslDiffieHellmanParameters &oth
return d->derData == other.d->derData;
}
+/*!
+ \internal
+*/
+void QSslDiffieHellmanParametersPrivate::initFromDer(const QByteArray &der)
+{
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ error = QSslDiffieHellmanParameters::Error(tlsBackend->dhParametersFromDer(der, &derData));
+}
+
+/*!
+ \internal
+*/
+void QSslDiffieHellmanParametersPrivate::initFromPem(const QByteArray &pem)
+{
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ error = QSslDiffieHellmanParameters::Error(tlsBackend->dhParametersFromPem(pem, &derData));
+}
+
#ifndef QT_NO_DEBUG_STREAM
/*!
\since 5.8
diff --git a/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp b/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp
deleted file mode 100644
index 8fcf141f73..0000000000
--- a/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp
+++ /dev/null
@@ -1,57 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-
-#include "qssldiffiehellmanparameters.h"
-#include "qssldiffiehellmanparameters_p.h"
-
-#include <QtCore/qglobal.h>
-#include <QtCore/qbytearray.h>
-
-QT_BEGIN_NAMESPACE
-
-void QSslDiffieHellmanParametersPrivate::decodeDer(const QByteArray &)
-{
-}
-
-void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &)
-{
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
index 05b3408b75..01dca50720 100644
--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
@@ -38,30 +38,25 @@
**
****************************************************************************/
-#include "qssldiffiehellmanparameters.h"
-#include "qssldiffiehellmanparameters_p.h"
#include "qsslsocket_openssl_symbols_p.h"
-#include "qsslsocket.h"
+#include "qtlsbackend_openssl_p.h"
#include "qsslsocket_p.h"
-#include "private/qssl_p.h"
-
-#include <QtCore/qatomic.h>
+#include <QtCore/qscopeguard.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qiodevice.h>
-#include <QtCore/qscopeguard.h>
-#ifndef QT_NO_DEBUG_STREAM
#include <QtCore/qdebug.h>
-#endif
#include <openssl/bn.h>
#include <openssl/dh.h>
QT_BEGIN_NAMESPACE
+namespace {
+
#ifdef OPENSSL_NO_DEPRECATED_3_0
-static int q_DH_check(DH *dh, int *status)
+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.
@@ -110,14 +105,15 @@ static int q_DH_check(DH *dh, int *status)
}
#endif // OPENSSL_NO_DEPRECATED_3_0
-static bool isSafeDH(DH *dh)
+bool isSafeDH(DH *dh)
{
int status = 0;
int bad = 0;
+ // TLSTODO: check it's needed or if supportsSsl()
+ // is enough.
QSslSocketPrivate::ensureInitialized();
-
// From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
//
// The additional call to BN_mod_word(dh->p, 24)
@@ -154,71 +150,81 @@ static bool isSafeDH(DH *dh)
return !(status & bad);
}
-void QSslDiffieHellmanParametersPrivate::decodeDer(const QByteArray &der)
+} // unnamed namespace
+
+int QTlsBackendOpenSSL::dhParametersFromDer(const QByteArray &der, QByteArray *derData) const
{
- if (der.isEmpty()) {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
- return;
- }
+ Q_ASSERT(derData);
+
+ if (der.isEmpty())
+ return DHParams::InvalidInputDataError;
const unsigned char *data = reinterpret_cast<const unsigned char *>(der.data());
- int len = der.size();
+ const int len = der.size();
+ // TLSTODO: check it's needed (loading ciphers and certs in
+ // addition to the library!)
QSslSocketPrivate::ensureInitialized();
DH *dh = q_d2i_DHparams(nullptr, &data, len);
if (dh) {
+ const auto dhRaii = qScopeGuard([dh] {q_DH_free(dh);});
+
if (isSafeDH(dh))
- derData = der;
+ *derData = der;
else
- error = QSslDiffieHellmanParameters::UnsafeParametersError;
+ return DHParams::UnsafeParametersError;
} else {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
+ return DHParams::InvalidInputDataError;
}
- q_DH_free(dh);
+ return DHParams::NoError;
}
-void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &pem)
+int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *data) const
{
- if (pem.isEmpty()) {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
- return;
- }
+ Q_ASSERT(data);
- if (!QSslSocket::supportsSsl()) {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
- return;
- }
+ if (pem.isEmpty())
+ return DHParams::InvalidInputDataError;
+ // TLSTODO: check it was not a cargo-cult programming in case of
+ // DH ...
QSslSocketPrivate::ensureInitialized();
BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pem.data()), pem.size());
- if (!bio) {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
- return;
- }
+ if (!bio)
+ return DHParams::InvalidInputDataError;
+
+ const auto bioRaii = qScopeGuard([bio]
+ {
+ q_BIO_free(bio);
+ });
DH *dh = nullptr;
q_PEM_read_bio_DHparams(bio, &dh, nullptr, nullptr);
if (dh) {
+ const auto dhGuard = qScopeGuard([dh]
+ {
+ q_DH_free(dh);
+ });
+
if (isSafeDH(dh)) {
char *buf = nullptr;
- int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf));
+ const int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf));
if (len > 0)
- derData = QByteArray(buf, len);
+ *data = QByteArray(buf, len);
else
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
+ return DHParams::InvalidInputDataError;
} else {
- error = QSslDiffieHellmanParameters::UnsafeParametersError;
+ return DHParams::UnsafeParametersError;
}
} else {
- error = QSslDiffieHellmanParameters::InvalidInputDataError;
+ return DHParams::InvalidInputDataError;
}
- q_DH_free(dh);
- q_BIO_free(bio);
+ return DHParams::NoError;
}
QT_END_NAMESPACE
diff --git a/src/network/ssl/qssldiffiehellmanparameters_p.h b/src/network/ssl/qssldiffiehellmanparameters_p.h
index 722c2e9cf0..6929d542cb 100644
--- a/src/network/ssl/qssldiffiehellmanparameters_p.h
+++ b/src/network/ssl/qssldiffiehellmanparameters_p.h
@@ -53,23 +53,20 @@
//
#include <QtNetwork/private/qtnetworkglobal_p.h>
-#include <QSharedData>
-#include "qsslkey.h"
#include "qssldiffiehellmanparameters.h"
-#include "qsslsocket_p.h" // includes wincrypt.h
+
+#include <QSharedData>
QT_BEGIN_NAMESPACE
class QSslDiffieHellmanParametersPrivate : public QSharedData
{
public:
- QSslDiffieHellmanParametersPrivate() : error(QSslDiffieHellmanParameters::NoError) {}
-
- void decodeDer(const QByteArray &der);
- void decodePem(const QByteArray &pem);
+ void initFromDer(const QByteArray &der);
+ void initFromPem(const QByteArray &pem);
- QSslDiffieHellmanParameters::Error error;
+ QSslDiffieHellmanParameters::Error error = QSslDiffieHellmanParameters::NoError;
QByteArray derData;
};
diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp
index 6bc5ee6286..7d1a911e67 100644
--- a/src/network/ssl/qsslellipticcurve.cpp
+++ b/src/network/ssl/qsslellipticcurve.cpp
@@ -38,6 +38,8 @@
****************************************************************************/
#include "qsslellipticcurve.h"
+#include "qtlsbackend_p.h"
+#include "qsslsocket_p.h"
#ifndef QT_NO_DEBUG_STREAM
#include <QDebug>
@@ -77,8 +79,6 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
-
Returns an QSslEllipticCurve instance representing the
named curve \a name. The \a name is the conventional short
name for the curve, as represented by RFC 4492 (for instance \c{secp521r1}),
@@ -91,10 +91,19 @@ QT_BEGIN_NAMESPACE
\sa shortName()
*/
+QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
+{
+ QSslEllipticCurve result;
+ if (name.isEmpty())
+ return result;
-/*!
- \fn QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ result.id = tlsBackend->curveIdFromShortName(name);
+ return result;
+}
+
+/*!
Returns an QSslEllipticCurve instance representing the named curve \a name.
The \a name is a long name for the curve, whose exact spelling depends on the
SSL implementation.
@@ -105,24 +114,49 @@ QT_BEGIN_NAMESPACE
\sa longName()
*/
+QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
+{
+ QSslEllipticCurve result;
+ if (name.isEmpty())
+ return result;
-/*!
- \fn QString QSslEllipticCurve::shortName() const
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ result.id = tlsBackend->curveIdFromLongName(name);
+
+ return result;
+}
+/*!
Returns the conventional short name for this curve. If this
curve is invalid, returns an empty string.
\sa longName()
*/
+QString QSslEllipticCurve::shortName() const
+{
+ QString name;
-/*!
- \fn QString QSslEllipticCurve::longName() const
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ name = tlsBackend->shortNameForId(id);
+ return name;
+}
+
+/*!
Returns the conventional long name for this curve. If this
curve is invalid, returns an empty string.
\sa shortName()
*/
+QString QSslEllipticCurve::longName() const
+{
+ QString name;
+
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ name = tlsBackend->longNameForId(id);
+
+ return name;
+}
/*!
\fn bool QSslEllipticCurve::isValid() const
@@ -131,12 +165,18 @@ QT_BEGIN_NAMESPACE
*/
/*!
- \fn bool QSslEllipticCurve::isTlsNamedCurve() const
-
Returns true if this elliptic curve is one of the named curves that can be
used in the key exchange when using an elliptic curve cipher with TLS;
false otherwise.
*/
+bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
+{
+ if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
+ return tlsBackend->isTlsNamedCurve(id);
+
+ return false;
+}
+
/*!
\fn bool QSslEllipticCurve::operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs)
diff --git a/src/network/ssl/qsslellipticcurve_dummy.cpp b/src/network/ssl/qsslellipticcurve_dummy.cpp
deleted file mode 100644
index 1313e06875..0000000000
--- a/src/network/ssl/qsslellipticcurve_dummy.cpp
+++ /dev/null
@@ -1,71 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Governikus GmbH & Co. KG.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsslellipticcurve.h"
-
-QT_BEGIN_NAMESPACE
-
-QString QSslEllipticCurve::shortName() const
-{
- return QString();
-}
-
-QString QSslEllipticCurve::longName() const
-{
- return QString();
-}
-
-QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
-{
- Q_UNUSED(name);
- return QSslEllipticCurve();
-}
-
-QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
-{
- Q_UNUSED(name);
- return QSslEllipticCurve();
-}
-
-bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
-{
- return false;
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp
deleted file mode 100644
index bb7ad66bd2..0000000000
--- a/src/network/ssl/qsslellipticcurve_openssl.cpp
+++ /dev/null
@@ -1,177 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Governikus GmbH & Co. KG.
-** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the QtNetwork module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qsslellipticcurve.h"
-#include "qsslsocket_p.h"
-#include "qsslsocket_openssl_symbols_p.h"
-
-#include <openssl/ssl.h>
-#include <openssl/obj_mac.h>
-
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-QString QSslEllipticCurve::shortName() const
-{
- QString result;
-#ifndef OPENSSL_NO_EC
- if (id != 0)
- result = QString::fromLatin1(q_OBJ_nid2sn(id));
-#endif
- return result;
-}
-
-QString QSslEllipticCurve::longName() const
-{
- QString result;
-#ifndef OPENSSL_NO_EC
- if (id != 0)
- result = QString::fromLatin1(q_OBJ_nid2ln(id));
-#endif
- return result;
-}
-
-QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
-{
- if (name.isEmpty())
- return QSslEllipticCurve();
-
- QSslSocketPrivate::ensureInitialized();
-
- QSslEllipticCurve result;
-
-#ifndef OPENSSL_NO_EC
-
- const QByteArray curveNameLatin1 = name.toLatin1();
- int nid = q_OBJ_sn2nid(curveNameLatin1.data());
-
- if (nid == 0)
- nid = q_EC_curve_nist2nid(curveNameLatin1.data());
-
- result.id = nid;
-
-#endif // !OPENSSL_NO_EC
-
- return result;
-}
-
-QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
-{
- if (name.isEmpty())
- return QSslEllipticCurve();
-
- QSslSocketPrivate::ensureInitialized();
-
- QSslEllipticCurve result;
-
-#ifndef OPENSSL_NO_EC
- const QByteArray curveNameLatin1 = name.toLatin1();
-
- int nid = q_OBJ_ln2nid(curveNameLatin1.data());
- result.id = nid;
-#endif
-
- return result;
-}
-
-
-// The brainpool curve NIDs (RFC 7027) have been introduced in OpenSSL 1.0.2,
-// redefine them here to make Qt compile with previous versions of OpenSSL
-// (yet correctly recognize them as TLS named curves).
-// See crypto/objects/obj_mac.h
-#ifndef NID_brainpoolP256r1
-#define NID_brainpoolP256r1 927
-#endif
-
-#ifndef NID_brainpoolP384r1
-#define NID_brainpoolP384r1 931
-#endif
-
-#ifndef NID_brainpoolP512r1
-#define NID_brainpoolP512r1 933
-#endif
-
-// NIDs of named curves allowed in TLS as per RFCs 4492 and 7027,
-// see also https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
-static const int tlsNamedCurveNIDs[] = {
- // RFC 4492
- NID_sect163k1,
- NID_sect163r1,
- NID_sect163r2,
- NID_sect193r1,
- NID_sect193r2,
- NID_sect233k1,
- NID_sect233r1,
- NID_sect239k1,
- NID_sect283k1,
- NID_sect283r1,
- NID_sect409k1,
- NID_sect409r1,
- NID_sect571k1,
- NID_sect571r1,
-
- NID_secp160k1,
- NID_secp160r1,
- NID_secp160r2,
- NID_secp192k1,
- NID_X9_62_prime192v1, // secp192r1
- NID_secp224k1,
- NID_secp224r1,
- NID_secp256k1,
- NID_X9_62_prime256v1, // secp256r1
- NID_secp384r1,
- NID_secp521r1,
-
- // RFC 7027
- NID_brainpoolP256r1,
- NID_brainpoolP384r1,
- NID_brainpoolP512r1
-};
-
-static const size_t tlsNamedCurveNIDCount = sizeof(tlsNamedCurveNIDs) / sizeof(tlsNamedCurveNIDs[0]);
-
-bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
-{
- const int * const tlsNamedCurveNIDsEnd = tlsNamedCurveNIDs + tlsNamedCurveNIDCount;
- return std::find(tlsNamedCurveNIDs, tlsNamedCurveNIDsEnd, id) != tlsNamedCurveNIDsEnd;
-}
-
-QT_END_NAMESPACE
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index fe59d6dab2..b9a8160e99 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -967,22 +967,22 @@ void QSslSocketPrivate::resetDefaultCiphers()
void QSslSocketPrivate::resetDefaultEllipticCurves()
{
- QList<QSslEllipticCurve> curves;
-
-#ifndef OPENSSL_NO_EC
- const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
+ // TLSTODO: this function to be be merged into qsslsocket.cpp
+ const auto *tlsBackend = tlsBackendInUse();
+ if (!tlsBackend)
+ return;
- QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
+ auto ids = tlsBackend->ellipticCurvesIds();
+ if (!ids.size())
+ return;
- if (q_EC_get_builtin_curves(builtinCurves.data(), curveCount) == curveCount) {
- curves.reserve(int(curveCount));
- for (size_t i = 0; i < curveCount; ++i) {
- QSslEllipticCurve curve;
- curve.id = builtinCurves[int(i)].nid;
- curves.append(curve);
- }
+ QList<QSslEllipticCurve> curves;
+ curves.reserve(ids.size());
+ for (int id : ids) {
+ QSslEllipticCurve curve;
+ curve.id = id;
+ curves.append(curve);
}
-#endif // OPENSSL_NO_EC
// set the list of supported ECs, but not the list
// of *default* ECs. OpenSSL doesn't like forcing an EC for the wrong
diff --git a/src/network/ssl/qtlsbackend.cpp b/src/network/ssl/qtlsbackend.cpp
index dcffb0afd1..c367766801 100644
--- a/src/network/ssl/qtlsbackend.cpp
+++ b/src/network/ssl/qtlsbackend.cpp
@@ -229,60 +229,120 @@ QString QTlsBackend::backendName() const
return QStringLiteral("dummyTLS");
}
+#define REPORT_MISSING_SUPPORT(message) \
+ qCWarning(lcSsl) << "The backend" << backendName() << message
+
QSsl::TlsKey *QTlsBackend::createKey() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot generate a key");
+ REPORT_MISSING_SUPPORT("does not support QSslKey");
return nullptr;
}
QSsl::X509Certificate *QTlsBackend::createCertificate() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot create a certificate");
+ REPORT_MISSING_SUPPORT("does not support QSslCertificate");
return nullptr;
}
QSsl::TlsCryptograph *QTlsBackend::createTlsCryptograph() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot create TLS session");
+ REPORT_MISSING_SUPPORT("does not support QSslSocket");
return nullptr;
}
QSsl::DtlsCryptograph *QTlsBackend::createDtlsCryptograph() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS session");
+ REPORT_MISSING_SUPPORT("does not support QDtls");
return nullptr;
}
QSsl::DtlsCookieVerifier *QTlsBackend::createDtlsCookieVerifier() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot create DTLS cookie generator/verifier");
+ REPORT_MISSING_SUPPORT("does not support DTLS cookies");
return nullptr;
}
QSsl::X509ChainVerifyPtr QTlsBackend::X509Verifier() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot verify X509 chain");
+ REPORT_MISSING_SUPPORT("does not support (manual) certificate verification");
return nullptr;
}
QSsl::X509PemReaderPtr QTlsBackend::X509PemReader() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot read PEM format");
+ REPORT_MISSING_SUPPORT("cannot read PEM format");
return nullptr;
}
QSsl::X509DerReaderPtr QTlsBackend::X509DerReader() const
{
- qCWarning(lcSsl, "Dummy TLS backend, don't know how to read DER");
+ REPORT_MISSING_SUPPORT("cannot read DER format");
return nullptr;
}
QSsl::X509Pkcs12ReaderPtr QTlsBackend::X509Pkcs12Reader() const
{
- qCWarning(lcSsl, "Dummy TLS backend, cannot read PKCS12");
+ REPORT_MISSING_SUPPORT("cannot read PKCS12 format");
return nullptr;
}
+QList<int> QTlsBackend::ellipticCurvesIds() const
+{
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return {};
+}
+
+int QTlsBackend::curveIdFromShortName(const QString &name) const
+{
+ Q_UNUSED(name);
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return 0;
+}
+
+int QTlsBackend::curveIdFromLongName(const QString &name) const
+{
+ Q_UNUSED(name);
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return 0;
+}
+
+QString QTlsBackend::shortNameForId(int cid) const
+{
+ Q_UNUSED(cid);
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return {};
+}
+
+QString QTlsBackend::longNameForId(int cid) const
+{
+ Q_UNUSED(cid);
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return {};
+}
+
+bool QTlsBackend::isTlsNamedCurve(int cid) const
+{
+ Q_UNUSED(cid);
+ REPORT_MISSING_SUPPORT("does not support QSslEllipticCurve");
+ return false;
+}
+
+int QTlsBackend::dhParametersFromDer(const QByteArray &derData, QByteArray *data) const
+{
+ Q_UNUSED(derData);
+ Q_UNUSED(data);
+ REPORT_MISSING_SUPPORT("does not support QSslDiffieHellmanParameters in DER format");
+ return {};
+}
+
+int QTlsBackend::dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const
+{
+ Q_UNUSED(pemData);
+ Q_UNUSED(data);
+ REPORT_MISSING_SUPPORT("does not support QSslDiffieHellmanParameters in PEM format");
+ return {};
+}
+
QList<QString> QTlsBackend::availableBackendNames()
{
if (!backends())
diff --git a/src/network/ssl/qtlsbackend_openssl.cpp b/src/network/ssl/qtlsbackend_openssl.cpp
index e288498820..b3686e15fa 100644
--- a/src/network/ssl/qtlsbackend_openssl.cpp
+++ b/src/network/ssl/qtlsbackend_openssl.cpp
@@ -51,6 +51,8 @@
#include <qlist.h>
+#include <algorithm>
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl");
@@ -181,4 +183,131 @@ QSsl::X509Pkcs12ReaderPtr QTlsBackendOpenSSL::X509Pkcs12Reader() const
return QSsl::X509CertificateOpenSSL::importPkcs12;
}
+QList<int> QTlsBackendOpenSSL::ellipticCurvesIds() const
+{
+ QList<int> ids;
+
+#ifndef OPENSSL_NO_EC
+ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
+ QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
+
+ if (q_EC_get_builtin_curves(builtinCurves.data(), curveCount) == curveCount) {
+ ids.reserve(curveCount);
+ for (const auto &ec : builtinCurves)
+ ids.push_back(ec.nid);
+ }
+#endif // OPENSSL_NO_EC
+
+ return ids;
+}
+
+ int QTlsBackendOpenSSL::curveIdFromShortName(const QString &name) const
+ {
+ int nid = 0;
+ if (name.isEmpty())
+ return nid;
+
+ // TLSTODO: check if it's needed! The fact we are here,
+ // means OpenSSL was loaded, symbols resolved. Is it because
+ // of ensureCiphers(AndCertificates)Loaded ?
+ QSslSocketPrivate::ensureInitialized();
+#ifndef OPENSSL_NO_EC
+ const QByteArray curveNameLatin1 = name.toLatin1();
+ nid = q_OBJ_sn2nid(curveNameLatin1.data());
+
+ if (nid == 0)
+ nid = q_EC_curve_nist2nid(curveNameLatin1.data());
+#endif // !OPENSSL_NO_EC
+
+ return nid;
+ }
+
+ int QTlsBackendOpenSSL::curveIdFromLongName(const QString &name) const
+ {
+ int nid = 0;
+ if (name.isEmpty())
+ return nid;
+
+ // TLSTODO: check if it's needed! The fact we are here,
+ // means OpenSSL was loaded, symbols resolved. Is it because
+ // of ensureCiphers(AndCertificates)Loaded ?
+ QSslSocketPrivate::ensureInitialized();
+
+#ifndef OPENSSL_NO_EC
+ const QByteArray curveNameLatin1 = name.toLatin1();
+ nid = q_OBJ_ln2nid(curveNameLatin1.data());
+#endif
+
+ return nid;
+ }
+
+ QString QTlsBackendOpenSSL::shortNameForId(int id) const
+ {
+ QString result;
+
+#ifndef OPENSSL_NO_EC
+ if (id != 0)
+ result = QString::fromLatin1(q_OBJ_nid2sn(id));
+#endif
+
+ return result;
+ }
+
+QString QTlsBackendOpenSSL::longNameForId(int id) const
+{
+ QString result;
+
+#ifndef OPENSSL_NO_EC
+ if (id != 0)
+ result = QString::fromLatin1(q_OBJ_nid2ln(id));
+#endif
+
+ return result;
+}
+
+// NIDs of named curves allowed in TLS as per RFCs 4492 and 7027,
+// see also https://www.iana.org/assignments/tls-parameters/tls-parameters.xhtml#tls-parameters-8
+static const int tlsNamedCurveNIDs[] = {
+ // RFC 4492
+ NID_sect163k1,
+ NID_sect163r1,
+ NID_sect163r2,
+ NID_sect193r1,
+ NID_sect193r2,
+ NID_sect233k1,
+ NID_sect233r1,
+ NID_sect239k1,
+ NID_sect283k1,
+ NID_sect283r1,
+ NID_sect409k1,
+ NID_sect409r1,
+ NID_sect571k1,
+ NID_sect571r1,
+
+ NID_secp160k1,
+ NID_secp160r1,
+ NID_secp160r2,
+ NID_secp192k1,
+ NID_X9_62_prime192v1, // secp192r1
+ NID_secp224k1,
+ NID_secp224r1,
+ NID_secp256k1,
+ NID_X9_62_prime256v1, // secp256r1
+ NID_secp384r1,
+ NID_secp521r1,
+
+ // RFC 7027
+ NID_brainpoolP256r1,
+ NID_brainpoolP384r1,
+ NID_brainpoolP512r1
+};
+
+const size_t tlsNamedCurveNIDCount = sizeof(tlsNamedCurveNIDs) / sizeof(tlsNamedCurveNIDs[0]);
+
+bool QTlsBackendOpenSSL::isTlsNamedCurve(int id) const
+{
+ const int *const tlsNamedCurveNIDsEnd = tlsNamedCurveNIDs + tlsNamedCurveNIDCount;
+ return std::find(tlsNamedCurveNIDs, tlsNamedCurveNIDsEnd, id) != tlsNamedCurveNIDsEnd;
+}
+
QT_END_NAMESPACE
diff --git a/src/network/ssl/qtlsbackend_openssl_p.h b/src/network/ssl/qtlsbackend_openssl_p.h
index 478e4762c2..b3c2b733a5 100644
--- a/src/network/ssl/qtlsbackend_openssl_p.h
+++ b/src/network/ssl/qtlsbackend_openssl_p.h
@@ -53,6 +53,7 @@
#include <private/qtnetworkglobal_p.h>
+#include "qssldiffiehellmanparameters.h"
#include "qtlsbackend_p.h"
#include <QtCore/qglobal.h>
@@ -83,6 +84,19 @@ private:
QSsl::X509PemReaderPtr X509PemReader() const override;
QSsl::X509DerReaderPtr X509DerReader() const override;
QSsl::X509Pkcs12ReaderPtr X509Pkcs12Reader() const override;
+
+ // Elliptic curves:
+ QList<int> ellipticCurvesIds() const override;
+ int curveIdFromShortName(const QString &name) const override;
+ int curveIdFromLongName(const QString &name) const override;
+ QString shortNameForId(int cid) const override;
+ QString longNameForId(int cid) const override;
+ bool isTlsNamedCurve(int cid) const override;
+
+ // DH parameters:
+ using DHParams = QSslDiffieHellmanParameters;
+ int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const override;
+ int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const override;
};
QT_END_NAMESPACE
diff --git a/src/network/ssl/qtlsbackend_p.h b/src/network/ssl/qtlsbackend_p.h
index d560288b5e..d91b3da548 100644
--- a/src/network/ssl/qtlsbackend_p.h
+++ b/src/network/ssl/qtlsbackend_p.h
@@ -68,7 +68,6 @@
#include <QtCore/qlist.h>
#include <QtCore/qmap.h>
-#include <vector>
#include <memory>
QT_BEGIN_NAMESPACE
@@ -168,6 +167,11 @@ public:
virtual size_t hash(size_t seed) const noexcept = 0;
};
+// TLSTODO: consider making those into virtuals in QTlsBackend. After all, we ask the backend
+// to return those pointers if the functionality is supported, but it's a bit odd to have
+// this level of indirection. They are not parts of the classes above because ...
+// you'd then have to ask backend to create a certificate to ... call those
+// functions on a certificate.
using X509ChainVerifyPtr = QList<QSslError> (*)(const QList<QSslCertificate> &chain,
const QString &hostName);
using X509PemReaderPtr = QList<QSslCertificate> (*)(const QByteArray &pem, int count);
@@ -212,12 +216,26 @@ public:
virtual QSsl::DtlsCryptograph *createDtlsCryptograph() const;
virtual QSsl::DtlsCookieVerifier *createDtlsCookieVerifier() const;
- // X509 machinery:
+ // TLSTODO - get rid of these function pointers, make them virtuals in
+ // the backend itself. X509 machinery:
virtual QSsl::X509ChainVerifyPtr X509Verifier() const;
virtual QSsl::X509PemReaderPtr X509PemReader() const;
virtual QSsl::X509DerReaderPtr X509DerReader() const;
virtual QSsl::X509Pkcs12ReaderPtr X509Pkcs12Reader() const;
+ // Elliptic curves:
+ virtual QList<int> ellipticCurvesIds() const;
+ virtual int curveIdFromShortName(const QString &name) const;
+ virtual int curveIdFromLongName(const QString &name) const;
+ virtual QString shortNameForId(int cid) const;
+ virtual QString longNameForId(int cid) const;
+ virtual bool isTlsNamedCurve(int cid) const;
+
+ // TLSTODO: int->enum ugliness in error reporting.
+ // DH decoding:
+ virtual int dhParametersFromDer(const QByteArray &derData, QByteArray *data) const;
+ virtual int dhParametersFromPem(const QByteArray &pemData, QByteArray *data) const;
+
static QList<QString> availableBackendNames();
static QString defaultBackendName();
static QTlsBackend *findBackend(const QString &backendName);