Add settable QSslDiffieHellmanParameters for QSslSocket-based servers.

Only the OpenSSL backend is supported right now.

[ChangeLog][QtNetwork][SSL/TLS support] It is now possible to
set custom Diffie-Hellman parameters for QSslSocket-based servers.

Change-Id: I50148873132cd0ec7e414250b107b6b4cbde02ea
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
This commit is contained in:
Mikkel Krautz 2016-05-25 21:24:25 +02:00 committed by Timur Pocheptsov
parent 6d9f648d0e
commit 2cf63c71eb
17 changed files with 1082 additions and 24 deletions

View File

@ -214,6 +214,7 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const
d->ciphers == other.d->ciphers &&
d->ellipticCurves == other.d->ellipticCurves &&
d->ephemeralServerKey == other.d->ephemeralServerKey &&
d->dhParams == other.d->dhParams &&
d->caCertificates == other.d->caCertificates &&
d->protocol == other.d->protocol &&
d->peerVerifyMode == other.d->peerVerifyMode &&
@ -256,6 +257,7 @@ bool QSslConfiguration::isNull() const
d->ciphers.count() == 0 &&
d->ellipticCurves.isEmpty() &&
d->ephemeralServerKey.isNull() &&
d->dhParams == QSslDiffieHellmanParameters::defaultParameters() &&
d->localCertificateChain.isEmpty() &&
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
@ -839,6 +841,33 @@ void QSslConfiguration::setPreSharedKeyIdentityHint(const QByteArray &hint)
d->preSharedKeyIdentityHint = hint;
}
/*!
\since 5.8
Retrieves the current set of Diffie-Hellman parameters.
If no Diffie-Hellman parameters have been set, the QSslConfiguration object
defaults to using the 1024-bit MODP group from RFC 2409.
*/
QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const
{
return d->dhParams;
}
/*!
\since 5.8
Sets a custom set of Diffie-Hellman parameters to be used by this socket when functioning as
a server.
If no Diffie-Hellman parameters have been set, the QSslConfiguration object
defaults to using the 1024-bit MODP group from RFC 2409.
*/
void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams)
{
d->dhParams = dhparams;
}
/*!
\since 5.3

View File

@ -69,6 +69,7 @@ class QSslCertificate;
class QSslCipher;
class QSslKey;
class QSslEllipticCurve;
class QSslDiffieHellmanParameters;
class QSslConfigurationPrivate;
class Q_NETWORK_EXPORT QSslConfiguration
@ -144,6 +145,9 @@ public:
QByteArray preSharedKeyIdentityHint() const;
void setPreSharedKeyIdentityHint(const QByteArray &hint);
QSslDiffieHellmanParameters diffieHellmanParameters() const;
void setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams);
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);

View File

@ -73,6 +73,7 @@
#include "qsslcipher.h"
#include "qsslkey.h"
#include "qsslellipticcurve.h"
#include "qssldiffiehellmanparameters.h"
QT_BEGIN_NAMESPACE
@ -87,6 +88,7 @@ public:
allowRootCertOnDemandLoading(true),
peerSessionShared(false),
sslOptions(QSslConfigurationPrivate::defaultSslOptions),
dhParams(QSslDiffieHellmanParameters::defaultParameters()),
sslSessionTicketLifeTimeHint(-1),
ephemeralServerKey(),
preSharedKeyIdentityHint(),
@ -118,6 +120,8 @@ public:
QVector<QSslEllipticCurve> ellipticCurves;
QSslDiffieHellmanParameters dhParams;
QByteArray sslSession;
int sslSessionTicketLifeTimeHint;

View File

@ -41,6 +41,7 @@
#include <QtNetwork/qsslsocket.h>
#include <QtNetwork/qssldiffiehellmanparameters.h>
#include <QtCore/qmutex.h>
#include "private/qssl_p.h"
@ -48,6 +49,7 @@
#include "private/qsslsocket_p.h"
#include "private/qsslsocket_openssl_p.h"
#include "private/qsslsocket_openssl_symbols_p.h"
#include "private/qssldiffiehellmanparameters_p.h"
QT_BEGIN_NAMESPACE
@ -55,22 +57,6 @@ QT_BEGIN_NAMESPACE
extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
extern QString getErrorsFromOpenSsl();
static DH *get_dh1024()
{
// Default DH params
// 1024-bit MODP Group
// From RFC 2409
QByteArray params = QByteArray::fromBase64(
QByteArrayLiteral("MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR" \
"Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL" \
"/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC"));
const char *ptr = params.constData();
DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
return dh;
}
QSslContext::QSslContext()
: ctx(0),
pkey(0),
@ -325,10 +311,23 @@ init_context:
sslContext->setSessionASN1(configuration.sessionTicket());
// Set temp DH params
DH *dh = 0;
dh = get_dh1024();
q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
q_DH_free(dh);
QSslDiffieHellmanParameters dhparams = configuration.diffieHellmanParameters();
if (!dhparams.isValid()) {
sslContext->errorStr = QSslSocket::tr("Diffie-Hellman parameters are not valid");
sslContext->errorCode = QSslError::UnspecifiedError;
return;
}
if (!dhparams.isEmpty()) {
const QByteArray &params = dhparams.d.data()->derData;
const char *ptr = params.constData();
DH *dh = q_d2i_DHparams(NULL, reinterpret_cast<const unsigned char **>(&ptr), params.length());
if (dh == NULL)
qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form");
q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh);
q_DH_free(dh);
}
#ifndef OPENSSL_NO_EC
#if OPENSSL_VERSION_NUMBER >= 0x10002000L

View File

@ -0,0 +1,313 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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$
**
****************************************************************************/
/*!
\class QSslDiffieHellmanParameters
\brief The QSslDiffieHellmanParameters class provides an interface for Diffie-Hellman parameters for servers.
\since 5.8
\reentrant
\ingroup network
\ingroup ssl
\ingroup shared
\inmodule QtNetwork
QSslDiffieHellmanParameters provides an interface for setting Diffie-Hellman parameters to servers based on QSslSocket.
\sa QSslSocket, QSslCipher, QSslConfiguration
*/
#include "qssldiffiehellmanparameters.h"
#include "qssldiffiehellmanparameters_p.h"
#include "qsslsocket.h"
#include "qsslsocket_p.h"
#include <QtCore/qcoreapplication.h>
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qbytearraymatcher.h>
#include <QtCore/qiodevice.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
/*!
Returns the default QSslDiffieHellmanParameters used by QSslSocket.
This is currently the 1024-bit MODP group from RFC 2459, also
known as the Second Oakley Group.
*/
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::defaultParameters()
{
// The 1024-bit MODP group from RFC 2459 (Second Oakley Group)
return QSslDiffieHellmanParameters(
QByteArray::fromBase64(QByteArrayLiteral(
"MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR"
"Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL"
"/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC"
)),
QSsl::Der
);
}
/*!
Constructs an empty QSslDiffieHellmanParameters instance.
If an empty QSslDiffieHellmanParameters instance is set on a
QSslConfiguration object, Diffie-Hellman negotiation will
be disabled.
\sa isValid()
\sa QSslConfiguration
*/
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters()
: d(new QSslDiffieHellmanParametersPrivate)
{
}
/*!
Constructs a QSslDiffieHellmanParameters object using
the byte array \encoded in either PEM or DER form.
After construction, the isValid() method should be used to
check whether the Diffie-Hellman parameters were valid and
loaded correctly.
\sa isValid()
\sa QSslConfiguration
*/
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(const QByteArray &encoded, QSsl::EncodingFormat encoding)
: d(new QSslDiffieHellmanParametersPrivate)
{
switch (encoding) {
case QSsl::Der:
d->decodeDer(encoded);
break;
case QSsl::Pem:
d->decodePem(encoded);
break;
}
}
/*!
Constructs a QSslDiffieHellmanParameters object by
reading from \device in either PEM or DER form.
After construction, the isValid() method should be used
to check whether the Diffie-Hellman parameters were valid
and loaded correctly.
\sa isValid()
\sa QSslConfiguration
*/
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(QIODevice *device, QSsl::EncodingFormat encoding)
: d(new QSslDiffieHellmanParametersPrivate)
{
if (!device)
return;
const QByteArray encoded = device->readAll();
switch (encoding) {
case QSsl::Der:
d->decodeDer(encoded);
break;
case QSsl::Pem:
d->decodePem(encoded);
break;
}
}
/*!
Constructs an identical copy of \a other.
*/
QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other) : d(other.d)
{
}
/*!
Destroys the QSslDiffieHellmanParameters object.
*/
QSslDiffieHellmanParameters::~QSslDiffieHellmanParameters()
{
}
/*!
Copies the contents of \a other into this QSslDiffieHellmanParameters, making the two QSslDiffieHellmanParameters
identical.
Returns a reference to this QSslDiffieHellmanParameters.
*/
QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(const QSslDiffieHellmanParameters &other)
{
d = other.d;
return *this;
}
/*!
\fn QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(QSslDiffieHellmanParameters &&other)
Move-assigns \a other to this QSslDiffieHellmanParameters instance.
*/
/*!
\fn void QSslDiffieHellmanParameters::swap(QSslDiffieHellmanParameters &other)
Swaps this QSslDiffieHellmanParameters with \a other. This function is very fast and
never fails.
*/
/*!
Returns \c true if this is a an empty QSslDiffieHellmanParameters instance.
Setting an empty QSslDiffieHellmanParameters instance on a QSslSocket-based
server will disable Diffie-Hellman key exchange.
*/
bool QSslDiffieHellmanParameters::isEmpty() const Q_DECL_NOTHROW
{
return d->derData.isNull() && d->error == QSslDiffieHellmanParameters::NoError;
}
/*!
Returns \c true if this is a valid QSslDiffieHellmanParameters; otherwise false.
This method should be used after constructing a QSslDiffieHellmanParameters
object to determine its validity.
If a QSslDiffieHellmanParameters object is not valid, you can use the error()
method to determine what error prevented the object from being constructed.
\sa clear()
\sa error()
*/
bool QSslDiffieHellmanParameters::isValid() const Q_DECL_NOTHROW
{
return d->error == QSslDiffieHellmanParameters::NoError;
}
/*!
\enum QSslDiffieHellmanParameters::Error
Describes a QSslDiffieHellmanParameters error.
\value ErrorInvalidInputData The given input data could not be used to
construct a QSslDiffieHellmanParameters
object.
\value ErrorUnsafeParameters The Diffie-Hellman parameters are unsafe
and should not be used.
*/
/*!
Returns the error that caused the QSslDiffieHellmanParameters object
to be invalid.
*/
QSslDiffieHellmanParameters::Error QSslDiffieHellmanParameters::error() const Q_DECL_NOTHROW
{
return d->error;
}
/*!
Returns a human-readable description of the error that caused the
QSslDiffieHellmanParameters object to be invalid.
*/
QString QSslDiffieHellmanParameters::errorString() const Q_DECL_NOTHROW
{
switch (d->error) {
case QSslDiffieHellmanParameters::NoError:
return QCoreApplication::translate("QSslDiffieHellmanParameter", "No error");
case QSslDiffieHellmanParameters::InvalidInputDataError:
return QCoreApplication::translate("QSslDiffieHellmanParameter", "Invalid input data");
case QSslDiffieHellmanParameters::UnsafeParametersError:
return QCoreApplication::translate("QSslDiffieHellmanParameter", "The given Diffie-Hellman parameters are deemed unsafe");
}
Q_UNREACHABLE();
return QString();
}
/*!
\relates QSslDiffieHellmanParameters
Returns \c true if \a lhs is equal to \a rhs; otherwise returns \c false.
*/
bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW
{
return lhs.d->derData == rhs.d->derData;
}
/*! \fn bool QSslDiffieHellmanParameters::operator!=(const QSslDiffieHellmanParameters &other) const
Returns \c true if this QSslDiffieHellmanParameters is not equal to \a other; otherwise
returns \c false.
*/
#ifndef QT_NO_DEBUG_STREAM
/*!
\relates QSslDiffieHellmanParameters
Writes the set of Diffie-Hellman parameters in \a dhparm into the debug object \a debug for
debugging purposes.
The Diffie-Hellman parameters will be represented in Base64-encoded DER form.
\sa {Debugging Techniques}
*/
QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparam)
{
QDebugStateSaver saver(debug);
debug.resetFormat().nospace();
debug << "QSslDiffieHellmanParameters(" << dhparam.d->derData.toBase64() << ')';
return debug;
}
#endif
/*!
\relates QHash
Returns an hash value for \a dhparam, using \a seed to seed
the calculation.
*/
uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) Q_DECL_NOTHROW
{
return qHash(dhparam.d->derData, seed);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,117 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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$
**
****************************************************************************/
#ifndef QSSLDIFFIEHELLMANPARAMETERS_H
#define QSSLDIFFIEHELLMANPARAMETERS_H
#include <QtNetwork/qssl.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qshareddata.h>
QT_BEGIN_NAMESPACE
#ifndef QT_NO_SSL
class QIODevice;
class QSslContext;
class QSslDiffieHellmanParametersPrivate;
class QSslDiffieHellmanParameters;
// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed = 0) Q_DECL_NOTHROW;
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparams);
#endif
Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW;
inline bool operator!=(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW
{
return !operator==(lhs, rhs);
}
class QSslDiffieHellmanParameters
{
public:
enum Error {
NoError,
InvalidInputDataError,
UnsafeParametersError
};
Q_NETWORK_EXPORT static QSslDiffieHellmanParameters defaultParameters();
Q_NETWORK_EXPORT QSslDiffieHellmanParameters();
Q_NETWORK_EXPORT explicit QSslDiffieHellmanParameters(const QByteArray &encoded, QSsl::EncodingFormat format = QSsl::Pem);
Q_NETWORK_EXPORT explicit QSslDiffieHellmanParameters(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem);
Q_NETWORK_EXPORT QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other);
Q_NETWORK_EXPORT ~QSslDiffieHellmanParameters();
Q_NETWORK_EXPORT QSslDiffieHellmanParameters &operator=(const QSslDiffieHellmanParameters &other);
#ifdef Q_COMPILER_RVALUE_REFS
QSslDiffieHellmanParameters &operator=(QSslDiffieHellmanParameters &&other) Q_DECL_NOTHROW { swap(other); return *this; }
#endif
void swap(QSslDiffieHellmanParameters &other) Q_DECL_NOTHROW { qSwap(d, other.d); }
Q_NETWORK_EXPORT bool isEmpty() const Q_DECL_NOTHROW;
Q_NETWORK_EXPORT bool isValid() const Q_DECL_NOTHROW;
Q_NETWORK_EXPORT QSslDiffieHellmanParameters::Error error() const Q_DECL_NOTHROW;
Q_NETWORK_EXPORT QString errorString() const Q_DECL_NOTHROW;
private:
QExplicitlySharedDataPointer<QSslDiffieHellmanParametersPrivate> d;
friend class QSslContext;
friend Q_NETWORK_EXPORT bool operator==(const QSslDiffieHellmanParameters &lhs, const QSslDiffieHellmanParameters &rhs) Q_DECL_NOTHROW;
#ifndef QT_NO_DEBUG_STREAM
friend Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslDiffieHellmanParameters &dhparam);
#endif
friend Q_NETWORK_EXPORT uint qHash(const QSslDiffieHellmanParameters &dhparam, uint seed) Q_DECL_NOTHROW;
};
Q_DECLARE_SHARED(QSslDiffieHellmanParameters)
#endif // QT_NO_SSL
QT_END_NAMESPACE
#endif

