diff options
Diffstat (limited to 'src/network/ssl')
39 files changed, 1108 insertions, 282 deletions
diff --git a/src/network/ssl/qasn1element_p.h b/src/network/ssl/qasn1element_p.h index c636351bf9..f532cec530 100644 --- a/src/network/ssl/qasn1element_p.h +++ b/src/network/ssl/qasn1element_p.h @@ -52,6 +52,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/qdatetime.h> #include <QtCore/qmap.h> diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h index 7742844246..c2a468c97c 100644 --- a/src/network/ssl/qssl.h +++ b/src/network/ssl/qssl.h @@ -41,7 +41,7 @@ #ifndef QSSL_H #define QSSL_H -#include <QtCore/qglobal.h> +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/QFlags> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qssl_p.h b/src/network/ssl/qssl_p.h index 85eb59ae35..83ccdc7fc3 100644 --- a/src/network/ssl/qssl_p.h +++ b/src/network/ssl/qssl_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/QLoggingCategory> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h index 814c6a701d..8b051a5c88 100644 --- a/src/network/ssl/qsslcertificate.h +++ b/src/network/ssl/qsslcertificate.h @@ -45,6 +45,7 @@ #undef verify #endif +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qnamespace.h> #include <QtCore/qbytearray.h> #include <QtCore/qcryptographichash.h> diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h index 8b83f754e4..616b5aec6d 100644 --- a/src/network/ssl/qsslcertificate_p.h +++ b/src/network/ssl/qsslcertificate_p.h @@ -41,6 +41,7 @@ #ifndef QSSLCERTIFICATE_OPENSSL_P_H #define QSSLCERTIFICATE_OPENSSL_P_H +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslcertificate.h" // diff --git a/src/network/ssl/qsslcertificateextension.h b/src/network/ssl/qsslcertificateextension.h index 795dd0ce80..2ce2112687 100644 --- a/src/network/ssl/qsslcertificateextension.h +++ b/src/network/ssl/qsslcertificateextension.h @@ -40,6 +40,7 @@ #ifndef QSSLCERTIFICATEEXTENSION_H #define QSSLCERTIFICATEEXTENSION_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qnamespace.h> #include <QtCore/qshareddata.h> #include <QtCore/qstring.h> diff --git a/src/network/ssl/qsslcertificateextension_p.h b/src/network/ssl/qsslcertificateextension_p.h index a7ff53d4a3..373f92a5cf 100644 --- a/src/network/ssl/qsslcertificateextension_p.h +++ b/src/network/ssl/qsslcertificateextension_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslcertificateextension.h" QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslcipher.h b/src/network/ssl/qsslcipher.h index 8bb404ffa7..c6328e0169 100644 --- a/src/network/ssl/qsslcipher.h +++ b/src/network/ssl/qsslcipher.h @@ -41,6 +41,7 @@ #ifndef QSSLCIPHER_H #define QSSLCIPHER_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qstring.h> #include <QtCore/qscopedpointer.h> #include <QtNetwork/qssl.h> diff --git a/src/network/ssl/qsslcipher_p.h b/src/network/ssl/qsslcipher_p.h index 1714617361..b8629f9f96 100644 --- a/src/network/ssl/qsslcipher_p.h +++ b/src/network/ssl/qsslcipher_p.h @@ -40,6 +40,7 @@ #ifndef QSSLCIPHER_P_H #define QSSLCIPHER_P_H +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslcipher.h" QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp index c8040dec7f..75a880f115 100644 --- a/src/network/ssl/qsslconfiguration.cpp +++ b/src/network/ssl/qsslconfiguration.cpp @@ -53,6 +53,7 @@ const QSsl::SslOptions QSslConfigurationPrivate::defaultSslOptions = QSsl::SslOp |QSsl::SslOptionDisableCompression |QSsl::SslOptionDisableSessionPersistence; +const char QSslConfiguration::ALPNProtocolHTTP2[] = "h2"; const char QSslConfiguration::NextProtocolSpdy3_0[] = "spdy/3"; const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1"; @@ -119,7 +120,8 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1"; /*! \enum QSslConfiguration::NextProtocolNegotiationStatus - Describes the status of the Next Protocol Negotiation (NPN). + Describes the status of the Next Protocol Negotiation (NPN) or + Application-Layer Protocol Negotiation (ALPN). \value NextProtocolNegotiationNone No application protocol has been negotiated (yet). @@ -209,9 +211,11 @@ bool QSslConfiguration::operator==(const QSslConfiguration &other) const d->privateKey == other.d->privateKey && d->sessionCipher == other.d->sessionCipher && d->sessionProtocol == other.d->sessionProtocol && + d->preSharedKeyIdentityHint == other.d->preSharedKeyIdentityHint && 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 && @@ -254,6 +258,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() && @@ -261,6 +266,7 @@ bool QSslConfiguration::isNull() const d->sslOptions == QSslConfigurationPrivate::defaultSslOptions && d->sslSession.isNull() && d->sslSessionTicketLifeTimeHint == -1 && + d->preSharedKeyIdentityHint.isNull() && d->nextAllowedProtocols.isEmpty() && d->nextNegotiatedProtocol.isNull() && d->nextProtocolNegotiationStatus == QSslConfiguration::NextProtocolNegotiationNone); @@ -811,11 +817,65 @@ QVector<QSslEllipticCurve> QSslConfiguration::supportedEllipticCurves() } /*! + \since 5.8 + + Returns the identity hint. + + \sa setPreSharedKeyIdentityHint() +*/ +QByteArray QSslConfiguration::preSharedKeyIdentityHint() const +{ + return d->preSharedKeyIdentityHint; +} + +/*! + \since 5.8 + + Sets the identity hint for a preshared key authentication to \a hint. This will + affect the next initiated handshake; calling this function on an already-encrypted + socket will not affect the socket's identity hint. + + The identity hint is used in QSslSocket::SslServerMode only! +*/ +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 to \a dhparams. + + 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 This function returns the protocol negotiated with the server - if the Next Protocol Negotiation (NPN) TLS extension was enabled. - In order for the NPN extension to be enabled, setAllowedNextProtocols() + if the Next Protocol Negotiation (NPN) or Application-Layer Protocol + Negotiation (ALPN) TLS extension was enabled. + In order for the NPN/ALPN extension to be enabled, setAllowedNextProtocols() needs to be called explicitly before connecting to the server. If no protocol could be negotiated or the extension was not enabled, @@ -832,9 +892,10 @@ QByteArray QSslConfiguration::nextNegotiatedProtocol() const \since 5.3 This function sets the allowed \a protocols to be negotiated with the - server through the Next Protocol Negotiation (NPN) TLS extension; each + server through the Next Protocol Negotiation (NPN) or Application-Layer + Protocol Negotiation (ALPN) TLS extension; each element in \a protocols must define one allowed protocol. - The function must be called explicitly before connecting to send the NPN + The function must be called explicitly before connecting to send the NPN/ALPN extension in the SSL handshake. Whether or not the negotiation succeeded can be queried through nextProtocolNegotiationStatus(). @@ -854,8 +915,8 @@ void QSslConfiguration::setAllowedNextProtocols(QList<QByteArray> protocols) \since 5.3 This function returns the allowed protocols to be negotiated with the - server through the Next Protocol Negotiation (NPN) TLS extension, as set - by setAllowedNextProtocols(). + server through the Next Protocol Negotiation (NPN) or Application-Layer + Protocol Negotiation (ALPN) TLS extension, as set by setAllowedNextProtocols(). \sa nextNegotiatedProtocol(), nextProtocolNegotiationStatus(), setAllowedNextProtocols(), QSslConfiguration::NextProtocolSpdy3_0, QSslConfiguration::NextProtocolHttp1_1 */ @@ -867,7 +928,8 @@ QList<QByteArray> QSslConfiguration::allowedNextProtocols() const /*! \since 5.3 - This function returns the status of the Next Protocol Negotiation (NPN). + This function returns the status of the Next Protocol Negotiation (NPN) + or Application-Layer Protocol Negotiation (ALPN). If the feature has not been enabled through setAllowedNextProtocols(), this function returns NextProtocolNegotiationNone. The status will be set before emitting the encrypted() signal. diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h index f0754d7ef5..1c57bebd65 100644 --- a/src/network/ssl/qsslconfiguration.h +++ b/src/network/ssl/qsslconfiguration.h @@ -56,6 +56,7 @@ #ifndef QSSLCONFIGURATION_H #define QSSLCONFIGURATION_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qshareddata.h> #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qssl.h> @@ -69,6 +70,7 @@ class QSslCertificate; class QSslCipher; class QSslKey; class QSslEllipticCurve; +class QSslDiffieHellmanParameters; class QSslConfigurationPrivate; class Q_NETWORK_EXPORT QSslConfiguration @@ -141,6 +143,12 @@ public: void setEllipticCurves(const QVector<QSslEllipticCurve> &curves); static QVector<QSslEllipticCurve> supportedEllipticCurves(); + 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); @@ -160,6 +168,7 @@ public: QByteArray nextNegotiatedProtocol() const; NextProtocolNegotiationStatus nextProtocolNegotiationStatus() const; + static const char ALPNProtocolHTTP2[]; static const char NextProtocolSpdy3_0[]; static const char NextProtocolHttp1_1[]; diff --git a/src/network/ssl/qsslconfiguration_p.h b/src/network/ssl/qsslconfiguration_p.h index 364bba92ec..6adf2c9b54 100644 --- a/src/network/ssl/qsslconfiguration_p.h +++ b/src/network/ssl/qsslconfiguration_p.h @@ -67,12 +67,14 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslconfiguration.h" #include "qlist.h" #include "qsslcertificate.h" #include "qsslcipher.h" #include "qsslkey.h" #include "qsslellipticcurve.h" +#include "qssldiffiehellmanparameters.h" QT_BEGIN_NAMESPACE @@ -87,8 +89,10 @@ public: allowRootCertOnDemandLoading(true), peerSessionShared(false), sslOptions(QSslConfigurationPrivate::defaultSslOptions), + dhParams(QSslDiffieHellmanParameters::defaultParameters()), sslSessionTicketLifeTimeHint(-1), ephemeralServerKey(), + preSharedKeyIdentityHint(), nextProtocolNegotiationStatus(QSslConfiguration::NextProtocolNegotiationNone) { } @@ -117,11 +121,15 @@ public: QVector<QSslEllipticCurve> ellipticCurves; + QSslDiffieHellmanParameters dhParams; + QByteArray sslSession; int sslSessionTicketLifeTimeHint; QSslKey ephemeralServerKey; + QByteArray preSharedKeyIdentityHint; + QList<QByteArray> nextAllowedProtocols; QByteArray nextNegotiatedProtocol; QSslConfiguration::NextProtocolNegotiationStatus nextProtocolNegotiationStatus; diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp index f132d0228c..c92d8fc3f8 100644 --- a/src/network/ssl/qsslcontext_openssl.cpp +++ b/src/network/ssl/qsslcontext_openssl.cpp @@ -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 ¶ms = dhparams.d->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 @@ -345,6 +344,11 @@ init_context: } #endif // OPENSSL_NO_EC +#if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) + if (!client) + q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData()); +#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) + const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves(); if (!qcurves.isEmpty()) { #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC) @@ -458,6 +462,23 @@ SSL* QSslContext::createSsl() m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); m_npnContext.len = m_supportedNPNVersions.count(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (q_SSLeay() >= 0x10002000L) { + // Callback's type has a parameter 'const unsigned char ** out' + // since it was introduced in 1.0.2. Internally, OpenSSL's own code + // (tests/examples) cast it to unsigned char * (since it's 'out'). + // We just re-use our NPN callback and cast here: + typedef int (*alpn_callback_t) (SSL *, const unsigned char **, unsigned char *, + const unsigned char *, unsigned int, void *); + // With ALPN callback is for a server side only, for a client m_npnContext.status + // will stay in NextProtocolNegotiationNone. + q_SSL_CTX_set_alpn_select_cb(ctx, alpn_callback_t(next_proto_cb), &m_npnContext); + // Client: + q_SSL_set_alpn_protos(ssl, m_npnContext.data, m_npnContext.len); + } +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... + + // And in case our peer does not support ALPN, but supports NPN: q_SSL_CTX_set_next_proto_select_cb(ctx, next_proto_cb, &m_npnContext); } #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... diff --git a/src/network/ssl/qsslcontext_openssl_p.h b/src/network/ssl/qsslcontext_openssl_p.h index ef4dc6f815..06a31af5e5 100644 --- a/src/network/ssl/qsslcontext_openssl_p.h +++ b/src/network/ssl/qsslcontext_openssl_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/qvariant.h> #include <QtNetwork/qsslcertificate.h> #include <QtNetwork/qsslconfiguration.h> diff --git a/src/network/ssl/qssldiffiehellmanparameters.cpp b/src/network/ssl/qssldiffiehellmanparameters.cpp new file mode 100644 index 0000000000..d0fcb3189a --- /dev/null +++ b/src/network/ssl/qssldiffiehellmanparameters.cpp @@ -0,0 +1,324 @@ +/**************************************************************************** +** +** 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 fromEncoded( + 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) +{ + d->ref.ref(); +} + +/*! + Constructs a QSslDiffieHellmanParameters object using + the byte array \a encoded in either PEM or DER form as specified by \a encoding. + + Use the isValid() method on the returned object to + check whether the Diffie-Hellman parameters were valid and + loaded correctly. + + \sa isValid() + \sa QSslConfiguration +*/ +QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(const QByteArray &encoded, QSsl::EncodingFormat encoding) +{ + QSslDiffieHellmanParameters result; + switch (encoding) { + case QSsl::Der: + result.d->decodeDer(encoded); + break; + case QSsl::Pem: + result.d->decodePem(encoded); + break; + } + return result; +} + +/*! + Constructs a QSslDiffieHellmanParameters object by + reading from \a device in either PEM or DER form as specified by \a encoding. + + Use the isValid() method on the returned object + to check whether the Diffie-Hellman parameters were valid + and loaded correctly. + + In particular, if \a device is \c nullptr or not open for reading, an invalid + object will be returned. + + \sa isValid() + \sa QSslConfiguration +*/ +QSslDiffieHellmanParameters QSslDiffieHellmanParameters::fromEncoded(QIODevice *device, QSsl::EncodingFormat encoding) +{ + if (device) + return fromEncoded(device->readAll(), encoding); + else + return QSslDiffieHellmanParameters(); +} + +/*! + Constructs an identical copy of \a other. +*/ +QSslDiffieHellmanParameters::QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other) + : d(other.d) +{ + if (d) + d->ref.ref(); +} + +/*! + \fn QSslDiffieHellmanParameters(QSslDiffieHellmanParameters &&other) + + Move-constructs from \a other. + + \note The moved-from object \a other is placed in a partially-formed state, in which + the only valid operations are destruction and assignment of a new value. +*/ + +/*! + Destroys the QSslDiffieHellmanParameters object. +*/ +QSslDiffieHellmanParameters::~QSslDiffieHellmanParameters() +{ + if (d && !d->ref.deref()) + delete d; +} + +/*! + 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) +{ + QSslDiffieHellmanParameters copy(other); + swap(copy); + return *this; +} + +/*! + \fn QSslDiffieHellmanParameters &QSslDiffieHellmanParameters::operator=(QSslDiffieHellmanParameters &&other) + + Move-assigns \a other to this QSslDiffieHellmanParameters instance. + + \note The moved-from object \a other is placed in a partially-formed state, in which + the only valid operations are destruction and assignment of a new value. +*/ + +/*! + \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 error() +*/ +bool QSslDiffieHellmanParameters::isValid() const Q_DECL_NOTHROW +{ + return d->error == QSslDiffieHellmanParameters::NoError; +} + +/*! + \enum QSslDiffieHellmanParameters::Error + + Describes a QSslDiffieHellmanParameters error. + + \value NoError No error occurred. + + \value InvalidInputDataError The given input data could not be used to + construct a QSslDiffieHellmanParameters + object. + + \value UnsafeParametersError 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(); +} + +/*! + \since 5.8 + \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; +} + +#ifndef QT_NO_DEBUG_STREAM +/*! + \since 5.8 + \relates QSslDiffieHellmanParameters + + Writes the set of Diffie-Hellman parameters in \a dhparam 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 + +/*! + \since 5.8 + \relates QSslDiffieHellmanParameters + + 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 diff --git a/src/network/ssl/qssldiffiehellmanparameters.h b/src/network/ssl/qssldiffiehellmanparameters.h new file mode 100644 index 0000000000..4533ea4ed2 --- /dev/null +++ b/src/network/ssl/qssldiffiehellmanparameters.h @@ -0,0 +1,118 @@ +/**************************************************************************** +** +** 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 QSslDiffieHellmanParameters(const QSslDiffieHellmanParameters &other); + QSslDiffieHellmanParameters(QSslDiffieHellmanParameters &&other) Q_DECL_NOTHROW : d(other.d) { other.d = nullptr; } + Q_NETWORK_EXPORT ~QSslDiffieHellmanParameters(); + + Q_NETWORK_EXPORT QSslDiffieHellmanParameters &operator=(const QSslDiffieHellmanParameters &other); + QSslDiffieHellmanParameters &operator=(QSslDiffieHellmanParameters &&other) Q_DECL_NOTHROW { swap(other); return *this; } + + void swap(QSslDiffieHellmanParameters &other) Q_DECL_NOTHROW { qSwap(d, other.d); } + + Q_NETWORK_EXPORT static QSslDiffieHellmanParameters fromEncoded(const QByteArray &encoded, QSsl::EncodingFormat format = QSsl::Pem); + Q_NETWORK_EXPORT static QSslDiffieHellmanParameters fromEncoded(QIODevice *device, QSsl::EncodingFormat format = QSsl::Pem); + + Q_NETWORK_EXPORT bool isEmpty() const Q_DECL_NOTHROW; + Q_NETWORK_EXPORT bool isValid() const Q_DECL_NOTHROW; + Q_NETWORK_EXPORT Error error() const Q_DECL_NOTHROW; + Q_NETWORK_EXPORT QString errorString() const Q_DECL_NOTHROW; + +private: + 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 diff --git a/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp b/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp new file mode 100644 index 0000000000..220c017f4c --- /dev/null +++ b/src/network/ssl/qssldiffiehellmanparameters_dummy.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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 &) +{ +} + +void QSslDiffieHellmanParametersPrivate::decodePem(const QByteArray &) +{ +} + +QT_END_NAMESPACE diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp new file mode 100644 index 0000000000..949da1b7df --- /dev/null +++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp @@ -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 diff --git a/src/network/ssl/qssldiffiehellmanparameters_p.h b/src/network/ssl/qssldiffiehellmanparameters_p.h new file mode 100644 index 0000000000..06ecf292ff --- /dev/null +++ b/src/network/ssl/qssldiffiehellmanparameters_p.h @@ -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 + +// +// 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 <QtNetwork/private/qtnetworkglobal_p.h> +#include <QSharedData> + +#include "qsslkey.h" +#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 diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h index 6ee66d1ec1..0e7cc60e31 100644 --- a/src/network/ssl/qsslellipticcurve.h +++ b/src/network/ssl/qsslellipticcurve.h @@ -40,7 +40,7 @@ #ifndef QSSLELLIPTICCURVE_H #define QSSLELLIPTICCURVE_H -#include <QtCore/QtGlobal> +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/QString> #include <QtCore/QMetaType> #if QT_DEPRECATED_SINCE(5, 6) diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h index 82db2e58e4..d7c959423d 100644 --- a/src/network/ssl/qsslerror.h +++ b/src/network/ssl/qsslerror.h @@ -41,6 +41,7 @@ #ifndef QSSLERROR_H #define QSSLERROR_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qvariant.h> #include <QtNetwork/qsslcertificate.h> diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h index 39c3659fb8..6de02b1e44 100644 --- a/src/network/ssl/qsslkey.h +++ b/src/network/ssl/qsslkey.h @@ -41,6 +41,7 @@ #ifndef QSSLKEY_H #define QSSLKEY_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qnamespace.h> #include <QtCore/qbytearray.h> #include <QtCore/qsharedpointer.h> diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index 34f664093c..e66ec953a0 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -56,6 +56,9 @@ #include "qsslkey.h" #include "qsslkey_p.h" +#ifndef QT_NO_OPENSSL +#include "qsslsocket_openssl_symbols_p.h" +#endif #include "qsslsocket.h" #include "qsslsocket_p.h" @@ -277,18 +280,23 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding \a type specifies whether the key is public or private. QSslKey will take ownership for this key and you must not - free the key using the native library. The algorithm used - when creating a key from a handle will always be QSsl::Opaque. + free the key using the native library. */ QSslKey::QSslKey(Qt::HANDLE handle, QSsl::KeyType type) : d(new QSslKeyPrivate) { #ifndef QT_NO_OPENSSL - d->opaque = reinterpret_cast<EVP_PKEY *>(handle); + EVP_PKEY *evpKey = reinterpret_cast<EVP_PKEY *>(handle); + if (!evpKey || !d->fromEVP_PKEY(evpKey)) { + d->opaque = evpKey; + d->algorithm = QSsl::Opaque; + } else { + q_EVP_PKEY_free(evpKey); + } #else d->opaque = handle; -#endif d->algorithm = QSsl::Opaque; +#endif d->type = type; d->isNull = !d->opaque; } diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h index c17183a059..c93941c198 100644 --- a/src/network/ssl/qsslkey_p.h +++ b/src/network/ssl/qsslkey_p.h @@ -41,8 +41,6 @@ #ifndef QSSLKEY_OPENSSL_P_H #define QSSLKEY_OPENSSL_P_H -#include "qsslkey.h" - // // W A R N I N G // ------------- @@ -54,6 +52,8 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> +#include "qsslkey.h" #include "qsslsocket_p.h" // includes wincrypt.h #ifndef QT_NO_OPENSSL diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h index f34a2cee75..a012ff489a 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator.h @@ -40,7 +40,7 @@ #ifndef QSSLPRESHAREDKEYAUTHENTICATOR_H #define QSSLPRESHAREDKEYAUTHENTICATOR_H -#include <QtCore/QtGlobal> +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/QString> #include <QtCore/QSharedDataPointer> #include <QtCore/QMetaType> diff --git a/src/network/ssl/qsslpresharedkeyauthenticator_p.h b/src/network/ssl/qsslpresharedkeyauthenticator_p.h index b9aa6eb28c..e5566c3b3c 100644 --- a/src/network/ssl/qsslpresharedkeyauthenticator_p.h +++ b/src/network/ssl/qsslpresharedkeyauthenticator_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QSharedData> QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp index fc60f48d93..29e1f32815 100644 --- a/src/network/ssl/qsslsocket.cpp +++ b/src/network/ssl/qsslsocket.cpp @@ -837,15 +837,7 @@ bool QSslSocket::atEnd() const // Note! docs copied from QAbstractSocket::flush() bool QSslSocket::flush() { - Q_D(QSslSocket); -#ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << "QSslSocket::flush()"; -#endif - if (d->mode != UnencryptedMode) - // encrypt any unencrypted bytes in our buffer - d->transmit(); - - return d->plainSocket ? d->plainSocket->flush() : false; + return d_func()->flush(); } /*! @@ -924,6 +916,8 @@ void QSslSocket::setSslConfiguration(const QSslConfiguration &configuration) d->configuration.privateKey = configuration.privateKey(); 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(); @@ -2623,6 +2617,22 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize) /*! \internal */ +bool QSslSocketPrivate::flush() +{ +#ifdef QSSLSOCKET_DEBUG + qCDebug(lcSsl) << "QSslSocketPrivate::flush()"; +#endif + if (mode != QSslSocket::UnencryptedMode) { + // encrypt any unencrypted bytes in our buffer + transmit(); + } + + return plainSocket && plainSocket->flush(); +} + +/*! + \internal +*/ bool QSslSocketPrivate::rootCertOnDemandLoadingSupported() { return s_loadRootCertsOnDemand; diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h index c069ff2f9d..1b29cd4637 100644 --- a/src/network/ssl/qsslsocket.h +++ b/src/network/ssl/qsslsocket.h @@ -41,6 +41,7 @@ #ifndef QSSLSOCKET_H #define QSSLSOCKET_H +#include <QtNetwork/qtnetworkglobal.h> #include <QtCore/qlist.h> #include <QtCore/qregexp.h> #ifndef QT_NO_SSL @@ -116,7 +117,7 @@ public: bool canReadLine() const Q_DECL_OVERRIDE; void close() Q_DECL_OVERRIDE; bool atEnd() const Q_DECL_OVERRIDE; - bool flush(); + bool flush(); // ### Qt6: remove me (implementation moved to private flush()) void abort(); // From QAbstractSocket: diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index fd82d53fa8..438ea9a38e 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -68,57 +68,18 @@ QT_BEGIN_NAMESPACE static SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode) { const bool isServer = mode == QSslSocket::SslServerMode; - SSLContextRef context = Q_NULLPTR; - -#ifndef Q_OS_OSX const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide; // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally. - context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); + SSLContextRef context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); if (!context) qCWarning(lcSsl) << "SSLCreateContext failed"; -#else // Q_OS_OSX - -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - const SSLProtocolSide side = isServer ? kSSLServerSide : kSSLClientSide; - // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally. - context = SSLCreateContext(Q_NULLPTR, side, kSSLStreamType); - if (!context) - qCWarning(lcSsl) << "SSLCreateContext failed"; - } else { -#else - { -#endif - const OSStatus errCode = SSLNewContext(isServer, &context); - if (errCode != noErr || !context) - qCWarning(lcSsl) << "SSLNewContext failed with error:" << errCode; - } -#endif // !Q_OS_OSX - return context; } static void qt_releaseSecureTransportContext(SSLContextRef context) { - if (!context) - return; - -#ifndef Q_OS_OSX - CFRelease(context); -#else - -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { + if (context) CFRelease(context); - } else { -#else - { -#endif // QT_MAC_PLATFORM_... - const OSStatus errCode = SSLDisposeContext(context); - if (errCode != noErr) - qCWarning(lcSsl) << "SSLDisposeContext failed with error:" << errCode; - } -#endif // !Q_OS_OSX } static bool qt_setSessionProtocol(SSLContextRef context, const QSslConfigurationPrivate &configuration, @@ -132,7 +93,6 @@ static bool qt_setSessionProtocol(SSLContextRef context, const QSslConfiguration OSStatus err = noErr; -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_5_0) if (configuration.protocol == QSsl::SslV3) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcSsl) << plainSocket << "requesting : SSLv3"; @@ -210,117 +170,10 @@ static bool qt_setSessionProtocol(SSLContextRef context, const QSslConfiguration #endif return false; } -#endif return err == noErr; } -#ifdef Q_OS_OSX - -static bool qt_setSessionProtocolOSX(SSLContextRef context, const QSslConfigurationPrivate &configuration, - QTcpSocket *plainSocket) -{ - // This function works with (now) deprecated API that does not even exist on - // iOS but is the only API we have on OS X below 10.8 - - // Without SSLSetProtocolVersionMin/Max functions it's quite difficult - // to have the required result: - // If we use SSLSetProtocolVersion - any constant except the ones with 'Only' suffix - - // allows a negotiation and we can not set the lower limit. - // SSLSetProtocolVersionEnabled supports only a limited subset of constants, if you believe their docs: - // kSSLProtocol2 - // kSSLProtocol3 - // kTLSProtocol1 - // kSSLProtocolAll - // Here we can only have a look into the SecureTransport's code and hope that what we see there - // and what we have on 10.7 is similar: - // SSLSetProtocoLVersionEnabled actually accepts other constants also, - // called twice with two different protocols it sets a range, - // called once with a protocol (when all protocols were disabled) - // - only this protocol is enabled (without a lower limit negotiation). - - Q_ASSERT(context); - -#ifndef QSSLSOCKET_DEBUG - Q_UNUSED(plainSocket) -#endif - - OSStatus err = noErr; - - // First, disable ALL: - if (SSLSetProtocolVersionEnabled(context, kSSLProtocolAll, false) != noErr) - return false; - - if (configuration.protocol == QSsl::SslV3) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : SSLv3"; - #endif - err = SSLSetProtocolVersion(context, kSSLProtocol3Only); - } else if (configuration.protocol == QSsl::TlsV1_0) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.0"; - #endif - err = SSLSetProtocolVersion(context, kTLSProtocol1Only); - } else if (configuration.protocol == QSsl::TlsV1_1) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol11, true); - } else if (configuration.protocol == QSsl::TlsV1_2) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - } else if (configuration.protocol == QSsl::AnyProtocol) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : any"; - #endif - err = SSLSetProtocolVersionEnabled(context, kSSLProtocolAll, true); - } else if (configuration.protocol == QSsl::TlsV1SslV3) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : SSLv3 - TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - if (err == noErr) - err = SSLSetProtocolVersionEnabled(context, kSSLProtocol3, true); - } else if (configuration.protocol == QSsl::SecureProtocols) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - if (err == noErr) - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol1, true); - } else if (configuration.protocol == QSsl::TlsV1_0OrLater) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1 - TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - if (err == noErr) - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol1, true); - } else if (configuration.protocol == QSsl::TlsV1_1OrLater) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - if (err == noErr) - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol11, true); - } else if (configuration.protocol == QSsl::TlsV1_2OrLater) { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "requesting : TLSv1.2"; - #endif - err = SSLSetProtocolVersionEnabled(context, kTLSProtocol12, true); - } else { - #ifdef QSSLSOCKET_DEBUG - qCDebug(lcSsl) << plainSocket << "no protocol version found in the configuration"; - #endif - return false; - } - - return err == noErr; -} - -#endif // Q_OS_OSX - QSecureTransportContext::QSecureTransportContext(SSLContextRef c) : context(c) { @@ -351,7 +204,7 @@ bool QSslSocketPrivate::s_loadedCiphersAndCerts = false; bool QSslSocketPrivate::s_loadRootCertsOnDemand = false; -#ifndef Q_OS_IOS // dhparam is not used on iOS. (see the SSLSetDiffieHellmanParams call below) +#if !defined(QT_PLATFORM_UIKIT) // dhparam is not used on iOS or tvOS. (see the SSLSetDiffieHellmanParams call below) static const uint8_t dhparam[] = "\x30\x82\x01\x08\x02\x82\x01\x01\x00\x97\xea\xd0\x46\xf7\xae\xa7\x76\x80" "\x9c\x74\x56\x98\xd8\x56\x97\x2b\x20\x6c\x77\xe2\x82\xbb\xc8\x84\xbe\xe7" @@ -370,8 +223,8 @@ static const uint8_t dhparam[] = "\x90\x0b\x35\x64\xff\xd9\xe3\xac\xf2\xf2\xeb\x3a\x63\x02\x01\x02"; #endif -// No ioErr on iOS. (defined in MacErrors.h on OS X) -#ifdef Q_OS_IOS +// No ioErr on iOS/tvOS. (defined in MacErrors.h on OS X) +#if defined(QT_PLATFORM_UIKIT) # define ioErr -36 #endif @@ -959,21 +812,6 @@ bool QSslSocketBackendPrivate::initSslContext() return false; } -#ifdef Q_OS_OSX - if (QSysInfo::MacintoshVersion < QSysInfo::MV_10_8) { - // Starting from OS X 10.8 SSLSetSessionOption with kSSLSessionOptionBreakOnServerAuth/ - // kSSLSessionOptionBreakOnClientAuth disables automatic certificate validation. - // But for OS X versions below 10.8 we have to do it explicitly: - const OSStatus err = SSLSetEnableCertVerify(context, false); - if (err != noErr) { - destroySslContext(); - setErrorAndEmit(QSslSocket::SslInternalError, - QStringLiteral("SSLSetEnableCertVerify failed: %1").arg(err)); - return false; - } - } -#endif - if (mode == QSslSocket::SslClientMode) { // enable Server Name Indication (SNI) QString tlsHostName(verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName); @@ -1011,7 +849,7 @@ bool QSslSocketBackendPrivate::initSslContext() return false; } } -#ifndef Q_OS_IOS +#if !defined(QT_PLATFORM_UIKIT) // No SSLSetDiffieHellmanParams on iOS; calling it is optional according to docs. SSLSetDiffieHellmanParams(context, dhparam, sizeof(dhparam)); #endif @@ -1128,20 +966,7 @@ bool QSslSocketBackendPrivate::setSessionProtocol() return false; } -#ifndef Q_OS_OSX return qt_setSessionProtocol(context, configuration, plainSocket); -#else - -#if QT_MAC_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_8, __IPHONE_NA) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_8) { - return qt_setSessionProtocol(context, configuration, plainSocket); - } else { -#else - { -#endif - return qt_setSessionProtocolOSX(context, configuration, plainSocket); - } -#endif } bool QSslSocketBackendPrivate::canIgnoreTrustVerificationFailure() const diff --git a/src/network/ssl/qsslsocket_mac_p.h b/src/network/ssl/qsslsocket_mac_p.h index 09b6f392cd..9e1d18981e 100644 --- a/src/network/ssl/qsslsocket_mac_p.h +++ b/src/network/ssl/qsslsocket_mac_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <QtCore/qstring.h> #include <QtCore/qglobal.h> #include <QtCore/qlist.h> diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index b3820aea97..aca7507d13 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -201,6 +201,15 @@ static unsigned int q_ssl_psk_client_callback(SSL *ssl, Q_ASSERT(d); return d->tlsPskClientCallback(hint, identity, max_identity_len, psk, max_psk_len); } + +static unsigned int q_ssl_psk_server_callback(SSL *ssl, + const char *identity, + unsigned char *psk, unsigned int max_psk_len) +{ + QSslSocketBackendPrivate *d = reinterpret_cast<QSslSocketBackendPrivate *>(q_SSL_get_ex_data(ssl, QSslSocketBackendPrivate::s_indexForSSLExtraData)); + Q_ASSERT(d); + return d->tlsPskServerCallback(identity, psk, max_psk_len); +} #endif } // extern "C" @@ -436,8 +445,12 @@ bool QSslSocketBackendPrivate::initSslContext() #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) // Set the client callback for PSK - if (q_SSLeay() >= 0x10001000L && mode == QSslSocket::SslClientMode) - q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); + if (q_SSLeay() >= 0x10001000L) { + if (mode == QSslSocket::SslClientMode) + q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); + else if (mode == QSslSocket::SslServerMode) + q_SSL_set_psk_server_callback(ssl, &q_ssl_psk_server_callback); + } #endif return true; @@ -522,15 +535,9 @@ void QSslSocketPrivate::ensureCiphersAndCertsLoaded() #if defined(Q_OS_WIN) HINSTANCE hLib = LoadLibraryW(L"Crypt32"); if (hLib) { -#if defined(Q_OS_WINCE) - ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, L"CertOpenStore"); - ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, L"CertFindCertificateInStore"); - ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, L"CertCloseStore"); -#else ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW"); ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore"); ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore"); -#endif if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore) qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen } else { @@ -691,15 +698,7 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates() #if defined(Q_OS_WIN) if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) { HCERTSTORE hSystemStore; -#if defined(Q_OS_WINCE) - hSystemStore = ptrCertOpenSystemStoreW(CERT_STORE_PROV_SYSTEM_W, - 0, - 0, - CERT_STORE_NO_CRYPT_RELEASE_FLAG|CERT_SYSTEM_STORE_CURRENT_USER, - L"ROOT"); -#else hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT"); -#endif if(hSystemStore) { PCCERT_CONTEXT pc = NULL; while(1) { @@ -1278,6 +1277,31 @@ unsigned int QSslSocketBackendPrivate::tlsPskClientCallback(const char *hint, return pskLength; } +unsigned int QSslSocketBackendPrivate::tlsPskServerCallback(const char *identity, + unsigned char *psk, unsigned int max_psk_len) +{ + QSslPreSharedKeyAuthenticator authenticator; + + // Fill in some read-only fields (for the user) + authenticator.d->identityHint = configuration.preSharedKeyIdentityHint; + authenticator.d->identity = identity; + authenticator.d->maximumIdentityLength = 0; // user cannot set an identity + authenticator.d->maximumPreSharedKeyLength = int(max_psk_len); + + // Let the client provide the remaining bits... + Q_Q(QSslSocket); + emit q->preSharedKeyAuthenticationRequired(&authenticator); + + // No PSK set? Return now to make the handshake fail + if (authenticator.preSharedKey().isEmpty()) + return 0; + + // Copy data back into OpenSSL + const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength()); + ::memcpy(psk, authenticator.preSharedKey().constData(), pskLength); + return pskLength; +} + #ifdef Q_OS_WIN void QSslSocketBackendPrivate::fetchCaRootForCert(const QSslCertificate &cert) @@ -1579,7 +1603,22 @@ void QSslSocketBackendPrivate::continueHandshake() } else { const unsigned char *proto = 0; unsigned int proto_len = 0; - q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + if (q_SSLeay() >= 0x10002000L) { + q_SSL_get0_alpn_selected(ssl, &proto, &proto_len); + if (proto_len && mode == QSslSocket::SslClientMode) { + // Client does not have a callback that sets it ... + configuration.nextProtocolNegotiationStatus = QSslConfiguration::NextProtocolNegotiationNegotiated; + } + } + + if (!proto_len) { // Test if NPN was more lucky ... +#else + { +#endif + q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len); + } + if (proto_len) configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len); else diff --git a/src/network/ssl/qsslsocket_openssl_android.cpp b/src/network/ssl/qsslsocket_openssl_android.cpp index d73ed8995e..b5d2458d56 100644 --- a/src/network/ssl/qsslsocket_openssl_android.cpp +++ b/src/network/ssl/qsslsocket_openssl_android.cpp @@ -70,6 +70,7 @@ QList<QByteArray> QSslSocketPrivate::fetchSslCertificateData() QJNIEnvironmentPrivate env; jobjectArray jcertificates = static_cast<jobjectArray>(certificates.object()); const jint nCertificates = env->GetArrayLength(jcertificates); + certificateData.reserve(static_cast<int>(nCertificates)); for (int i = 0; i < nCertificates; ++i) { jbyteArray jCert = static_cast<jbyteArray>(env->GetObjectArrayElement(jcertificates, i)); diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h index 0674c05d71..755a08ef6e 100644 --- a/src/network/ssl/qsslsocket_openssl_p.h +++ b/src/network/ssl/qsslsocket_openssl_p.h @@ -66,6 +66,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslsocket_p.h" #ifdef Q_OS_WIN @@ -143,6 +144,7 @@ public: bool checkSslErrors(); void storePeerCertificates(); unsigned int tlsPskClientCallback(const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); + unsigned int tlsPskServerCallback(const char *identity, unsigned char *psk, unsigned int max_psk_len); #ifdef Q_OS_WIN void fetchCaRootForCert(const QSslCertificate &cert); void _q_caRootLoaded(QSslCertificate,QSslCertificate) Q_DECL_OVERRIDE; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index d420f78dc7..88fed69d3a 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -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) @@ -202,17 +206,20 @@ DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) #else +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) #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 DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *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) #endif #endif +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) #ifndef OPENSSL_NO_EC @@ -300,6 +307,8 @@ DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return N #endif #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callback_t callback, callback, return, DUMMYARG) +DEFINEFUNC2(void, SSL_set_psk_server_callback, SSL* ssl, ssl, q_psk_server_callback_t callback, callback, return, DUMMYARG) +DEFINEFUNC2(int, SSL_CTX_use_psk_identity_hint, SSL_CTX* ctx, ctx, const char *hint, hint, return 0, return) #endif #if OPENSSL_VERSION_NUMBER >= 0x10000000L #ifndef OPENSSL_NO_SSL2 @@ -418,10 +427,24 @@ DEFINEFUNC3(void, SSL_CTX_set_next_proto_select_cb, SSL_CTX *s, s, void *arg, arg, return, DUMMYARG) DEFINEFUNC3(void, SSL_get0_next_proto_negotiated, const SSL *s, s, const unsigned char **data, data, unsigned *len, len, return, DUMMYARG) +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +DEFINEFUNC3(int, SSL_set_alpn_protos, SSL *s, s, const unsigned char *protos, protos, + unsigned protos_len, protos_len, return -1, return) +DEFINEFUNC3(void, SSL_CTX_set_alpn_select_cb, SSL_CTX *s, s, + int (*cb) (SSL *ssl, const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, void *arg), cb, + void *arg, arg, return, DUMMYARG) +DEFINEFUNC3(void, SSL_get0_alpn_selected, const SSL *s, s, const unsigned char **data, data, + unsigned *len, len, return, DUMMYARG) +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... 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) @@ -768,6 +791,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) @@ -811,17 +838,20 @@ bool q_resolveOpenSslSymbols() #ifdef SSLEAY_MACROS // ### verify RESOLVEFUNC(PEM_ASN1_read_bio) #else + RESOLVEFUNC(PEM_read_bio_PrivateKey) RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) #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 RESOLVEFUNC(PEM_write_bio_ECPrivateKey) #endif #endif + RESOLVEFUNC(PEM_read_bio_PUBKEY) RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) #ifndef OPENSSL_NO_EC @@ -889,6 +919,8 @@ bool q_resolveOpenSslSymbols() #endif #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) RESOLVEFUNC(SSL_set_psk_client_callback) + RESOLVEFUNC(SSL_set_psk_server_callback) + RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) #endif RESOLVEFUNC(SSL_write) #ifndef OPENSSL_NO_SSL2 @@ -972,9 +1004,16 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) RESOLVEFUNC(SSL_get0_next_proto_negotiated) #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... +#if OPENSSL_VERSION_NUMBER >= 0x10002000L + RESOLVEFUNC(SSL_set_alpn_protos) + RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) + RESOLVEFUNC(SSL_get0_alpn_selected) +#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ... 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) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index df17fd8a9c..508fdc2a4b 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -67,6 +67,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslsocket_openssl_p.h" #include <QtCore/qglobal.h> @@ -220,13 +221,28 @@ unsigned char * q_ASN1_STRING_data(ASN1_STRING *a); int q_ASN1_STRING_length(ASN1_STRING *a); int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b); long q_BIO_ctrl(BIO *a, int b, long c, void *d); -int q_BIO_free(BIO *a); -BIO *q_BIO_new(BIO_METHOD *a); +Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a); +Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a); BIO *q_BIO_new_mem_buf(void *a, int b); 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); +Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem(); +Q_AUTOTEST_EXPORT 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); @@ -279,11 +295,13 @@ void *q_PEM_ASN1_read_bio(d2i_of_void *a, const char *b, BIO *c, void **d, pem_p void *f); // ### ditto for write #else +Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); 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, @@ -293,6 +311,7 @@ int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigne int e, pem_password_cb *f, void *g); #endif #endif +Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d); #ifndef OPENSSL_NO_EC @@ -376,6 +395,9 @@ void *q_SSL_get_ex_data(const SSL *ssl, int idx); #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) typedef unsigned int (*q_psk_client_callback_t)(SSL *ssl, const char *hint, char *identity, unsigned int max_identity_len, unsigned char *psk, unsigned int max_psk_len); void q_SSL_set_psk_client_callback(SSL *ssl, q_psk_client_callback_t callback); +typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity, unsigned char *psk, unsigned int max_psk_len); +void q_SSL_set_psk_server_callback(SSL *ssl, q_psk_server_callback_t callback); +int q_SSL_CTX_use_psk_identity_hint(SSL_CTX *ctx, const char *hint); #endif // OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK) #if OPENSSL_VERSION_NUMBER >= 0x10000000L #ifndef OPENSSL_NO_SSL2 @@ -472,6 +494,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) @@ -518,6 +542,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) @@ -558,6 +585,19 @@ void q_SSL_CTX_set_next_proto_select_cb(SSL_CTX *s, void *arg); void q_SSL_get0_next_proto_negotiated(const SSL *s, const unsigned char **data, unsigned *len); +#if OPENSSL_VERSION_NUMBER >= 0x10002000L +int q_SSL_set_alpn_protos(SSL *ssl, const unsigned char *protos, + unsigned protos_len); +void q_SSL_CTX_set_alpn_select_cb(SSL_CTX *ctx, + int (*cb) (SSL *ssl, + const unsigned char **out, + unsigned char *outlen, + const unsigned char *in, + unsigned int inlen, + void *arg), void *arg); +void q_SSL_get0_alpn_selected(const SSL *ssl, const unsigned char **data, + unsigned *len); +#endif #endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ... // Helper function diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 5d4d52cd6d..696827daff 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -54,6 +54,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include <private/qtcpsocket_p.h> #include "qsslkey.h" #include "qsslconfiguration_p.h" @@ -89,11 +90,7 @@ QT_BEGIN_NAMESPACE #endif #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) -#if defined(Q_OS_WINCE) - typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(LPCSTR, DWORD, HCRYPTPROV_LEGACY, DWORD, const void*); -#else typedef HCERTSTORE (WINAPI *PtrCertOpenSystemStoreW)(HCRYPTPROV_LEGACY, LPCWSTR); -#endif typedef PCCERT_CONTEXT (WINAPI *PtrCertFindCertificateInStore)(HCERTSTORE, DWORD, DWORD, DWORD, const void*, PCCERT_CONTEXT); typedef BOOL (WINAPI *PtrCertCloseStore)(HCERTSTORE, DWORD); #endif // Q_OS_WIN && !Q_OS_WINRT @@ -193,6 +190,7 @@ public: virtual qint64 peek(char *data, qint64 maxSize) Q_DECL_OVERRIDE; virtual QByteArray peek(qint64 maxSize) Q_DECL_OVERRIDE; + bool flush() Q_DECL_OVERRIDE; // Platform specific functions virtual void startClientEncryption() = 0; diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp index edc8ca0bbb..f5dc9fcdcd 100644 --- a/src/network/ssl/qsslsocket_winrt.cpp +++ b/src/network/ssl/qsslsocket_winrt.cpp @@ -215,7 +215,9 @@ QList<QSslCipher> QSslSocketBackendPrivate::defaultCiphers() const QString protocolStrings[] = { QStringLiteral("SSLv3"), QStringLiteral("TLSv1"), QStringLiteral("TLSv1.1"), QStringLiteral("TLSv1.2") }; const QSsl::SslProtocol protocols[] = { QSsl::SslV3, QSsl::TlsV1_0, QSsl::TlsV1_1, QSsl::TlsV1_2 }; - for (int i = 0; i < ARRAYSIZE(protocols); ++i) { + const int size = static_cast<int>(ARRAYSIZE(protocols)); + ciphers.reserve(size); + for (int i = 0; i < size; ++i) { QSslCipher cipher; cipher.d->isNull = false; cipher.d->name = QStringLiteral("WINRT"); diff --git a/src/network/ssl/qsslsocket_winrt_p.h b/src/network/ssl/qsslsocket_winrt_p.h index 3946a0e60b..1043aeee11 100644 --- a/src/network/ssl/qsslsocket_winrt_p.h +++ b/src/network/ssl/qsslsocket_winrt_p.h @@ -51,6 +51,7 @@ // We mean it. // +#include <QtNetwork/private/qtnetworkglobal_p.h> #include "qsslsocket_p.h" #include <wrl.h> diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index c70664ef9b..edbbeadf51 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -1,5 +1,5 @@ # OpenSSL support; compile in QSslSocket. -contains(QT_CONFIG, ssl) | contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { +contains(QT_CONFIG, ssl) { HEADERS += ssl/qasn1element_p.h \ ssl/qssl.h \ ssl/qssl_p.h \ @@ -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,43 +48,45 @@ 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 \ ssl/qsslsocket_mac.cpp \ ssl/qsslellipticcurve_dummy.cpp } -} -contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { - HEADERS += ssl/qsslcontext_openssl_p.h \ - ssl/qsslsocket_openssl_p.h \ - ssl/qsslsocket_openssl_symbols_p.h - SOURCES += ssl/qsslcertificate_openssl.cpp \ - ssl/qsslcontext_openssl.cpp \ - ssl/qsslellipticcurve_openssl.cpp \ - ssl/qsslkey_openssl.cpp \ - ssl/qsslsocket_openssl.cpp \ - ssl/qsslsocket_openssl_symbols.cpp + contains(QT_CONFIG, openssl) | contains(QT_CONFIG, openssl-linked) { + HEADERS += ssl/qsslcontext_openssl_p.h \ + ssl/qsslsocket_openssl_p.h \ + 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 \ + ssl/qsslsocket_openssl_symbols.cpp - darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp + darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp - android: SOURCES += ssl/qsslsocket_openssl_android.cpp + android: SOURCES += ssl/qsslsocket_openssl_android.cpp - # Add optional SSL libs - # Static linking of OpenSSL with msvc: - # - Binaries http://slproweb.com/products/Win32OpenSSL.html - # - also needs -lUser32 -lAdvapi32 -lGdi32 -lCrypt32 - # - libs in <OPENSSL_DIR>\lib\VC\static - # - configure: -openssl -openssl-linked -I <OPENSSL_DIR>\include -L <OPENSSL_DIR>\lib\VC\static OPENSSL_LIBS="-lUser32 -lAdvapi32 -lGdi32" OPENSSL_LIBS_DEBUG="-lssleay32MDd -llibeay32MDd" OPENSSL_LIBS_RELEASE="-lssleay32MD -llibeay32MD" + # Add optional SSL libs + # Static linking of OpenSSL with msvc: + # - Binaries http://slproweb.com/products/Win32OpenSSL.html + # - also needs -lUser32 -lAdvapi32 -lGdi32 -lCrypt32 + # - libs in <OPENSSL_DIR>\lib\VC\static + # - configure: -openssl -openssl-linked -I <OPENSSL_DIR>\include -L <OPENSSL_DIR>\lib\VC\static OPENSSL_LIBS="-lUser32 -lAdvapi32 -lGdi32" OPENSSL_LIBS_DEBUG="-lssleay32MDd -llibeay32MDd" OPENSSL_LIBS_RELEASE="-lssleay32MD -llibeay32MD" - CONFIG(debug, debug|release) { - LIBS_PRIVATE += $$OPENSSL_LIBS_DEBUG - } else { - LIBS_PRIVATE += $$OPENSSL_LIBS_RELEASE - } + CONFIG(debug, debug|release) { + LIBS_PRIVATE += $$OPENSSL_LIBS_DEBUG + } else { + LIBS_PRIVATE += $$OPENSSL_LIBS_RELEASE + } - QMAKE_CXXFLAGS += $$OPENSSL_CFLAGS - LIBS_PRIVATE += $$OPENSSL_LIBS - win32: LIBS_PRIVATE += -lcrypt32 + QMAKE_CXXFLAGS += $$OPENSSL_CFLAGS + LIBS_PRIVATE += $$OPENSSL_LIBS + win32: LIBS_PRIVATE += -lcrypt32 + } } |