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. Pick-to: dev 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>
This commit is contained in:
parent
c2e7eaa009
commit
cdf4976b5a
@ -330,8 +330,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_ssl
|
||||
|
||||
qt_internal_extend_target(Network CONDITION QT_FEATURE_schannel AND QT_FEATURE_ssl
|
||||
SOURCES
|
||||
ssl/qssldiffiehellmanparameters_dummy.cpp
|
||||
ssl/qsslellipticcurve_dummy.cpp
|
||||
ssl/qsslsocket_qt.cpp
|
||||
ssl/qsslsocket_schannel.cpp ssl/qsslsocket_schannel_p.h
|
||||
ssl/qtlsbackend_schannel_p.h
|
||||
@ -347,8 +345,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_schannel AND QT_FEATURE_s
|
||||
|
||||
qt_internal_extend_target(Network CONDITION QT_FEATURE_securetransport AND QT_FEATURE_ssl
|
||||
SOURCES
|
||||
ssl/qssldiffiehellmanparameters_dummy.cpp
|
||||
ssl/qsslellipticcurve_dummy.cpp
|
||||
ssl/qsslsocket_mac.cpp ssl/qsslsocket_mac_p.h
|
||||
ssl/qsslsocket_mac_shared.cpp
|
||||
ssl/qsslsocket_qt.cpp
|
||||
@ -367,7 +363,6 @@ qt_internal_extend_target(Network CONDITION QT_FEATURE_openssl AND QT_FEATURE_ss
|
||||
SOURCES
|
||||
ssl/qsslcontext_openssl.cpp ssl/qsslcontext_openssl_p.h
|
||||
ssl/qssldiffiehellmanparameters_openssl.cpp
|
||||
ssl/qsslellipticcurve_openssl.cpp
|
||||
ssl/qsslsocket_openssl.cpp ssl/qsslsocket_openssl_p.h
|
||||
ssl/qsslsocket_openssl_symbols.cpp ssl/qsslsocket_openssl_symbols_p.h
|
||||
ssl/qtlskey_openssl.cpp ssl/qtlskey_openssl_p.h
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
|
||||
|
@ -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 initFromDer(const QByteArray &der);
|
||||
void initFromPem(const QByteArray &pem);
|
||||
|
||||
void decodeDer(const QByteArray &der);
|
||||
void decodePem(const QByteArray &pem);
|
||||
|
||||
QSslDiffieHellmanParameters::Error error;
|
||||
QSslDiffieHellmanParameters::Error error = QSslDiffieHellmanParameters::NoError;
|
||||
QByteArray derData;
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
||||
if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
|
||||
result.id = tlsBackend->curveIdFromShortName(name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QSslEllipticCurve QSslEllipticCurve::fromLongName(const QString &name)
|
||||
|
||||
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;
|
||||
|
||||
if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
|
||||
result.id = tlsBackend->curveIdFromLongName(name);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QString QSslEllipticCurve::shortName() const
|
||||
|
||||
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;
|
||||
|
||||
if (const auto *tlsBackend = QSslSocketPrivate::tlsBackendInUse())
|
||||
name = tlsBackend->shortNameForId(id);
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
/*!
|
||||
\fn QString QSslEllipticCurve::longName() const
|
||||
|
||||
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)
|
||||
|
@ -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
|
@ -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
|
@ -967,22 +967,22 @@ void QSslSocketPrivate::resetDefaultCiphers()
|
||||
|
||||
void QSslSocketPrivate::resetDefaultEllipticCurves()
|
||||
{
|
||||
// TLSTODO: this function to be be merged into qsslsocket.cpp
|
||||
const auto *tlsBackend = tlsBackendInUse();
|
||||
if (!tlsBackend)
|
||||
return;
|
||||
|
||||
auto ids = tlsBackend->ellipticCurvesIds();
|
||||
if (!ids.size())
|
||||
return;
|
||||
|
||||
QList<QSslEllipticCurve> curves;
|
||||
|
||||
#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) {
|
||||
curves.reserve(int(curveCount));
|
||||
for (size_t i = 0; i < curveCount; ++i) {
|
||||
QSslEllipticCurve curve;
|
||||
curve.id = builtinCurves[int(i)].nid;
|
||||
curves.append(curve);
|
||||
}
|
||||
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
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user