View File

@ -0,0 +1,59 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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 &)
{
Q_UNIMPLEMENTED();
}
void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &)
{
Q_UNIMPLEMENTED();
}
QT_END_NAMESPACE

View File

@ -0,0 +1,164 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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 "qsslsocket_openssl_symbols_p.h"
#include "qsslsocket.h"
#include "qsslsocket_p.h"
#include <QtCore/qatomic.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qiodevice.h>
#ifndef QT_NO_DEBUG_STREAM
#include <QtCore/qdebug.h>
#endif
// For q_BN_is_word.
#include <openssl/bn.h>
QT_BEGIN_NAMESPACE
static bool isSafeDH(DH *dh)
{
int status = 0;
int bad = 0;
QSslSocketPrivate::ensureInitialized();
// 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;
// From https://wiki.openssl.org/index.php/Diffie-Hellman_parameters:
//
// The additional call to BN_mod_word(dh->p, 24)
// (and unmasking of DH_NOT_SUITABLE_GENERATOR)
// is performed to ensure your program accepts
// IETF group parameters. OpenSSL checks the prime
// is congruent to 11 when g = 2; while the IETF's
// primes are congruent to 23 when g = 2.
// 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 (q_BN_is_word(dh->g, DH_GENERATOR_2)) {
long residue = q_BN_mod_word(dh->p, 24);
if (residue == 11 || residue == 23)
status &= ~DH_NOT_SUITABLE_GENERATOR;
}
bad |= DH_CHECK_P_NOT_PRIME;
bad |= DH_CHECK_P_NOT_SAFE_PRIME;
bad |= DH_NOT_SUITABLE_GENERATOR;
return !(status & bad);
}
void QSslDiffieHellmanParametersPrivate::decodeDer(const QByteArray &der)
{
if (der.isEmpty()) {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
return;
}
const unsigned char *data = reinterpret_cast<const unsigned char *>(der.data());
int len = der.size();
QSslSocketPrivate::ensureInitialized();
DH *dh = q_d2i_DHparams(NULL, &data, len);
if (dh) {
if (isSafeDH(dh))
derData = der;
else
error = QSslDiffieHellmanParameters::UnsafeParametersError;
} else {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
}
q_DH_free(dh);
}
void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &pem)
{
if (pem.isEmpty()) {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
return;
}
if (!QSslSocket::supportsSsl()) {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
return;
}
QSslSocketPrivate::ensureInitialized();
BIO *bio = q_BIO_new_mem_buf(const_cast<char *>(pem.data()), pem.size());
if (!bio) {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
return;
}
DH *dh = Q_NULLPTR;
q_PEM_read_bio_DHparams(bio, &dh, 0, 0);
if (dh) {
if (isSafeDH(dh)) {
char *buf = Q_NULLPTR;
int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf));
if (len > 0)
derData = QByteArray(buf, len);
else
error = QSslDiffieHellmanParameters::InvalidInputDataError;
} else {
error = QSslDiffieHellmanParameters::UnsafeParametersError;
}
} else {
error = QSslDiffieHellmanParameters::InvalidInputDataError;
}
q_DH_free(dh);
q_BIO_free(bio);
}
QT_END_NAMESPACE

View File

@ -0,0 +1,78 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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$
**
****************************************************************************/
#ifndef QSSLDIFFIEHELLMANPARAMETERS_P_H
#define QSSLDIFFIEHELLMANPARAMETERS_P_H
#include "qsslkey.h"
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of qssldiffiehellmanparameters.cpp. This header file may change from version to version
// without notice, or even be removed.
//
// We mean it.
//
#include <QSharedData>
#include "qssldiffiehellmanparameters.h"
#include "qsslsocket_p.h" // includes wincrypt.h
QT_BEGIN_NAMESPACE
class QSslDiffieHellmanParametersPrivate : public QSharedData
{
public:
QSslDiffieHellmanParametersPrivate() : error(QSslDiffieHellmanParameters::NoError) {};
void decodeDer(const QByteArray &der);
void decodePem(const QByteArray &pem);
QSslDiffieHellmanParameters::Error error;
QByteArray derData;
};
QT_END_NAMESPACE
#endif // QSSLDIFFIEHELLMANPARAMETERS_P_H

View File

@ -916,6 +916,7 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration)
d->configuration.ciphers = configuration.ciphers();
d->configuration.ellipticCurves = configuration.ellipticCurves();
d->configuration.preSharedKeyIdentityHint = configuration.preSharedKeyIdentityHint();
d->configuration.dhParams = configuration.diffieHellmanParameters();
d->configuration.caCertificates = configuration.caCertificates();
d->configuration.peerVerifyDepth = configuration.peerVerifyDepth();
d->configuration.peerVerifyMode = configuration.peerVerifyMode();

View File

@ -151,6 +151,10 @@ DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, return)
DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
DEFINEFUNC3(int, BIO_write, BIO *a, a, const void *b, b, int c, c, return -1, return)
DEFINEFUNC(int, BN_num_bits, const BIGNUM *a, a, return 0, return)
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
#endif
DEFINEFUNC2(BN_ULONG, BN_mod_word, const BIGNUM *a, a, BN_ULONG w, w, return -1, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return 0, return)
DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return)
@ -207,6 +211,7 @@ DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_passwo
#ifndef OPENSSL_NO_EC
DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
#endif
DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return 0, return)
DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return)
#ifndef OPENSSL_NO_EC
@ -436,6 +441,8 @@ DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char *
DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return 0, 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 0, return)
DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return)
DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return)
DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return 0, return)
#ifndef OPENSSL_NO_EC
DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return 0, return)
@ -782,6 +789,10 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(EC_GROUP_get_degree)
#endif
RESOLVEFUNC(BN_num_bits)
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
RESOLVEFUNC(BN_is_word)
#endif
RESOLVEFUNC(BN_mod_word)
RESOLVEFUNC(CRYPTO_free)
RESOLVEFUNC(CRYPTO_num_locks)
RESOLVEFUNC(CRYPTO_set_id_callback)
@ -830,6 +841,7 @@ bool q_resolveOpenSslSymbols()
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(PEM_read_bio_ECPrivateKey)
#endif
RESOLVEFUNC(PEM_read_bio_DHparams)
RESOLVEFUNC(PEM_write_bio_DSAPrivateKey)
RESOLVEFUNC(PEM_write_bio_RSAPrivateKey)
#ifndef OPENSSL_NO_EC
@ -991,6 +1003,8 @@ bool q_resolveOpenSslSymbols()
RESOLVEFUNC(DH_new)
RESOLVEFUNC(DH_free)
RESOLVEFUNC(d2i_DHparams)
RESOLVEFUNC(i2d_DHparams)
RESOLVEFUNC(DH_check)
RESOLVEFUNC(BN_bin2bn)
#ifndef OPENSSL_NO_EC
RESOLVEFUNC(EC_KEY_dup)

View File

@ -227,6 +227,21 @@ int q_BIO_read(BIO *a, void *b, int c);
BIO_METHOD *q_BIO_s_mem();
int q_BIO_write(BIO *a, const void *b, int c);
int q_BN_num_bits(const BIGNUM *a);
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
int q_BN_is_word(BIGNUM *a, BN_ULONG w);
#else
// BN_is_word is implemented purely as a
// macro in OpenSSL < 1.1. It doesn't
// call any functions.
//
// The implementation of BN_is_word is
// 100% the same between 1.0.0, 1.0.1
// and 1.0.2.
//
// Users are required to include <openssl/bn.h>.
#define q_BN_is_word BN_is_word
#endif // OPENSSL_VERSION_NUMBER >= 0x10100000L
BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
#ifndef OPENSSL_NO_EC
const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
int q_EC_GROUP_get_degree(const EC_GROUP* g);
@ -284,6 +299,7 @@ RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d);
#ifndef OPENSSL_NO_EC
EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d);
#endif
DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d);
int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d,
int e, pem_password_cb *f, void *g);
int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d,
@ -475,6 +491,8 @@ STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
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);
int q_DH_check(DH *dh, int *codes);
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)
@ -521,6 +539,9 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
#define q_PEM_write_bio_DSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_DSAPrivateKey,PEM_STRING_DSA,\
bp,(char *)x,enc,kstr,klen,cb,u)
#define q_PEM_read_bio_DHparams(bp, dh, cb, u) \
(DH *)q_PEM_ASN1_read_bio( \
(void *(*)(void**, const unsigned char**, long int))q_d2i_DHparams, PEM_STRING_DHPARAMS, bp, (void **)x, cb, u)
#endif
#define q_SSL_CTX_set_options(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
#define q_SSL_CTX_set_mode(ctx,op) q_SSL_CTX_ctrl((ctx),SSL_CTRL_MODE,(op),NULL)

View File

@ -9,6 +9,8 @@ contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, op
ssl/qsslconfiguration_p.h \
ssl/qsslcipher.h \
ssl/qsslcipher_p.h \
ssl/qssldiffiehellmanparameters.h \
ssl/qssldiffiehellmanparameters_p.h \
ssl/qsslellipticcurve.h \
ssl/qsslerror.h \
ssl/qsslkey.h \
@ -24,6 +26,7 @@ contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, op
ssl/qsslcertificate.cpp \
ssl/qsslconfiguration.cpp \
ssl/qsslcipher.cpp \
ssl/qssldiffiehellmanparameters.cpp \
ssl/qsslellipticcurve.cpp \
ssl/qsslkey_p.cpp \
ssl/qsslerror.cpp \
@ -35,6 +38,7 @@ contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, op
HEADERS += ssl/qsslsocket_winrt_p.h
SOURCES += ssl/qsslcertificate_qt.cpp \
ssl/qsslcertificate_winrt.cpp \
ssl/qssldiffiehellmanparameters_dummy.cpp \
ssl/qsslkey_qt.cpp \
ssl/qsslkey_winrt.cpp \
ssl/qsslsocket_winrt.cpp \
@ -44,6 +48,7 @@ contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, op
contains(QT_CONFIG, securetransport) {
HEADERS += ssl/qsslsocket_mac_p.h
SOURCES += ssl/qsslcertificate_qt.cpp \
ssl/qssldiffiehellmanparameters_dummy.cpp \
ssl/qsslkey_qt.cpp \
ssl/qsslkey_mac.cpp \
ssl/qsslsocket_mac_shared.cpp \
@ -58,6 +63,7 @@ contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) {
ssl/qsslsocket_openssl_symbols_p.h
SOURCES += ssl/qsslcertificate_openssl.cpp \
ssl/qsslcontext_openssl.cpp \
ssl/qssldiffiehellmanparameters_openssl.cpp \
ssl/qsslellipticcurve_openssl.cpp \
ssl/qsslkey_openssl.cpp \
ssl/qsslsocket_openssl.cpp \

View File

@ -0,0 +1,8 @@
CONFIG += testcase
CONFIG += parallel_test
SOURCES += tst_qssldiffiehellmanparameters.cpp
!wince*:win32:LIBS += -lws2_32
QT = core network testlib
TARGET = tst_qssldiffiehellmanparameters

View File

@ -0,0 +1,157 @@
/****************************************************************************
**
** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
** Contact: http://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 <QtTest/QtTest>
#include <QSslDiffieHellmanParameters>
#include <QSslSocket>
#include <QByteArray>
class tst_QSslDiffieHellmanParameters : public QObject
{
Q_OBJECT
private Q_SLOTS:
void constructionEmpty();
void constructionDefault();
void constructionDER();
void constructionPEM();
void unsafe512Bits();
void unsafeNonPrime();
};
void tst_QSslDiffieHellmanParameters::constructionEmpty()
{
QSslDiffieHellmanParameters dh;
QCOMPARE(dh.isEmpty(), true);
QCOMPARE(dh.isValid(), true);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError);
}
void tst_QSslDiffieHellmanParameters::constructionDefault()
{
QSslDiffieHellmanParameters dh = QSslDiffieHellmanParameters::defaultParameters();
#ifndef QT_NO_OPENSSL
QCOMPARE(dh.isValid(), true);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError);
#endif
}
void tst_QSslDiffieHellmanParameters::constructionDER()
{
// Uniquely generated with 'openssl dhparam -outform DER -out out.der -check -2 4096'
QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral(
"MIICCAKCAgEAsbQYx57ZlyEyWF8jD5WYEswGR2aTVFsHqP3026SdyTwcjY+YlMOae0EagK"
"jDA0UlPcih1kguQOvOVgyc5gI3YbBb4pCNEdy048xITlsdqG7qC3+2VvFR3vfixEbQQll9"
"2cGIIneD/36p7KJcDnBNUwwWj/VJKhTwelTfKTj2T39si9xGMkqZiQuCaXRk6vSKZ4ZDPk"
"jiq5Ti1kHVFbL9SMWRa8zplPtDMrVfhSyw10njgD4qKd1UoUPdmhEPhRZlHaZ/cAHNSHMj"
"uhDakeMpN+XP2/sl5IpPZ3/vVOk9PhBDFO1NYzKx/b7RQgZCUmXoglKYpfBiz8OheoI0hK"
"V0fU/OCtHjRrP4hE9vIHA2aE+gaQZiYCciGcR9BjHQ7Y8K9qHyTX8UIz2G4ZKzQZK9G+pA"
"K0xD+1H3qZ/MaUhzNDQOwwihnTjjXzTjfIGqYDdbouAhw+tX51CsGonI0cL3s3QMa3CwGH"
"mw+AH2b/Z68dTSy0sC3CYn9cNbrctqyeHwQrsx9FfpOz+Z6sk2WsPgqgSp/pDVVgm5oSfO"
"2mN7WAWgUlf9TQuj1HIRCTI+PbBq2vYvn+YResMRo+8ng1QptKAAgQoVVGNRYxZ9iAZlvO"
"52DcHKlsqDuafQ1XVGmzVIrKtBi2gfLtPqY4v6g6v26l8gbzK67PpWstllHiPb4VMCAQI="
)), QSsl::Der);
#ifndef QT_NO_OPENSSL
QCOMPARE(dh.isValid(), true);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError);
#endif
}
void tst_QSslDiffieHellmanParameters::constructionPEM()
{
// Uniquely generated with 'openssl dhparam -outform PEM -out out.pem -check -2 4096'
QSslDiffieHellmanParameters dh(QByteArrayLiteral(
"-----BEGIN DH PARAMETERS-----\n"
"MIICCAKCAgEA9QTdqhQkbGuhWzBsW5X475AjjrITpg1BHX5+mp1sstUd84Lshq1T\n"
"+S2QQQtdl25EPoUblpyyLAf8krFSH4YwR7jjLWklA8paDOwRYod0zLmVZ1Wx6og3\n"
"PRc8P+SCs+6gKTXfv//bJJhiJXnM73lDFsGHbSqN+msf20ei/zy5Rwey2t8dPjLC\n"
"Q+qkb/avlovi2t2rsUWcxMT1875TQ4HuApayqw3R3lTQe9u05b9rTrinmT7AE4mm\n"
"xGqO9FZJdXYE2sOKwwJkpM48KFyV90uJANmqJnQrkgdukaGTHwxZxgAyO6ur/RWC\n"
"kzf9STFT6IY4Qy05q+oZVJfh8xPHszKmmC8nWaLfiHMYBnL5fv+1kh/aU11Kz9TG\n"
"iDXwQ+tzhKAutQPUwe3IGQUYQMZPwZI4vegdU88/7YPXuWt7b/0Il5+2ma5FbtG2\n"
"u02PMi+J3JZsYi/tEUv1tJBVHGH0kDpgcyOm8rvkCtNbNkETzfwUPoEgA0oPMhVt\n"
"sFGub1av+jLRyFNGNBJcqXAO+Tq2zXG00DxbGY+aooJ50qU/Lh5gfnCEMDXlMM9P\n"
"T8JVpWaaNLCC+0Z5txsfYp+FO8mOttIPIF6F8FtmTnm/jhNntvqKvsU+NHylIYzr\n"
"o42EpiWwS7ktPPUS2GtG+IUdy8rvdO1xJ5kNxs7ZlygY4W1htOhbUusCAQI=\n"
"-----END DH PARAMETERS-----\n"
), QSsl::Pem);
#ifndef QT_NO_OPENSSL
QCOMPARE(dh.isValid(), true);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::NoError);
#endif
}
void tst_QSslDiffieHellmanParameters::unsafe512Bits()
{
// Uniquely generated with 'openssl dhparam -outform PEM -out out.pem -check -2 512'
QSslDiffieHellmanParameters dh(QByteArrayLiteral(
"-----BEGIN DH PARAMETERS-----\n"
"MEYCQQCf8goDn56akiliAtEL1ZG7VH+9wfLxsv8/B1emTUG+rMKB1yaVAU7HaAiM\n"
"Gtmo2bAWUqBczUTOTzqmWTm28P6bAgEC\n"
"-----END DH PARAMETERS-----\n"
), QSsl::Pem);
#ifndef QT_NO_OPENSSL
QCOMPARE(dh.isValid(), false);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::UnsafeParametersError);
#endif
}
void tst_QSslDiffieHellmanParameters::unsafeNonPrime()
{
// Uniquely generated with 'openssl dhparam -outform DER -out out.der -check -2 1024'
// and then modified by hand to make P not be a prime number.
QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral(
"MIGHAoGBALLcOLg+ow8TMnbCUeNjwys6wUTIH9mn4ZSeIbD6qvCsJgg4cUxXwJQmPY"
"Xl15AsKXgkXWh0n+/N6tjH0sSRJnzDvN2H3KxFLKkvxmBYrDOJMdCuMgZD50aOsVyd"
"vholAW9zilkoYkB6sqwxY1Z2dbpTWajCsUAWZQ0AIP4Y5nesAgEC"
)), QSsl::Der);
#ifndef QT_NO_OPENSSL
QCOMPARE(dh.isValid(), false);
QCOMPARE(dh.error(), QSslDiffieHellmanParameters::UnsafeParametersError);
#endif
}
QTEST_MAIN(tst_QSslDiffieHellmanParameters)
#include "tst_qssldiffiehellmanparameters.moc"

View File

@ -219,6 +219,10 @@ private slots:
void qtbug18498_peek();
void qtbug18498_peek2();
void dhServer();
#ifndef QT_NO_OPENSSL
void dhServerCustomParamsNull();
void dhServerCustomParams();
#endif
void ecdhServer();
void verifyClientCertificate_data();
void verifyClientCertificate();
@ -2819,10 +2823,8 @@ void tst_QSslSocket::qtbug18498_peek2()
void tst_QSslSocket::dhServer()
{
if (!QSslSocket::supportsSsl()) {
qWarning("SSL not supported, skipping test");
return;
}
if (!QSslSocket::supportsSsl())
QSKIP("No SSL support");
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
@ -2847,6 +2849,87 @@ void tst_QSslSocket::dhServer()
QCOMPARE(client->state(), QAbstractSocket::ConnectedState);
}
#ifndef QT_NO_OPENSSL
void tst_QSslSocket::dhServerCustomParamsNull()
{
if (!QSslSocket::supportsSsl())
QSKIP("No SSL support");
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
SslServer server;
server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
QSslConfiguration cfg = server.config;
cfg.setDiffieHellmanParameters(QSslDiffieHellmanParameters());
server.config = cfg;
QVERIFY(server.listen());
QEventLoop loop;
QTimer::singleShot(5000, &loop, SLOT(quit()));
QSslSocketPtr client(new QSslSocket);
socket = client.data();
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit()));
client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
loop.exec();
QVERIFY(client->state() != QAbstractSocket::ConnectedState);
}
#endif // QT_NO_OPENSSL
#ifndef QT_NO_OPENSSL
void tst_QSslSocket::dhServerCustomParams()
{
if (!QSslSocket::supportsSsl())
QSKIP("No SSL support");
QFETCH_GLOBAL(bool, setProxy);
if (setProxy)
return;
SslServer server;
server.ciphers = QLatin1String("DHE-RSA-AES256-SHA:DHE-DSS-AES256-SHA");
QSslConfiguration cfg = server.config;
// Custom 2048-bit DH parameters generated with 'openssl dhparam -outform DER -out out.der -check -2 2048'
QSslDiffieHellmanParameters dh(QByteArray::fromBase64(QByteArrayLiteral(
"MIIBCAKCAQEAvVA7b8keTfjFutCtTJmP/pnQfw/prKa+GMed/pBWjrC4N1YwnI8h/A861d9WE/VWY7XMTjvjX3/0"
"aaU8wEe0EXNpFdlTH+ZMQctQTSJOyQH0RCTwJfDGPCPT9L+c9GKwEKWORH38Earip986HJc0w3UbnfIwXUdsWHiXi"
"Z6r3cpyBmTKlsXTFiDVAOUXSiO8d/zOb6zHZbDfyB/VbtZRmnA7TXVn9oMzC0g9+FXHdrV4K+XfdvNZdCegvoAZiy"
"R6ZQgNG9aZ36/AQekhg060hp55f9HDPgXqYeNeXBiferjUtU7S9b3s83XhOJAr01/0Tf5dENwCfg2gK36TM8cC4wI"
"BAg==")), QSsl::Der);
cfg.setDiffieHellmanParameters(dh);
server.config = cfg;
QVERIFY(server.listen());
QEventLoop loop;
QTimer::singleShot(5000, &loop, SLOT(quit()));
QSslSocketPtr client(new QSslSocket);
socket = client.data();
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit()));
connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot()));
connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit()));
client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort());
loop.exec();
QVERIFY(client->state() == QAbstractSocket::ConnectedState);
}
#endif // QT_NO_OPENSSL
void tst_QSslSocket::ecdhServer()
{
if (!QSslSocket::supportsSsl()) {

View File

@ -2,6 +2,7 @@ TEMPLATE=subdirs
SUBDIRS=\
qsslcertificate \
qsslcipher \
qssldiffiehellmanparameters \
qsslellipticcurve \
qsslerror \
qsslkey \