summaryrefslogtreecommitdiffstats
path: root/libraries/qt5/patches/qtbase59-openssl11.patch
diff options
context:
space:
mode:
Diffstat (limited to 'libraries/qt5/patches/qtbase59-openssl11.patch')
-rw-r--r--libraries/qt5/patches/qtbase59-openssl11.patch3961
1 files changed, 3961 insertions, 0 deletions
diff --git a/libraries/qt5/patches/qtbase59-openssl11.patch b/libraries/qt5/patches/qtbase59-openssl11.patch
new file mode 100644
index 0000000000..d84a3b56e0
--- /dev/null
+++ b/libraries/qt5/patches/qtbase59-openssl11.patch
@@ -0,0 +1,3961 @@
+/*
+ * openssl v1.1 support in qtbase 5.9
+ * Taken from Qt (or KDE, don't remember) for use on 5.9.1 (5.9.8 is last tested)
+ * ole.andre.rodlie@gmail.com
+*/
+
+diff --git a/config.tests/unix/openssl11/openssl.cpp b/config.tests/unix/openssl11/openssl.cpp
+new file mode 100644
+index 0000000..c20cc59
+--- /dev/null
++++ b/config.tests/unix/openssl11/openssl.cpp
+@@ -0,0 +1,48 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the config.tests 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 <openssl/opensslv.h>
++
++#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L
++# error "OpenSSL >= 1.1 is required"
++#endif
++
++int main()
++{
++}
+diff --git a/config.tests/unix/openssl11/openssl.pro b/config.tests/unix/openssl11/openssl.pro
+new file mode 100644
+index 0000000..a023aee
+--- /dev/null
++++ b/config.tests/unix/openssl11/openssl.pro
+@@ -0,0 +1,2 @@
++SOURCES = openssl.cpp
++CONFIG -= x11 qt
+diff --git a/src/network/configure.json b/src/network/configure.json
+index 916448a..5ecf1ad 100644
+--- a/src/network/configure.json
++++ b/src/network/configure.json
+@@ -154,6 +154,12 @@
+ ]
+ },
+ "use": "network"
++ },
++ "openssl11": {
++ "label": "OpenSSL v. 1.1 support",
++ "type": "compile",
++ "test": "unix/openssl11",
++ "use": "network"
+ }
+ },
+
+@@ -221,6 +227,11 @@
+ "condition": "config.winrt || features.securetransport || features.openssl",
+ "output": [ "publicFeature", "feature" ]
+ },
++ "opensslv11": {
++ "label": "OpenSSL v. 1.1",
++ "condition": "tests.openssl11",
++ "output": ["publicFeature", "feature"]
++ },
+ "sctp": {
+ "label": "SCTP",
+ "autoDetect": false,
+diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
+index 28b7eda..71e514a 100644
+--- a/src/network/ssl/qsslcertificate_openssl.cpp
++++ b/src/network/ssl/qsslcertificate_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -64,12 +65,14 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
+ uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+ {
+ if (X509 * const x509 = key.d->x509) {
+- (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash
+- // (if someone knows a better way...)
+- return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed);
+- } else {
+- return seed;
++ const EVP_MD *sha1 = q_EVP_sha1();
++ unsigned int len = 0;
++ unsigned char md[EVP_MAX_MD_SIZE];
++ q_X509_digest(x509, sha1, md, &len);
++ return qHashBits(md, len, seed);
+ }
++
++ return seed;
+ }
+
+ bool QSslCertificate::isNull() const
+@@ -89,8 +92,7 @@ QByteArray QSslCertificate::version() const
+ {
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+ if (d->versionString.isEmpty() && d->x509)
+- d->versionString =
+- QByteArray::number(qlonglong(q_ASN1_INTEGER_get(d->x509->cert_info->version)) + 1);
++ d->versionString = QByteArray::number(qlonglong(q_X509_get_version(d->x509)) + 1);
+
+ return d->versionString;
+ }
+@@ -99,7 +101,7 @@ QByteArray QSslCertificate::serialNumber() const
+ {
+ QMutexLocker lock(QMutexPool::globalInstanceGet(d.data()));
+ if (d->serialNumberString.isEmpty() && d->x509) {
+- ASN1_INTEGER *serialNumber = d->x509->cert_info->serialNumber;
++ ASN1_INTEGER *serialNumber = q_X509_get_serialNumber(d->x509);
+ QByteArray hexString;
+ hexString.reserve(serialNumber->length * 3);
+ for (int a = 0; a < serialNumber->length; ++a) {
+@@ -199,14 +201,15 @@ QMultiMap<QSsl::AlternativeNameEntryType, QString> QSslCertificate::subjectAlter
+ continue;
+ }
+
+- const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(genName->d.ia5));
++ const char *altNameStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(genName->d.ia5));
+ const QString altName = QString::fromLatin1(altNameStr, len);
+ if (genName->type == GEN_DNS)
+ result.insert(QSsl::DnsEntry, altName);
+ else if (genName->type == GEN_EMAIL)
+ result.insert(QSsl::EmailEntry, altName);
+ }
+- q_sk_pop_free((STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_sk_free));
++
++ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)altNames, reinterpret_cast<void(*)(void*)>(q_OPENSSL_sk_free));
+ }
+
+ return result;
+@@ -235,25 +238,26 @@ QSslKey QSslCertificate::publicKey() const
+ QSslKey key;
+
+ key.d->type = QSsl::PublicKey;
+- X509_PUBKEY *xkey = d->x509->cert_info->key;
+- EVP_PKEY *pkey = q_X509_PUBKEY_get(xkey);
++
++ EVP_PKEY *pkey = q_X509_get_pubkey(d->x509);
+ Q_ASSERT(pkey);
++ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
+
+- if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_RSA) {
++ if (keyType == EVP_PKEY_RSA) {
+ key.d->rsa = q_EVP_PKEY_get1_RSA(pkey);
+ key.d->algorithm = QSsl::Rsa;
+ key.d->isNull = false;
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA) {
++ } else if (keyType == EVP_PKEY_DSA) {
+ key.d->dsa = q_EVP_PKEY_get1_DSA(pkey);
+ key.d->algorithm = QSsl::Dsa;
+ key.d->isNull = false;
+ #ifndef OPENSSL_NO_EC
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_EC) {
++ } else if (keyType == EVP_PKEY_EC) {
+ key.d->ec = q_EVP_PKEY_get1_EC_KEY(pkey);
+ key.d->algorithm = QSsl::Ec;
+ key.d->isNull = false;
+ #endif
+- } else if (q_EVP_PKEY_type(pkey->type) == EVP_PKEY_DH) {
++ } else if (keyType == EVP_PKEY_DH) {
+ // DH unsupported
+ } else {
+ // error?
+@@ -275,7 +279,7 @@ static QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext)
+ X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext));
+ if (!meth) {
+ ASN1_OCTET_STRING *value = q_X509_EXTENSION_get_data(ext);
+- QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_data(value)),
++ QByteArray result( reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(value)),
+ q_ASN1_STRING_length(value));
+ return result;
+ }
+@@ -371,7 +375,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
+ continue;
+ }
+
+- const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_data(name->d.uniformResourceIdentifier));
++ const char *uriStr = reinterpret_cast<const char *>(q_ASN1_STRING_get0_data(name->d.uniformResourceIdentifier));
+ const QString uri = QString::fromUtf8(uriStr, len);
+
+ result[QString::fromUtf8(QSslCertificatePrivate::asn1ObjectName(ad->method))] = uri;
+@@ -380,11 +384,7 @@ static QVariant x509ExtensionToValue(X509_EXTENSION *ext)
+ }
+ }
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_pop_free((_STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
+-#else
+- q_sk_pop_free((STACK*)info, reinterpret_cast<void(*)(void*)>(q_sk_free));
+-#endif
++ q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast<void(*)(void *)>(q_OPENSSL_sk_free));
+ return result;
+ }
+ break;
+@@ -607,7 +607,11 @@ static QMap<QByteArray, QString> _q_mapFromX509Name(X509_NAME *name)
+ unsigned char *data = 0;
+ int size = q_ASN1_STRING_to_UTF8(&data, q_X509_NAME_ENTRY_get_data(e));
+ info.insertMulti(name, QString::fromUtf8((char*)data, size));
++#if QT_CONFIG(opensslv11)
++ q_CRYPTO_free(data, 0, 0);
++#else
+ q_CRYPTO_free(data);
++#endif
+ }
+
+ return info;
+@@ -619,8 +623,9 @@ QSslCertificate QSslCertificatePrivate::QSslCertificate_from_X509(X509 *x509)
+ if (!x509 || !QSslSocket::supportsSsl())
+ return certificate;
+
+- ASN1_TIME *nbef = q_X509_get_notBefore(x509);
+- ASN1_TIME *naft = q_X509_get_notAfter(x509);
++ ASN1_TIME *nbef = q_X509_getm_notBefore(x509);
++ ASN1_TIME *naft = q_X509_getm_notAfter(x509);
++
+ certificate.d->notValidBefore = q_getTimeFromASN1(nbef);
+ certificate.d->notValidAfter = q_getTimeFromASN1(naft);
+ certificate.d->null = false;
+diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
+index c92d8fc..cef5037 100644
+--- a/src/network/ssl/qsslcontext_openssl.cpp
++++ b/src/network/ssl/qsslcontext_openssl.cpp
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG.
+ ** Contact: https://www.qt.io/licensing/
+@@ -41,22 +41,14 @@
+
+
+ #include <QtNetwork/qsslsocket.h>
+-#include <QtNetwork/qssldiffiehellmanparameters.h>
+-#include <QtCore/qmutex.h>
+
+ #include "private/qssl_p.h"
+ #include "private/qsslcontext_openssl_p.h"
+-#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
+
+-// defined in qsslsocket_openssl.cpp:
+-extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
+-extern QString getErrorsFromOpenSsl();
+-
+ QSslContext::QSslContext()
+ : ctx(0),
+ pkey(0),
+@@ -78,301 +70,6 @@ QSslContext::~QSslContext()
+ q_SSL_SESSION_free(session);
+ }
+
+-static inline QString msgErrorSettingEllipticCurves(const QString &why)
+-{
+- return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
+-}
+-
+-// static
+-void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+-{
+- sslContext->sslConfiguration = configuration;
+- sslContext->errorCode = QSslError::NoError;
+-
+- bool client = (mode == QSslSocket::SslClientMode);
+-
+- bool reinitialized = false;
+- bool unsupportedProtocol = false;
+-init_context:
+- switch (sslContext->sslConfiguration.protocol()) {
+- case QSsl::SslV2:
+-#ifndef OPENSSL_NO_SSL2
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
+-#else
+- // SSL 2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::SslV3:
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
+-#else
+- // SSL 3 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::SecureProtocols:
+- // SSLv2 and SSLv3 will be disabled by SSL options
+- // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
+- case QSsl::TlsV1SslV3:
+- // SSLv2 will will be disabled by SSL options
+- case QSsl::AnyProtocol:
+- default:
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+- break;
+- case QSsl::TlsV1_0:
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
+- break;
+- case QSsl::TlsV1_1:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
+-#else
+- // TLS 1.1 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::TlsV1_2:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
+-#else
+- // TLS 1.2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- case QSsl::TlsV1_0OrLater:
+- // Specific protocols will be specified via SSL options.
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+- break;
+- case QSsl::TlsV1_1OrLater:
+- case QSsl::TlsV1_2OrLater:
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- // Specific protocols will be specified via SSL options.
+- sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
+-#else
+- // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
+- sslContext->ctx = 0;
+- unsupportedProtocol = true;
+-#endif
+- break;
+- }
+-
+- if (!sslContext->ctx) {
+- // After stopping Flash 10 the SSL library looses its ciphers. Try re-adding them
+- // by re-initializing the library.
+- if (!reinitialized) {
+- reinitialized = true;
+- if (q_SSL_library_init() == 1)
+- goto init_context;
+- }
+-
+- sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
+- unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+- );
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // Enable bug workarounds.
+- long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
+- q_SSL_CTX_set_options(sslContext->ctx, options);
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- // Tell OpenSSL to release memory early
+- // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
+- if (q_SSLeay() >= 0x10000000L)
+- q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
+-#endif
+-
+- // Initialize ciphers
+- QByteArray cipherString;
+- bool first = true;
+- QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
+- if (ciphers.isEmpty())
+- ciphers = QSslSocketPrivate::defaultCiphers();
+- for (const QSslCipher &cipher : qAsConst(ciphers)) {
+- if (first)
+- first = false;
+- else
+- cipherString.append(':');
+- cipherString.append(cipher.name().toLatin1());
+- }
+-
+- if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
+- sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- const QDateTime now = QDateTime::currentDateTimeUtc();
+-
+- // Add all our CAs to this store.
+- const auto caCertificates = sslContext->sslConfiguration.caCertificates();
+- for (const QSslCertificate &caCertificate : caCertificates) {
+- // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
+- //
+- // If several CA certificates matching the name, key identifier, and
+- // serial number condition are available, only the first one will be
+- // examined. This may lead to unexpected results if the same CA
+- // certificate is available with different expiration dates. If a
+- // ``certificate expired'' verification error occurs, no other
+- // certificate will be searched. Make sure to not have expired
+- // certificates mixed with valid ones.
+- //
+- // See also: QSslSocketBackendPrivate::verify()
+- if (caCertificate.expiryDate() >= now) {
+- q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
+- }
+- }
+-
+- if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
+- // tell OpenSSL the directories where to look up the root certs on demand
+- const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
+- for (const QByteArray &unixDir : unixDirs)
+- q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
+- }
+-
+- if (!sslContext->sslConfiguration.localCertificate().isNull()) {
+- // Require a private key as well.
+- if (sslContext->sslConfiguration.privateKey().isNull()) {
+- sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // Load certificate
+- if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
+- sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
+- sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
+- } else {
+- // Load private key
+- sslContext->pkey = q_EVP_PKEY_new();
+- // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
+- // this lead to a memory leak. Now we use the *_set1_* functions which do not
+- // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
+- if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
+- q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
+- else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
+- q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
+-#ifndef OPENSSL_NO_EC
+- else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
+- q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
+-#endif
+- }
+-
+- if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
+- sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+- if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
+- sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
+-
+- // Check if the certificate matches the private key.
+- if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
+- sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- return;
+- }
+-
+- // If we have any intermediate certificates then we need to add them to our chain
+- bool first = true;
+- for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
+- if (first) {
+- first = false;
+- continue;
+- }
+- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
+- q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
+- }
+- }
+-
+- // Initialize peer verification.
+- if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
+- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
+- } else {
+- q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
+- }
+-
+- // Set verification depth.
+- if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
+- q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
+-
+- // set persisted session if the user set it
+- if (!configuration.sessionTicket().isEmpty())
+- sslContext->setSessionASN1(configuration.sessionTicket());
+-
+- // Set temp DH params
+- 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->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
+- if (q_SSLeay() >= 0x10002000L) {
+- q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
+- } else
+-#endif
+- {
+- // Set temp ECDH params
+- EC_KEY *ecdh = 0;
+- ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+- q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
+- q_EC_KEY_free(ecdh);
+- }
+-#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)
+- // Set the curves to be used
+- if (q_SSLeay() >= 0x10002000L) {
+- // SSL_CTX_ctrl wants a non-const pointer as last argument,
+- // but let's avoid a copy into a temporary array
+- if (!q_SSL_CTX_ctrl(sslContext->ctx,
+- SSL_CTRL_SET_CURVES,
+- qcurves.size(),
+- const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
+- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- }
+- } else
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
+- {
+- // specific curves requested, but not possible to set -> error
+- sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
+- sslContext->errorCode = QSslError::UnspecifiedError;
+- }
+- }
+-}
+-
+ QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
+ {
+ QSslContext *sslContext = new QSslContext();
+@@ -463,7 +160,7 @@ SSL* QSslContext::createSsl()
+ m_npnContext.len = m_supportedNPNVersions.count();
+ m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone;
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L) {
++ if (QSslSocket::sslLibraryVersionNumber() >= 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').
+@@ -508,7 +205,7 @@ bool QSslContext::cacheSession(SSL* ssl)
+ unsigned char *data = reinterpret_cast<unsigned char *>(m_sessionASN1.data());
+ if (!q_i2d_SSL_SESSION(session, &data))
+ qCWarning(lcSsl, "could not store persistent version of SSL session");
+- m_sessionTicketLifeTimeHint = session->tlsext_tick_lifetime_hint;
++ m_sessionTicketLifeTimeHint = q_SSL_SESSION_get_ticket_lifetime_hint(session);
+ }
+ }
+
+diff --git a/src/network/ssl/qsslcontext_openssl11.cpp b/src/network/ssl/qsslcontext_openssl11.cpp
+new file mode 100644
+index 0000000..787b6ae
+--- /dev/null
++++ b/src/network/ssl/qsslcontext_openssl11.cpp
+@@ -0,0 +1,277 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++
++#include <QtNetwork/qsslsocket.h>
++#include <QtNetwork/qssldiffiehellmanparameters.h>
++
++#include "private/qssl_p.h"
++#include "private/qsslcontext_openssl_p.h"
++#include "private/qsslsocket_p.h"
++#include "private/qsslsocket_openssl_p.h"
++#include "private/qsslsocket_openssl_symbols_p.h"
++#include "private/qssldiffiehellmanparameters_p.h"
++
++#include <vector>
++
++QT_BEGIN_NAMESPACE
++
++// defined in qsslsocket_openssl.cpp:
++extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
++extern QString getErrorsFromOpenSsl();
++
++static inline QString msgErrorSettingEllipticCurves(const QString &why)
++{
++ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
++}
++
++// static
++void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
++{
++ sslContext->sslConfiguration = configuration;
++ sslContext->errorCode = QSslError::NoError;
++
++ bool client = (mode == QSslSocket::SslClientMode);
++
++ bool reinitialized = false;
++ bool unsupportedProtocol = false;
++init_context:
++ if (sslContext->sslConfiguration.protocol() == QSsl::SslV2) {
++ // SSL 2 is no longer supported, but chosen deliberately -> error
++ sslContext->ctx = nullptr;
++ unsupportedProtocol = true;
++ } else {
++ // The ssl options will actually control the supported methods
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLS_client_method() : q_TLS_server_method());
++ }
++
++ if (!sslContext->ctx) {
++ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
++ // by re-initializing the library.
++ if (!reinitialized) {
++ reinitialized = true;
++ if (q_OPENSSL_init_ssl(0, nullptr) == 1)
++ goto init_context;
++ }
++
++ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
++ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
++ );
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Enable bug workarounds.
++ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
++ q_SSL_CTX_set_options(sslContext->ctx, options);
++
++ // Tell OpenSSL to release memory early
++ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
++ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
++
++ // Initialize ciphers
++ QByteArray cipherString;
++ bool first = true;
++ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
++ if (ciphers.isEmpty())
++ ciphers = QSslSocketPrivate::defaultCiphers();
++ for (const QSslCipher &cipher : qAsConst(ciphers)) {
++ if (first)
++ first = false;
++ else
++ cipherString.append(':');
++ cipherString.append(cipher.name().toLatin1());
++ }
++
++ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
++ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ const QDateTime now = QDateTime::currentDateTimeUtc();
++
++ // Add all our CAs to this store.
++ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
++ for (const QSslCertificate &caCertificate : caCertificates) {
++ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
++ //
++ // If several CA certificates matching the name, key identifier, and
++ // serial number condition are available, only the first one will be
++ // examined. This may lead to unexpected results if the same CA
++ // certificate is available with different expiration dates. If a
++ // ``certificate expired'' verification error occurs, no other
++ // certificate will be searched. Make sure to not have expired
++ // certificates mixed with valid ones.
++ //
++ // See also: QSslSocketBackendPrivate::verify()
++ if (caCertificate.expiryDate() >= now) {
++ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
++ }
++ }
++
++ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
++ // tell OpenSSL the directories where to look up the root certs on demand
++ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
++ for (const QByteArray &unixDir : unixDirs)
++ q_SSL_CTX_load_verify_locations(sslContext->ctx, nullptr, unixDir.constData());
++ }
++
++ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
++ // Require a private key as well.
++ if (sslContext->sslConfiguration.privateKey().isNull()) {
++ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Load certificate
++ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
++ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
++ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
++ } else {
++ // Load private key
++ sslContext->pkey = q_EVP_PKEY_new();
++ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
++ // this lead to a memory leak. Now we use the *_set1_* functions which do not
++ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
++ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
++ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
++ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
++ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
++#ifndef OPENSSL_NO_EC
++ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
++ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
++#endif
++ }
++
++ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
++ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
++ sslContext->pkey = nullptr; // Don't free the private key, it belongs to QSslKey
++
++ // Check if the certificate matches the private key.
++ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
++ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // If we have any intermediate certificates then we need to add them to our chain
++ bool first = true;
++ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
++ if (first) {
++ first = false;
++ continue;
++ }
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
++ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
++ }
++ }
++
++ // Initialize peer verification.
++ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, nullptr);
++ } else {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
++ }
++
++ // Set verification depth.
++ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
++ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
++
++ // set persisted session if the user set it
++ if (!configuration.sessionTicket().isEmpty())
++ sslContext->setSessionASN1(configuration.sessionTicket());
++
++ // Set temp DH params
++ 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->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_PSK
++ if (!client)
++ q_SSL_CTX_use_psk_identity_hint(sslContext->ctx, sslContext->sslConfiguration.preSharedKeyIdentityHint().constData());
++#endif // !OPENSSL_NO_PSK
++
++ const QVector<QSslEllipticCurve> qcurves = sslContext->sslConfiguration.ellipticCurves();
++ if (!qcurves.isEmpty()) {
++#ifdef OPENSSL_NO_EC
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version with disabled elliptic curves"));
++ sslContext->errorCode = QSslError::UnspecifiedError;
++#else
++ // Set the curves to be used.
++ std::vector<int> curves;
++ curves.reserve(qcurves.size());
++ for (const auto &sslCurve : qcurves)
++ curves.push_back(sslCurve.id);
++ if (!q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_CURVES, long(curves.size()), &curves[0])) {
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++#endif
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/src/network/ssl/qsslcontext_opensslpre11.cpp b/src/network/ssl/qsslcontext_opensslpre11.cpp
+new file mode 100644
+index 0000000..9c01c2f
+--- /dev/null
++++ b/src/network/ssl/qsslcontext_opensslpre11.cpp
+@@ -0,0 +1,354 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++
++#include <QtNetwork/qsslsocket.h>
++#include <QtNetwork/qssldiffiehellmanparameters.h>
++
++#include "private/qssl_p.h"
++#include "private/qsslcontext_openssl_p.h"
++#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
++
++// defined in qsslsocket_openssl.cpp:
++extern int q_X509Callback(int ok, X509_STORE_CTX *ctx);
++extern QString getErrorsFromOpenSsl();
++
++static inline QString msgErrorSettingEllipticCurves(const QString &why)
++{
++ return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why);
++}
++
++// static
++void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading)
++{
++ sslContext->sslConfiguration = configuration;
++ sslContext->errorCode = QSslError::NoError;
++
++ bool client = (mode == QSslSocket::SslClientMode);
++
++ bool reinitialized = false;
++ bool unsupportedProtocol = false;
++init_context:
++ switch (sslContext->sslConfiguration.protocol()) {
++ case QSsl::SslV2:
++#ifndef OPENSSL_NO_SSL2
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
++#else
++ // SSL 2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::SslV3:
++#ifndef OPENSSL_NO_SSL3_METHOD
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv3_client_method() : q_SSLv3_server_method());
++#else
++ // SSL 3 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::SecureProtocols:
++ // SSLv2 and SSLv3 will be disabled by SSL options
++ // But we need q_SSLv23_server_method() otherwise AnyProtocol will be unable to connect on Win32.
++ case QSsl::TlsV1SslV3:
++ // SSLv2 will will be disabled by SSL options
++ case QSsl::AnyProtocol:
++ default:
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++ break;
++ case QSsl::TlsV1_0:
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_client_method() : q_TLSv1_server_method());
++ break;
++ case QSsl::TlsV1_1:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
++#else
++ // TLS 1.1 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::TlsV1_2:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
++#else
++ // TLS 1.2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ case QSsl::TlsV1_0OrLater:
++ // Specific protocols will be specified via SSL options.
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++ break;
++ case QSsl::TlsV1_1OrLater:
++ case QSsl::TlsV1_2OrLater:
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ // Specific protocols will be specified via SSL options.
++ sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv23_client_method() : q_SSLv23_server_method());
++#else
++ // TLS 1.1/1.2 not supported by the system, but chosen deliberately -> error
++ sslContext->ctx = 0;
++ unsupportedProtocol = true;
++#endif
++ break;
++ }
++
++ if (!sslContext->ctx) {
++ // After stopping Flash 10 the SSL library loses its ciphers. Try re-adding them
++ // by re-initializing the library.
++ if (!reinitialized) {
++ reinitialized = true;
++ if (q_SSL_library_init() == 1)
++ goto init_context;
++ }
++
++ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
++ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
++ );
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Enable bug workarounds.
++ long options = QSslSocketBackendPrivate::setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions);
++ q_SSL_CTX_set_options(sslContext->ctx, options);
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++ // Tell OpenSSL to release memory early
++ // http://www.openssl.org/docs/ssl/SSL_CTX_set_mode.html
++ if (q_SSLeay() >= 0x10000000L)
++ q_SSL_CTX_set_mode(sslContext->ctx, SSL_MODE_RELEASE_BUFFERS);
++#endif
++
++ // Initialize ciphers
++ QByteArray cipherString;
++ bool first = true;
++ QList<QSslCipher> ciphers = sslContext->sslConfiguration.ciphers();
++ if (ciphers.isEmpty())
++ ciphers = QSslSocketPrivate::defaultCiphers();
++ for (const QSslCipher &cipher : qAsConst(ciphers)) {
++ if (first)
++ first = false;
++ else
++ cipherString.append(':');
++ cipherString.append(cipher.name().toLatin1());
++ }
++
++ if (!q_SSL_CTX_set_cipher_list(sslContext->ctx, cipherString.data())) {
++ sslContext->errorStr = QSslSocket::tr("Invalid or empty cipher list (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ const QDateTime now = QDateTime::currentDateTimeUtc();
++
++ // Add all our CAs to this store.
++ const auto caCertificates = sslContext->sslConfiguration.caCertificates();
++ for (const QSslCertificate &caCertificate : caCertificates) {
++ // From https://www.openssl.org/docs/ssl/SSL_CTX_load_verify_locations.html:
++ //
++ // If several CA certificates matching the name, key identifier, and
++ // serial number condition are available, only the first one will be
++ // examined. This may lead to unexpected results if the same CA
++ // certificate is available with different expiration dates. If a
++ // ``certificate expired'' verification error occurs, no other
++ // certificate will be searched. Make sure to not have expired
++ // certificates mixed with valid ones.
++ //
++ // See also: QSslSocketBackendPrivate::verify()
++ if (caCertificate.expiryDate() >= now) {
++ q_X509_STORE_add_cert(q_SSL_CTX_get_cert_store(sslContext->ctx), (X509 *)caCertificate.handle());
++ }
++ }
++
++ if (QSslSocketPrivate::s_loadRootCertsOnDemand && allowRootCertOnDemandLoading) {
++ // tell OpenSSL the directories where to look up the root certs on demand
++ const QList<QByteArray> unixDirs = QSslSocketPrivate::unixRootCertDirectories();
++ for (const QByteArray &unixDir : unixDirs)
++ q_SSL_CTX_load_verify_locations(sslContext->ctx, 0, unixDir.constData());
++ }
++
++ if (!sslContext->sslConfiguration.localCertificate().isNull()) {
++ // Require a private key as well.
++ if (sslContext->sslConfiguration.privateKey().isNull()) {
++ sslContext->errorStr = QSslSocket::tr("Cannot provide a certificate with no key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // Load certificate
++ if (!q_SSL_CTX_use_certificate(sslContext->ctx, (X509 *)sslContext->sslConfiguration.localCertificate().handle())) {
++ sslContext->errorStr = QSslSocket::tr("Error loading local certificate, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque) {
++ sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle());
++ } else {
++ // Load private key
++ sslContext->pkey = q_EVP_PKEY_new();
++ // before we were using EVP_PKEY_assign_R* functions and did not use EVP_PKEY_free.
++ // this lead to a memory leak. Now we use the *_set1_* functions which do not
++ // take ownership of the RSA/DSA key instance because the QSslKey already has ownership.
++ if (configuration.d->privateKey.algorithm() == QSsl::Rsa)
++ q_EVP_PKEY_set1_RSA(sslContext->pkey, reinterpret_cast<RSA *>(configuration.d->privateKey.handle()));
++ else if (configuration.d->privateKey.algorithm() == QSsl::Dsa)
++ q_EVP_PKEY_set1_DSA(sslContext->pkey, reinterpret_cast<DSA *>(configuration.d->privateKey.handle()));
++#ifndef OPENSSL_NO_EC
++ else if (configuration.d->privateKey.algorithm() == QSsl::Ec)
++ q_EVP_PKEY_set1_EC_KEY(sslContext->pkey, reinterpret_cast<EC_KEY *>(configuration.d->privateKey.handle()));
++#endif
++ }
++
++ if (!q_SSL_CTX_use_PrivateKey(sslContext->ctx, sslContext->pkey)) {
++ sslContext->errorStr = QSslSocket::tr("Error loading private key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++ if (configuration.d->privateKey.algorithm() == QSsl::Opaque)
++ sslContext->pkey = 0; // Don't free the private key, it belongs to QSslKey
++
++ // Check if the certificate matches the private key.
++ if (!q_SSL_CTX_check_private_key(sslContext->ctx)) {
++ sslContext->errorStr = QSslSocket::tr("Private key does not certify public key, %1").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ return;
++ }
++
++ // If we have any intermediate certificates then we need to add them to our chain
++ bool first = true;
++ for (const QSslCertificate &cert : qAsConst(configuration.d->localCertificateChain)) {
++ if (first) {
++ first = false;
++ continue;
++ }
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_EXTRA_CHAIN_CERT, 0,
++ q_X509_dup(reinterpret_cast<X509 *>(cert.handle())));
++ }
++ }
++
++ // Initialize peer verification.
++ if (sslContext->sslConfiguration.peerVerifyMode() == QSslSocket::VerifyNone) {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_NONE, 0);
++ } else {
++ q_SSL_CTX_set_verify(sslContext->ctx, SSL_VERIFY_PEER, q_X509Callback);
++ }
++
++ // Set verification depth.
++ if (sslContext->sslConfiguration.peerVerifyDepth() != 0)
++ q_SSL_CTX_set_verify_depth(sslContext->ctx, sslContext->sslConfiguration.peerVerifyDepth());
++
++ // set persisted session if the user set it
++ if (!configuration.sessionTicket().isEmpty())
++ sslContext->setSessionASN1(configuration.sessionTicket());
++
++ // Set temp DH params
++ 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->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
++ if (q_SSLeay() >= 0x10002000L) {
++ q_SSL_CTX_ctrl(sslContext->ctx, SSL_CTRL_SET_ECDH_AUTO, 1, NULL);
++ } else
++#endif
++ {
++ // Set temp ECDH params
++ EC_KEY *ecdh = 0;
++ ecdh = q_EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
++ q_SSL_CTX_set_tmp_ecdh(sslContext->ctx, ecdh);
++ q_EC_KEY_free(ecdh);
++ }
++#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)
++ // Set the curves to be used
++ if (q_SSLeay() >= 0x10002000L) {
++ // SSL_CTX_ctrl wants a non-const pointer as last argument,
++ // but let's avoid a copy into a temporary array
++ if (!q_SSL_CTX_ctrl(sslContext->ctx,
++ SSL_CTRL_SET_CURVES,
++ qcurves.size(),
++ const_cast<int *>(reinterpret_cast<const int *>(qcurves.data())))) {
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++ } else
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(OPENSSL_NO_EC)
++ {
++ // specific curves requested, but not possible to set -> error
++ sslContext->errorStr = msgErrorSettingEllipticCurves(QSslSocket::tr("OpenSSL version too old, need at least v1.0.2"));
++ sslContext->errorCode = QSslError::UnspecifiedError;
++ }
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+index 90687b0..5ebad82 100644
+--- a/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
++++ b/src/network/ssl/qssldiffiehellmanparameters_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk>
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -50,8 +51,8 @@
+ #include <QtCore/qdebug.h>
+ #endif
+
+-// For q_BN_is_word.
+ #include <openssl/bn.h>
++#include <openssl/dh.h>
+
+ QT_BEGIN_NAMESPACE
+
+@@ -62,13 +63,6 @@ static bool isSafeDH(DH *dh)
+
+ 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:
+ //
+@@ -81,11 +75,39 @@ static bool isSafeDH(DH *dh)
+ // Without the test, the IETF parameters would
+ // fail validation. For details, see Diffie-Hellman
+ // Parameter Check (when g = 2, must p mod 24 == 11?).
++#if QT_CONFIG(opensslv11)
++ // Mark p < 1024 bits as unsafe.
++ if (q_DH_bits(dh) < 1024)
++ return false;
++
++ if (q_DH_check(dh, &status) != 1)
++ return false;
++
++ const BIGNUM *p = nullptr;
++ const BIGNUM *q = nullptr;
++ const BIGNUM *g = nullptr;
++ q_DH_get0_pqg(dh, &p, &q, &g);
++
++ if (q_BN_is_word(const_cast<BIGNUM *>(g), DH_GENERATOR_2)) {
++ long residue = q_BN_mod_word(p, 24);
++ if (residue == 11 || residue == 23)
++ status &= ~DH_NOT_SUITABLE_GENERATOR;
++ }
++
++#else
++ // Mark p < 1024 bits as unsafe.
++ if (q_BN_num_bits(dh->p) < 1024)
++ return false;
++
++ if (q_DH_check(dh, &status) != 1)
++ return false;
++
+ if (q_BN_is_word(dh->g, DH_GENERATOR_2)) {
+ long residue = q_BN_mod_word(dh->p, 24);
+ if (residue == 11 || residue == 23)
+ status &= ~DH_NOT_SUITABLE_GENERATOR;
+ }
++#endif
+
+ bad |= DH_CHECK_P_NOT_PRIME;
+ bad |= DH_CHECK_P_NOT_SAFE_PRIME;
+diff --git a/src/network/ssl/qsslellipticcurve.h b/src/network/ssl/qsslellipticcurve.h
+index 2315660..57dda19 100644
+--- a/src/network/ssl/qsslellipticcurve.h
++++ b/src/network/ssl/qsslellipticcurve.h
+@@ -80,6 +80,7 @@ private:
+ friend Q_DECL_CONSTEXPR bool operator==(QSslEllipticCurve lhs, QSslEllipticCurve rhs) Q_DECL_NOTHROW;
+ friend Q_DECL_CONSTEXPR uint qHash(QSslEllipticCurve curve, uint seed) Q_DECL_NOTHROW;
+
++ friend class QSslContext;
+ friend class QSslSocketPrivate;
+ friend class QSslSocketBackendPrivate;
+ };
+diff --git a/src/network/ssl/qsslellipticcurve_openssl.cpp b/src/network/ssl/qsslellipticcurve_openssl.cpp
+index e18197b..8cd1483 100644
+--- a/src/network/ssl/qsslellipticcurve_openssl.cpp
++++ b/src/network/ssl/qsslellipticcurve_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -78,17 +79,18 @@ QSslEllipticCurve QSslEllipticCurve::fromShortName(const QString &name)
+ QSslEllipticCurve result;
+
+ #ifndef OPENSSL_NO_EC
+- const QByteArray curveNameLatin1 = name.toLatin1();
+
++ const QByteArray curveNameLatin1 = name.toLatin1();
+ int nid = q_OBJ_sn2nid(curveNameLatin1.data());
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (nid == 0 && q_SSLeay() >= 0x10002000L)
++ if (nid == 0 && QSslSocket::sslLibraryVersionNumber() >= 0x10002000L)
+ nid = q_EC_curve_nist2nid(curveNameLatin1.data());
+ #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+
+ result.id = nid;
+-#endif
++
++#endif // !OPENSSL_NO_EC
+
+ return result;
+ }
+diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp
+index 2611902..2b03af9 100644
+--- a/src/network/ssl/qsslkey_openssl.cpp
++++ b/src/network/ssl/qsslkey_openssl.cpp
+@@ -1,6 +1,7 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -87,33 +88,32 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey)
+ if (pkey == nullptr)
+ return false;
+
+- if (pkey->type == EVP_PKEY_RSA) {
++#if QT_CONFIG(opensslv11)
++ const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey));
++#else
++ const int keyType = pkey->type;
++#endif
++ if (keyType == EVP_PKEY_RSA) {
+ isNull = false;
+ algorithm = QSsl::Rsa;
+ type = QSsl::PrivateKey;
+
+- rsa = q_RSA_new();
+- memcpy(rsa, q_EVP_PKEY_get1_RSA(pkey), sizeof(RSA));
+-
++ rsa = q_EVP_PKEY_get1_RSA(pkey);
+ return true;
+- }
+- else if (pkey->type == EVP_PKEY_DSA) {
++ } else if (keyType == EVP_PKEY_DSA) {
+ isNull = false;
+ algorithm = QSsl::Dsa;
+ type = QSsl::PrivateKey;
+
+- dsa = q_DSA_new();
+- memcpy(dsa, q_EVP_PKEY_get1_DSA(pkey), sizeof(DSA));
+-
++ dsa = q_EVP_PKEY_get1_DSA(pkey);
+ return true;
+ }
+ #ifndef OPENSSL_NO_EC
+- else if (pkey->type == EVP_PKEY_EC) {
++ else if (keyType == EVP_PKEY_EC) {
+ isNull = false;
+ algorithm = QSsl::Ec;
+ type = QSsl::PrivateKey;
+- ec = q_EC_KEY_dup(q_EVP_PKEY_get1_EC_KEY(pkey));
+-
++ ec = q_EVP_PKEY_get1_EC_KEY(pkey);
+ return true;
+ }
+ #endif
+@@ -181,8 +181,8 @@ int QSslKeyPrivate::length() const
+ return -1;
+
+ switch (algorithm) {
+- case QSsl::Rsa: return q_BN_num_bits(rsa->n);
+- case QSsl::Dsa: return q_BN_num_bits(dsa->p);
++ case QSsl::Rsa: return q_RSA_bits(rsa);
++ case QSsl::Dsa: return q_DSA_bits(dsa);
+ #ifndef OPENSSL_NO_EC
+ case QSsl::Ec: return q_EC_GROUP_get_degree(q_EC_KEY_get0_group(ec));
+ #endif
+@@ -276,7 +276,13 @@ Qt::HANDLE QSslKeyPrivate::handle() const
+
+ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc)
+ {
+- EVP_CIPHER_CTX ctx;
++#if QT_CONFIG(opensslv11)
++ EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new();
++#else
++ EVP_CIPHER_CTX evpCipherContext;
++ EVP_CIPHER_CTX *ctx = &evpCipherContext;
++#endif
++
+ const EVP_CIPHER* type = 0;
+ int i = 0, len = 0;
+
+@@ -294,21 +300,44 @@ static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data,
+
+ QByteArray output;
+ output.resize(data.size() + EVP_MAX_BLOCK_LENGTH);
+- q_EVP_CIPHER_CTX_init(&ctx);
+- q_EVP_CipherInit(&ctx, type, NULL, NULL, enc);
+- q_EVP_CIPHER_CTX_set_key_length(&ctx, key.size());
++
++#if QT_CONFIG(opensslv11)
++ q_EVP_CIPHER_CTX_reset(ctx);
++#else
++ q_EVP_CIPHER_CTX_init(ctx);
++#endif
++
++ q_EVP_CipherInit(ctx, type, NULL, NULL, enc);
++ q_EVP_CIPHER_CTX_set_key_length(ctx, key.size());
+ if (cipher == QSslKeyPrivate::Rc2Cbc)
+- q_EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
+- q_EVP_CipherInit(&ctx, NULL,
++ q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL);
++
++#if QT_CONFIG(opensslv11)
++ // EVP_CipherInit in 1.1 resets the context thus making the calls above useless.
++ // We call EVP_CipherInit_ex instead.
++ q_EVP_CipherInit_ex(ctx, nullptr, nullptr,
++ reinterpret_cast<const unsigned char *>(key.constData()),
++ reinterpret_cast<const unsigned char *>(iv.constData()),
++ enc);
++#else
++ q_EVP_CipherInit(ctx, NULL,
+ reinterpret_cast<const unsigned char *>(key.constData()),
+ reinterpret_cast<const unsigned char *>(iv.constData()), enc);
+- q_EVP_CipherUpdate(&ctx,
++#endif // opensslv11
++
++ q_EVP_CipherUpdate(ctx,
+ reinterpret_cast<unsigned char *>(output.data()), &len,
+ reinterpret_cast<const unsigned char *>(data.constData()), data.size());
+- q_EVP_CipherFinal(&ctx,
++ q_EVP_CipherFinal(ctx,
+ reinterpret_cast<unsigned char *>(output.data()) + len, &i);
+ len += i;
+- q_EVP_CIPHER_CTX_cleanup(&ctx);
++
++#if QT_CONFIG(opensslv11)
++ q_EVP_CIPHER_CTX_reset(ctx);
++ q_EVP_CIPHER_CTX_free(ctx);
++#else
++ q_EVP_CIPHER_CTX_cleanup(ctx);
++#endif
+
+ return output.left(len);
+ }
+diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
+index ab82cdc..c838e01 100644
+--- a/src/network/ssl/qsslsocket_openssl.cpp
++++ b/src/network/ssl/qsslsocket_openssl.cpp
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 Governikus GmbH & Co. KG
+ ** Contact: https://www.qt.io/licensing/
+ **
+@@ -97,70 +97,6 @@ bool QSslSocketPrivate::s_loadRootCertsOnDemand = false;
+ int QSslSocketBackendPrivate::s_indexForSSLExtraData = -1;
+ #endif
+
+-/* \internal
+-
+- From OpenSSL's thread(3) manual page:
+-
+- OpenSSL can safely be used in multi-threaded applications provided that at
+- least two callback functions are set.
+-
+- locking_function(int mode, int n, const char *file, int line) is needed to
+- perform locking on shared data structures. (Note that OpenSSL uses a
+- number of global data structures that will be implicitly shared
+- whenever multiple threads use OpenSSL.) Multi-threaded
+- applications will crash at random if it is not set. ...
+- ...
+- id_function(void) is a function that returns a thread ID. It is not
+- needed on Windows nor on platforms where getpid() returns a different
+- ID for each thread (most notably Linux)
+-*/
+-class QOpenSslLocks
+-{
+-public:
+- inline QOpenSslLocks()
+- : initLocker(QMutex::Recursive),
+- locksLocker(QMutex::Recursive)
+- {
+- QMutexLocker locker(&locksLocker);
+- int numLocks = q_CRYPTO_num_locks();
+- locks = new QMutex *[numLocks];
+- memset(locks, 0, numLocks * sizeof(QMutex *));
+- }
+- inline ~QOpenSslLocks()
+- {
+- QMutexLocker locker(&locksLocker);
+- for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
+- delete locks[i];
+- delete [] locks;
+-
+- QSslSocketPrivate::deinitialize();
+- }
+- inline QMutex *lock(int num)
+- {
+- QMutexLocker locker(&locksLocker);
+- QMutex *tmp = locks[num];
+- if (!tmp)
+- tmp = locks[num] = new QMutex(QMutex::Recursive);
+- return tmp;
+- }
+-
+- QMutex *globalLock()
+- {
+- return &locksLocker;
+- }
+-
+- QMutex *initLock()
+- {
+- return &initLocker;
+- }
+-
+-private:
+- QMutex initLocker;
+- QMutex locksLocker;
+- QMutex **locks;
+-};
+-Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
+-
+ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ {
+ QString errorString;
+@@ -175,20 +111,6 @@ QString QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ }
+
+ extern "C" {
+-static void locking_function(int mode, int lockNumber, const char *, int)
+-{
+- QMutex *mutex = openssl_locks()->lock(lockNumber);
+-
+- // Lock or unlock it
+- if (mode & CRYPTO_LOCK)
+- mutex->lock();
+- else
+- mutex->unlock();
+-}
+-static unsigned long id_function()
+-{
+- return (quintptr)QThread::currentThreadId();
+-}
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+ static unsigned int q_ssl_psk_client_callback(SSL *ssl,
+@@ -227,7 +149,7 @@ QSslSocketBackendPrivate::~QSslSocketBackendPrivate()
+ destroySslContext();
+ }
+
+-QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher)
++QSslCipher QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher)
+ {
+ QSslCipher ciph;
+
+@@ -283,6 +205,7 @@ struct QSslErrorList
+ QMutex mutex;
+ QVector<QSslErrorEntry> errors;
+ };
++
+ Q_GLOBAL_STATIC(QSslErrorList, _q_sslErrorList)
+
+ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
+@@ -312,7 +235,7 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx)
+ }
+ #endif
+ }
+- // Always return OK to allow verification to continue. We're handle the
++ // Always return OK to allow verification to continue. We handle the
+ // errors gracefully after collecting all errors, after verification has
+ // completed.
+ return 1;
+@@ -397,7 +320,7 @@ bool QSslSocketBackendPrivate::initSslContext()
+ if (configuration.protocol != QSsl::SslV2 &&
+ configuration.protocol != QSsl::SslV3 &&
+ configuration.protocol != QSsl::UnknownProtocol &&
+- mode == QSslSocket::SslClientMode && q_SSLeay() >= 0x00090806fL) {
++ mode == QSslSocket::SslClientMode && QSslSocket::sslLibraryVersionNumber() >= 0x00090806fL) {
+ // Set server hostname on TLS extension. RFC4366 section 3.1 requires it in ACE format.
+ QString tlsHostName = verificationPeerName.isEmpty() ? q->peerName() : verificationPeerName;
+ if (tlsHostName.isEmpty())
+@@ -438,13 +361,13 @@ bool QSslSocketBackendPrivate::initSslContext()
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+ // Save a pointer to this object into the SSL structure.
+- if (q_SSLeay() >= 0x10001000L)
++ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L)
+ q_SSL_set_ex_data(ssl, s_indexForSSLExtraData, this);
+ #endif
+
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L && !defined(OPENSSL_NO_PSK)
+ // Set the client callback for PSK
+- if (q_SSLeay() >= 0x10001000L) {
++ if (QSslSocket::sslLibraryVersionNumber() >= 0x10001000L) {
+ if (mode == QSslSocket::SslClientMode)
+ q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback);
+ else if (mode == QSslSocket::SslServerMode)
+@@ -466,16 +389,6 @@ void QSslSocketBackendPrivate::destroySslContext()
+
+ /*!
+ \internal
+-*/
+-void QSslSocketPrivate::deinitialize()
+-{
+- q_CRYPTO_set_id_callback(0);
+- q_CRYPTO_set_locking_callback(0);
+- q_ERR_free_strings();
+-}
+-
+-/*!
+- \internal
+
+ Does the minimum amount of initialization to determine whether SSL
+ is supported or not.
+@@ -486,91 +399,6 @@ bool QSslSocketPrivate::supportsSsl()
+ return ensureLibraryLoaded();
+ }
+
+-bool QSslSocketPrivate::ensureLibraryLoaded()
+-{
+- if (!q_resolveOpenSslSymbols())
+- return false;
+-
+- // Check if the library itself needs to be initialized.
+- QMutexLocker locker(openssl_locks()->initLock());
+-
+- if (!s_libraryLoaded) {
+- s_libraryLoaded = true;
+-
+- // Initialize OpenSSL.
+- q_CRYPTO_set_id_callback(id_function);
+- q_CRYPTO_set_locking_callback(locking_function);
+- if (q_SSL_library_init() != 1)
+- return false;
+- q_SSL_load_error_strings();
+- q_OpenSSL_add_all_algorithms();
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- if (q_SSLeay() >= 0x10001000L)
+- QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
+-#endif
+-
+- // Initialize OpenSSL's random seed.
+- if (!q_RAND_status()) {
+- qWarning("Random number generator not seeded, disabling SSL support");
+- return false;
+- }
+- }
+- return true;
+-}
+-
+-void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
+-{
+- QMutexLocker locker(openssl_locks()->initLock());
+- if (s_loadedCiphersAndCerts)
+- return;
+- s_loadedCiphersAndCerts = true;
+-
+- resetDefaultCiphers();
+- resetDefaultEllipticCurves();
+-
+-#if QT_CONFIG(library)
+- //load symbols needed to receive certificates from system store
+-#if defined(Q_OS_WIN)
+- HINSTANCE hLib = LoadLibraryW(L"Crypt32");
+- if (hLib) {
+- ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
+- ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
+- ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
+- if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
+- qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
+- } else {
+- qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
+- }
+-#elif defined(Q_OS_QNX)
+- s_loadRootCertsOnDemand = true;
+-#elif defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
+- // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
+- QList<QByteArray> dirs = unixRootCertDirectories();
+- QStringList symLinkFilter;
+- symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
+- for (int a = 0; a < dirs.count(); ++a) {
+- QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
+- if (iterator.hasNext()) {
+- s_loadRootCertsOnDemand = true;
+- break;
+- }
+- }
+-#endif
+-#endif // QT_CONFIG(library)
+- // if on-demand loading was not enabled, load the certs now
+- if (!s_loadRootCertsOnDemand)
+- setDefaultCaCertificates(systemCaCertificates());
+-#ifdef Q_OS_WIN
+- //Enabled for fetching additional root certs from windows update on windows 6+
+- //This flag is set false by setDefaultCaCertificates() indicating the app uses
+- //its own cert bundle rather than the system one.
+- //Same logic that disables the unix on demand cert loading.
+- //Unlike unix, we do preload the certificates from the cert store.
+- if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
+- s_loadRootCertsOnDemand = true;
+-#endif
+-}
+
+ /*!
+ \internal
+@@ -587,26 +415,6 @@ void QSslSocketPrivate::ensureInitialized()
+ ensureCiphersAndCertsLoaded();
+ }
+
+-long QSslSocketPrivate::sslLibraryVersionNumber()
+-{
+- if (!supportsSsl())
+- return 0;
+-
+- return q_SSLeay();
+-}
+-
+-QString QSslSocketPrivate::sslLibraryVersionString()
+-{
+- if (!supportsSsl())
+- return QString();
+-
+- const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
+- if (!versionString)
+- return QString();
+-
+- return QString::fromLatin1(versionString);
+-}
+-
+ long QSslSocketPrivate::sslLibraryBuildVersionNumber()
+ {
+ return OPENSSL_VERSION_NUMBER;
+@@ -628,7 +436,11 @@ QString QSslSocketPrivate::sslLibraryBuildVersionString()
+ */
+ void QSslSocketPrivate::resetDefaultCiphers()
+ {
++#if QT_CONFIG(opensslv11)
++ SSL_CTX *myCtx = q_SSL_CTX_new(q_TLS_client_method());
++#else
+ SSL_CTX *myCtx = q_SSL_CTX_new(q_SSLv23_client_method());
++#endif
+ SSL *mySsl = q_SSL_new(myCtx);
+
+ QList<QSslCipher> ciphers;
+@@ -664,7 +476,7 @@ void QSslSocketPrivate::resetDefaultEllipticCurves()
+ QVector<QSslEllipticCurve> curves;
+
+ #ifndef OPENSSL_NO_EC
+- const size_t curveCount = q_EC_get_builtin_curves(NULL, 0);
++ const size_t curveCount = q_EC_get_builtin_curves(nullptr, 0);
+
+ QVarLengthArray<EC_builtin_curve> builtinCurves(static_cast<int>(curveCount));
+
+@@ -698,13 +510,14 @@ QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()
+ if (ptrCertOpenSystemStoreW && ptrCertFindCertificateInStore && ptrCertCloseStore) {
+ HCERTSTORE hSystemStore;
+ hSystemStore = ptrCertOpenSystemStoreW(0, L"ROOT");
+- if(hSystemStore) {
+- PCCERT_CONTEXT pc = NULL;
+- while(1) {
+- pc = ptrCertFindCertificateInStore( hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, pc);
+- if(!pc)
++ if (hSystemStore) {
++ PCCERT_CONTEXT pc = nullptr;
++ while (1) {
++ pc = ptrCertFindCertificateInStore(hSystemStore, X509_ASN_ENCODING, 0, CERT_FIND_ANY, nullptr, pc);
++ if (!pc)
+ break;
+- QByteArray der((const char *)(pc->pbCertEncoded), static_cast<int>(pc->cbCertEncoded));
++ QByteArray der(reinterpret_cast<const char *>(pc->pbCertEncoded),
++ static_cast<int>(pc->cbCertEncoded));
+ QSslCertificate cert(der, QSsl::Der);
+ systemCerts.append(cert);
+ }
+@@ -1502,14 +1315,8 @@ QSslCipher QSslSocketBackendPrivate::sessionCipher() const
+ {
+ if (!ssl)
+ return QSslCipher();
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- // FIXME This is fairly evil, but needed to keep source level compatibility
+- // with the OpenSSL 0.9.x implementation at maximum -- some other functions
+- // don't take a const SSL_CIPHER* when they should
+- SSL_CIPHER *sessionCipher = const_cast<SSL_CIPHER *>(q_SSL_get_current_cipher(ssl));
+-#else
+- SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
+-#endif
++
++ const SSL_CIPHER *sessionCipher = q_SSL_get_current_cipher(ssl);
+ return sessionCipher ? QSslCipher_from_SSL_CIPHER(sessionCipher) : QSslCipher();
+ }
+
+@@ -1535,112 +1342,6 @@ QSsl::SslProtocol QSslSocketBackendPrivate::sessionProtocol() const
+ return QSsl::UnknownProtocol;
+ }
+
+-void QSslSocketBackendPrivate::continueHandshake()
+-{
+- Q_Q(QSslSocket);
+- // if we have a max read buffer size, reset the plain socket's to match
+- if (readBufferMaxSize)
+- plainSocket->setReadBufferSize(readBufferMaxSize);
+-
+- if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
+- configuration.peerSessionShared = true;
+-
+-#ifdef QT_DECRYPT_SSL_TRAFFIC
+- if (ssl->session && ssl->s3) {
+- const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
+- QByteArray masterKey(mk, ssl->session->master_key_length);
+- const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
+- QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
+-
+- // different format, needed for e.g. older Wireshark versions:
+-// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
+-// QByteArray sessionID(sid, ssl->session->session_id_length);
+-// QByteArray debugLineRSA("RSA Session-ID:");
+-// debugLineRSA.append(sessionID.toHex().toUpper());
+-// debugLineRSA.append(" Master-Key:");
+-// debugLineRSA.append(masterKey.toHex().toUpper());
+-// debugLineRSA.append("\n");
+-
+- QByteArray debugLineClientRandom("CLIENT_RANDOM ");
+- debugLineClientRandom.append(clientRandom.toHex().toUpper());
+- debugLineClientRandom.append(" ");
+- debugLineClientRandom.append(masterKey.toHex().toUpper());
+- debugLineClientRandom.append("\n");
+-
+- QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
+- QFile file(sslKeyFile);
+- if (!file.open(QIODevice::Append))
+- qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
+- if (!file.write(debugLineClientRandom))
+- qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
+- file.close();
+- } else {
+- qCWarning(lcSsl, "could not decrypt SSL traffic");
+- }
+-#endif
+-
+- // Cache this SSL session inside the QSslContext
+- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
+- if (!sslContextPointer->cacheSession(ssl)) {
+- sslContextPointer.clear(); // we could not cache the session
+- } else {
+- // Cache the session for permanent usage as well
+- if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
+- if (!sslContextPointer->sessionASN1().isEmpty())
+- configuration.sslSession = sslContextPointer->sessionASN1();
+- configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
+- }
+- }
+- }
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+-
+- configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
+- if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
+- // we could not agree -> be conservative and use HTTP/1.1
+- configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
+- } else {
+- const unsigned char *proto = 0;
+- unsigned int proto_len = 0;
+-#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
+- configuration.nextNegotiatedProtocol.clear();
+- }
+-#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
+-
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
+- EVP_PKEY *key;
+- if (q_SSL_get_server_tmp_key(ssl, &key))
+- configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
+- }
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
+-
+- connectionEncrypted = true;
+- emit q->encrypted();
+- if (autoStartHandshake && pendingClose) {
+- pendingClose = false;
+- q->disconnectFromHost();
+- }
+-}
+-
+ QList<QSslCertificate> QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509)
+ {
+ ensureInitialized();
+@@ -1694,12 +1395,12 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
+ QMutexLocker sslErrorListMutexLocker(&_q_sslErrorList()->mutex);
+
+ // Register a custom callback to get all verification errors.
+- X509_STORE_set_verify_cb_func(certStore, q_X509Callback);
++ q_X509_STORE_set_verify_cb(certStore, q_X509Callback);
+
+ // Build the chain of intermediate certificates
+ STACK_OF(X509) *intermediates = 0;
+ if (certificateChain.length() > 1) {
+- intermediates = (STACK_OF(X509) *) q_sk_new_null();
++ intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null();
+
+ if (!intermediates) {
+ q_X509_STORE_free(certStore);
+@@ -1713,11 +1414,8 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
+ first = false;
+ continue;
+ }
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_push( (_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
+-#else
+- q_sk_push( (STACK *)intermediates, reinterpret_cast<char *>(cert.handle()));
+-#endif
++
++ q_OPENSSL_sk_push((OPENSSL_STACK *)intermediates, reinterpret_cast<X509 *>(cert.handle()));
+ }
+ }
+
+@@ -1741,11 +1439,7 @@ QList<QSslError> QSslSocketBackendPrivate::verify(const QList<QSslCertificate> &
+ (void) q_X509_verify_cert(storeContext);
+
+ q_X509_STORE_CTX_free(storeContext);
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+- q_sk_free( (_STACK *) intermediates);
+-#else
+- q_sk_free( (STACK *) intermediates);
+-#endif
++ q_OPENSSL_sk_free((OPENSSL_STACK *)intermediates);
+
+ // Now process the errors
+ const auto errorList = std::move(_q_sslErrorList()->errors);
+@@ -1819,7 +1513,8 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
+ // Convert to Qt types
+ if (!key->d->fromEVP_PKEY(pkey)) {
+ qCWarning(lcSsl, "Unable to convert private key");
+- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
++ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
++ reinterpret_cast<void (*)(void *)>(q_OPENSSL_sk_free));
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+@@ -1834,7 +1529,11 @@ bool QSslSocketBackendPrivate::importPkcs12(QIODevice *device,
+ *caCertificates = QSslSocketBackendPrivate::STACKOFX509_to_QSslCertificates(ca);
+
+ // Clean up
+- q_sk_pop_free(reinterpret_cast<STACK *>(ca), reinterpret_cast<void(*)(void*)>(q_sk_free));
++ // TODO: verify ASAP, in the past we had sk_pop_free with q_OPENSSL_sk_free
++ // which seems to be blatantly wrong and even crashes with 1.1.
++ q_OPENSSL_sk_pop_free(reinterpret_cast<OPENSSL_STACK *>(ca),
++ reinterpret_cast<void (*)(void *)>(q_X509_free));
++
+ q_X509_free(x509);
+ q_EVP_PKEY_free(pkey);
+ q_PKCS12_free(p12);
+diff --git a/src/network/ssl/qsslsocket_openssl11.cpp b/src/network/ssl/qsslsocket_openssl11.cpp
+new file mode 100644
+index 0000000..b6d1894
+--- /dev/null
++++ b/src/network/ssl/qsslsocket_openssl11.cpp
+@@ -0,0 +1,285 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 Governikus GmbH & Co. KG
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++//#define QT_DECRYPT_SSL_TRAFFIC
++
++#include "qssl_p.h"
++#include "qsslsocket_openssl_p.h"
++#include "qsslsocket_openssl_symbols_p.h"
++#include "qsslsocket.h"
++#include "qsslkey.h"
++
++#include <QtCore/qdebug.h>
++#include <QtCore/qdir.h>
++#include <QtCore/qdiriterator.h>
++#include <QtCore/qfile.h>
++#include <QtCore/qmutex.h>
++#include <QtCore/qlibrary.h>
++
++QT_BEGIN_NAMESPACE
++
++Q_GLOBAL_STATIC_WITH_ARGS(QMutex, qt_opensslInitMutex, (QMutex::Recursive))
++
++/*!
++ \internal
++*/
++void QSslSocketPrivate::deinitialize()
++{
++ // This function exists only for compatibility with the pre-11 code,
++ // where deinitialize() actually does some cleanup. To be discarded
++ // once we retire < 1.1.
++}
++
++bool QSslSocketPrivate::ensureLibraryLoaded()
++{
++ if (!q_resolveOpenSslSymbols())
++ return false;
++
++ const QMutexLocker locker(qt_opensslInitMutex);
++
++ if (!s_libraryLoaded) {
++ s_libraryLoaded = true;
++
++ // Initialize OpenSSL.
++ if (q_OPENSSL_init_ssl(0, nullptr) != 1)
++ return false;
++ q_SSL_load_error_strings();
++ q_OpenSSL_add_all_algorithms();
++
++ QSslSocketBackendPrivate::s_indexForSSLExtraData
++ = q_CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_SSL, 0L, nullptr, nullptr,
++ nullptr, nullptr);
++
++ // Initialize OpenSSL's random seed.
++ if (!q_RAND_status()) {
++ qWarning("Random number generator not seeded, disabling SSL support");
++ return false;
++ }
++ }
++ return true;
++}
++
++void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
++{
++ const QMutexLocker locker(qt_opensslInitMutex);
++
++ if (s_loadedCiphersAndCerts)
++ return;
++ s_loadedCiphersAndCerts = true;
++
++ resetDefaultCiphers();
++ resetDefaultEllipticCurves();
++
++#if QT_CONFIG(library)
++ //load symbols needed to receive certificates from system store
++#if defined(Q_OS_WIN)
++ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
++ if (hLib) {
++ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
++ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
++ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
++ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
++ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
++ } else {
++ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
++ }
++#elif defined(Q_OS_QNX)
++ s_loadRootCertsOnDemand = true;
++#elif defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
++ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
++ QList<QByteArray> dirs = unixRootCertDirectories();
++ QStringList symLinkFilter;
++ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
++ for (int a = 0; a < dirs.count(); ++a) {
++ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
++ if (iterator.hasNext()) {
++ s_loadRootCertsOnDemand = true;
++ break;
++ }
++ }
++#endif
++#endif // QT_CONFIG(library)
++ // if on-demand loading was not enabled, load the certs now
++ if (!s_loadRootCertsOnDemand)
++ setDefaultCaCertificates(systemCaCertificates());
++#ifdef Q_OS_WIN
++ //Enabled for fetching additional root certs from windows update on windows 6+
++ //This flag is set false by setDefaultCaCertificates() indicating the app uses
++ //its own cert bundle rather than the system one.
++ //Same logic that disables the unix on demand cert loading.
++ //Unlike unix, we do preload the certificates from the cert store.
++ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
++ s_loadRootCertsOnDemand = true;
++#endif
++}
++
++long QSslSocketPrivate::sslLibraryVersionNumber()
++{
++ if (!supportsSsl())
++ return 0;
++
++ return q_OpenSSL_version_num();
++}
++
++QString QSslSocketPrivate::sslLibraryVersionString()
++{
++ if (!supportsSsl())
++ return QString();
++
++ const char *versionString = q_OpenSSL_version(OPENSSL_VERSION);
++ if (!versionString)
++ return QString();
++
++ return QString::fromLatin1(versionString);
++}
++
++void QSslSocketBackendPrivate::continueHandshake()
++{
++ Q_Q(QSslSocket);
++ // if we have a max read buffer size, reset the plain socket's to match
++ if (readBufferMaxSize)
++ plainSocket->setReadBufferSize(readBufferMaxSize);
++
++ if (q_SSL_session_reused(ssl))
++ configuration.peerSessionShared = true;
++
++#ifdef QT_DECRYPT_SSL_TRAFFIC
++ if (q_SSL_get_session(ssl)) {
++ size_t master_key_len = q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl), 0, 0);
++ size_t client_random_len = q_SSL_get_client_random(ssl, 0, 0);
++ QByteArray masterKey(int(master_key_len), 0); // Will not overflow
++ QByteArray clientRandom(int(client_random_len), 0); // Will not overflow
++
++ q_SSL_SESSION_get_master_key(q_SSL_get_session(ssl),
++ reinterpret_cast<unsigned char*>(masterKey.data()),
++ masterKey.size());
++ q_SSL_get_client_random(ssl, reinterpret_cast<unsigned char *>(clientRandom.data()),
++ clientRandom.size());
++
++ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
++ debugLineClientRandom.append(clientRandom.toHex().toUpper());
++ debugLineClientRandom.append(" ");
++ debugLineClientRandom.append(masterKey.toHex().toUpper());
++ debugLineClientRandom.append("\n");
++
++ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
++ QFile file(sslKeyFile);
++ if (!file.open(QIODevice::Append))
++ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
++ if (!file.write(debugLineClientRandom))
++ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
++ file.close();
++ } else {
++ qCWarning(lcSsl, "could not decrypt SSL traffic");
++ }
++#endif
++
++ // Cache this SSL session inside the QSslContext
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
++ if (!sslContextPointer->cacheSession(ssl)) {
++ sslContextPointer.clear(); // we could not cache the session
++ } else {
++ // Cache the session for permanent usage as well
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
++ if (!sslContextPointer->sessionASN1().isEmpty())
++ configuration.sslSession = sslContextPointer->sessionASN1();
++ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
++ }
++ }
++ }
++
++#if !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
++ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
++ // we could not agree -> be conservative and use HTTP/1.1
++ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
++ } else {
++ const unsigned char *proto = 0;
++ unsigned int proto_len = 0;
++
++ 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 ...
++ q_SSL_get0_next_proto_negotiated(ssl, &proto, &proto_len);
++ }
++
++ if (proto_len)
++ configuration.nextNegotiatedProtocol = QByteArray(reinterpret_cast<const char *>(proto), proto_len);
++ else
++ configuration.nextNegotiatedProtocol.clear();
++ }
++#endif // !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ if (mode == QSslSocket::SslClientMode) {
++ EVP_PKEY *key;
++ if (q_SSL_get_server_tmp_key(ssl, &key))
++ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
++ }
++
++ connectionEncrypted = true;
++ emit q->encrypted();
++ if (autoStartHandshake && pendingClose) {
++ pendingClose = false;
++ q->disconnectFromHost();
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/src/network/ssl/qsslsocket_openssl11_symbols_p.h b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+new file mode 100644
+index 0000000..2980b3d
+--- /dev/null
++++ b/src/network/ssl/qsslsocket_openssl11_symbols_p.h
+@@ -0,0 +1,132 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++#ifndef QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
++#define QSSLSOCKET_OPENSSL11_SYMBOLS_P_H
++
++//
++// W A R N I N G
++// -------------
++//
++// This file is not part of the Qt API. It exists purely as an
++// implementation detail. This header file may change from version to
++// version without notice, or even be removed.
++//
++// We mean it.
++//
++
++// Note: this file does not have QT_BEGIN_NAMESPACE/QT_END_NAMESPACE, it's done
++// in qsslsocket_openssl_symbols_p.h.
++
++#ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
++#error "You are not supposed to use this header file, include qsslsocket_openssl_symbols_p.h instead"
++#endif
++
++const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x);
++
++Q_AUTOTEST_EXPORT BIO *q_BIO_new(const BIO_METHOD *a);
++Q_AUTOTEST_EXPORT const BIO_METHOD *q_BIO_s_mem();
++
++int q_DSA_bits(DSA *a);
++int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c);
++int q_EVP_PKEY_base_id(EVP_PKEY *a);
++int q_RSA_bits(RSA *a);
++int q_OPENSSL_sk_num(OPENSSL_STACK *a);
++void q_OPENSSL_sk_pop_free(OPENSSL_STACK *a, void (*b)(void *));
++OPENSSL_STACK *q_OPENSSL_sk_new_null();
++void q_OPENSSL_sk_push(OPENSSL_STACK *st, void *data);
++void q_OPENSSL_sk_free(OPENSSL_STACK *a);
++void * q_OPENSSL_sk_value(OPENSSL_STACK *a, int b);
++int q_SSL_session_reused(SSL *a);
++unsigned long q_SSL_CTX_set_options(SSL_CTX *ctx, unsigned long op);
++int q_OPENSSL_init_ssl(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
++size_t q_SSL_get_client_random(SSL *a, unsigned char *out, size_t outlen);
++size_t q_SSL_SESSION_get_master_key(const SSL_SESSION *session, unsigned char *out, size_t outlen);
++int q_CRYPTO_get_ex_new_index(int class_index, long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
++const SSL_METHOD *q_TLS_method();
++const SSL_METHOD *q_TLS_client_method();
++const SSL_METHOD *q_TLS_server_method();
++ASN1_TIME *q_X509_getm_notBefore(X509 *a);
++ASN1_TIME *q_X509_getm_notAfter(X509 *a);
++
++long q_X509_get_version(X509 *a);
++EVP_PKEY *q_X509_get_pubkey(X509 *a);
++void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify_cb);
++STACK_OF(X509) *q_X509_STORE_CTX_get0_chain(X509_STORE_CTX *ctx);
++void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g);
++int q_DH_bits(DH *dh);
++
++# define q_SSL_load_error_strings() q_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_SSL_STRINGS \
++ | OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL)
++
++#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_OPENSSL_sk_num)(st)
++#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_OPENSSL_sk_value)(st, i)
++
++#define q_OPENSSL_add_all_algorithms_conf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
++ | OPENSSL_INIT_ADD_ALL_DIGESTS \
++ | OPENSSL_INIT_LOAD_CONFIG, NULL)
++#define q_OPENSSL_add_all_algorithms_noconf() q_OPENSSL_init_crypto(OPENSSL_INIT_ADD_ALL_CIPHERS \
++ | OPENSSL_INIT_ADD_ALL_DIGESTS, NULL)
++
++int q_OPENSSL_init_crypto(uint64_t opts, const OPENSSL_INIT_SETTINGS *settings);
++void q_CRYPTO_free(void *str, const char *file, int line);
++
++long q_OpenSSL_version_num();
++const char *q_OpenSSL_version(int type);
++
++unsigned long q_SSL_SESSION_get_ticket_lifetime_hint(const SSL_SESSION *session);
++
++#endif
+diff --git a/src/network/ssl/qsslsocket_openssl_p.h b/src/network/ssl/qsslsocket_openssl_p.h
+index b2adb3e..7f9e884 100644
+--- a/src/network/ssl/qsslsocket_openssl_p.h
++++ b/src/network/ssl/qsslsocket_openssl_p.h
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -98,8 +98,8 @@
+ #include <openssl/crypto.h>
+ #include <openssl/tls1.h>
+
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-typedef _STACK STACK;
++#if QT_CONFIG(opensslv11)
++#include <openssl/dh.h>
+ #endif
+
+ QT_BEGIN_NAMESPACE
+@@ -151,7 +151,7 @@ public:
+ #endif
+
+ Q_AUTOTEST_EXPORT static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions);
+- static QSslCipher QSslCipher_from_SSL_CIPHER(SSL_CIPHER *cipher);
++ static QSslCipher QSslCipher_from_SSL_CIPHER(const SSL_CIPHER *cipher);
+ static QList<QSslCertificate> STACKOFX509_to_QSslCertificates(STACK_OF(X509) *x509);
+ static QList<QSslError> verify(const QList<QSslCertificate> &certificateChain, const QString &hostName);
+ static QString getErrorsFromOpenSsl();
+diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp
+index c344a94..0ef8bf6 100644
+--- a/src/network/ssl/qsslsocket_openssl_symbols.cpp
++++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp
+@@ -1,7 +1,8 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
++** Copyright (C) 2016 Richard J. Moore <rich@kde.org>
+ ** Contact: https://www.qt.io/licensing/
+ **
+ ** This file is part of the QtNetwork module of the Qt Toolkit.
+@@ -136,49 +137,195 @@ void qsslSocketCannotResolveSymbolWarning(const char *functionName)
+
+ #endif // QT_LINKED_OPENSSL
+
++#if QT_CONFIG(opensslv11)
++
++// Below are the functions first introduced in version 1.1:
++
++DEFINEFUNC(const unsigned char *, ASN1_STRING_get0_data, const ASN1_STRING *a, a, return 0, return)
++DEFINEFUNC2(int, OPENSSL_init_ssl, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
++DEFINEFUNC2(int, OPENSSL_init_crypto, uint64_t opts, opts, const OPENSSL_INIT_SETTINGS *settings, settings, return 0, return)
++DEFINEFUNC(BIO *, BIO_new, const BIO_METHOD *a, a, return 0, return)
++DEFINEFUNC(const BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
++DEFINEFUNC2(int, BN_is_word, BIGNUM *a, a, BN_ULONG w, w, return 0, return)
++DEFINEFUNC(int, EVP_CIPHER_CTX_reset, EVP_CIPHER_CTX *c, c, return 0, return)
++DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return)
++DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return)
++DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return)
++DEFINEFUNC(int, OPENSSL_sk_num, OPENSSL_STACK *a, a, return -1, return)
++DEFINEFUNC2(void, OPENSSL_sk_pop_free, OPENSSL_STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
++DEFINEFUNC(OPENSSL_STACK *, OPENSSL_sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMMYARG)
++DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return 0, return)
++DEFINEFUNC(int, SSL_session_reused, SSL *a, a, return 0, return)
++DEFINEFUNC2(unsigned long, SSL_CTX_set_options, SSL_CTX *ctx, ctx, unsigned long op, op, return 0, return)
++DEFINEFUNC3(size_t, SSL_get_client_random, SSL *a, a, unsigned char *out, out, size_t outlen, outlen, return 0, return)
++DEFINEFUNC3(size_t, SSL_SESSION_get_master_key, const SSL_SESSION *ses, ses, unsigned char *out, out, size_t outlen, outlen, return 0, return)
++DEFINEFUNC6(int, CRYPTO_get_ex_new_index, int class_index, class_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
++
++DEFINEFUNC(const SSL_METHOD *, TLS_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLS_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return 0, return)
++DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return 0, return)
++DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return)
++DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return 0, return)
++DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG)
++DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return 0, return)
++DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG)
++DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return)
++DEFINEFUNC(const char *, OpenSSL_version, int a, a, return 0, return)
++DEFINEFUNC(unsigned long, SSL_SESSION_get_ticket_lifetime_hint, const SSL_SESSION *session, session, return 0, return)
++DEFINEFUNC4(void, DH_get0_pqg, const DH *dh, dh, const BIGNUM **p, p, const BIGNUM **q, q, const BIGNUM **g, g, return, DUMMYARG)
++DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return)
++
++#else // QT_CONFIG(opensslv11)
++
++// Functions below are either deprecated or removed in OpenSSL >= 1.1:
++
++DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
++
+ #ifdef SSLEAY_MACROS
+ DEFINEFUNC3(void *, ASN1_dup, i2d_of_void *a, a, d2i_of_void *b, b, char *c, c, return 0, return)
+ #endif
++DEFINEFUNC2(BIO *, BIO_new_file, const char *filename, filename, const char *mode, mode, return 0, return)
++DEFINEFUNC(void, ERR_clear_error, DUMMYARG, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
++DEFINEFUNC(BIO_METHOD *, BIO_s_mem, void, DUMMYARG, return 0, return)
++DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
++DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
++DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
++DEFINEFUNC(unsigned long, ERR_peek_last_error, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++
++#ifdef SSLEAY_MACROS
++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)
++#endif // SSLEAY_MACROS
++
++DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
++DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
++DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
++#else
++DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
++DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
++DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10000000L
++
++DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
++DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
++
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10001000L
++
++#if OPENSSL_VERSION_NUMBER >= 0x10000000L
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#else
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
++#ifndef OPENSSL_NO_SSL2
++DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
++#endif
++
++DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
++
++#ifdef SSLEAY_MACROS
++DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
++DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
++#ifndef OPENSSL_NO_EC
++DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
++#endif
++DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
++DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
++#ifndef OPENSSL_NO_EC
++DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
++#endif
++#endif
++DEFINEFUNC(char *, CONF_get1_default_config_file, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
++DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
++DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
++
++#endif // QT_CONFIG(opensslv11)
++
+ DEFINEFUNC(long, ASN1_INTEGER_get, ASN1_INTEGER *a, a, return 0, return)
+-DEFINEFUNC(unsigned char *, ASN1_STRING_data, ASN1_STRING *a, a, return 0, return)
+ DEFINEFUNC(int, ASN1_STRING_length, ASN1_STRING *a, a, return 0, return)
+-DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return);
++DEFINEFUNC2(int, ASN1_STRING_to_UTF8, unsigned char **a, a, ASN1_STRING *b, b, return 0, return)
+ DEFINEFUNC4(long, BIO_ctrl, BIO *a, a, int b, b, long c, c, void *d, d, return -1, return)
+ DEFINEFUNC(int, BIO_free, BIO *a, a, return 0, return)
+-DEFINEFUNC(BIO *, BIO_new, BIO_METHOD *a, a, return 0, return)
+ DEFINEFUNC2(BIO *, BIO_new_mem_buf, void *a, a, int b, b, return 0, return)
+ 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 static_cast<BN_ULONG>(-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)
+ #endif
+-DEFINEFUNC(int, CRYPTO_num_locks, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(void, CRYPTO_set_locking_callback, void (*a)(int, int, const char *, int), a, return, DUMMYARG)
+-DEFINEFUNC(void, CRYPTO_set_id_callback, unsigned long (*a)(), a, return, DUMMYARG)
+-DEFINEFUNC(void, CRYPTO_free, void *a, a, return, DUMMYARG)
+ DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG)
+ DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c, return 0, return)
+ DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return)
+ DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG)
+-DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+-DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
+-DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return);
++DEFINEFUNC(EVP_CIPHER_CTX *, EVP_CIPHER_CTX_new, void, DUMMYARG, return 0, return)
++DEFINEFUNC(void, EVP_CIPHER_CTX_free, EVP_CIPHER_CTX *a, a, return, DUMMYARG)
++DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return)
+ DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return)
+-DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return);
+-DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return);
+-DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return);
++DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
++DEFINEFUNC6(int, EVP_CipherInit_ex, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *cipher, cipher, ENGINE *impl, impl, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return)
++DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return)
++DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return)
++DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return)
+ DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return)
+ DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return)
+@@ -202,10 +349,8 @@ DEFINEFUNC3(int, i2t_ASN1_OBJECT, char *a, a, int b, b, ASN1_OBJECT *c, c, retur
+ DEFINEFUNC4(int, OBJ_obj2txt, char *a, a, int b, b, ASN1_OBJECT *c, c, int d, d, return -1, return)
+
+ DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return)
+-#ifdef SSLEAY_MACROS
+-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
++
++#ifndef SSLEAY_MACROS
+ 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)
+@@ -218,7 +363,7 @@ DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CI
+ #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
++#endif // !SSLEAY_MACROS
+ 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)
+@@ -234,23 +379,10 @@ DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG)
+ DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return)
+ DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return 0, return)
+ DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG)
+-DEFINEFUNC(int, sk_num, STACK *a, a, return -1, return)
+-DEFINEFUNC2(void, sk_pop_free, STACK *a, a, void (*b)(void*), b, return, DUMMYARG)
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-DEFINEFUNC(_STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC2(void, sk_push, _STACK *a, a, void *b, b, return, DUMMYARG)
+-DEFINEFUNC(void, sk_free, _STACK *a, a, return, DUMMYARG)
+-DEFINEFUNC2(void *, sk_value, STACK *a, a, int b, b, return 0, return)
+-#else
+-DEFINEFUNC(STACK *, sk_new_null, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC2(void, sk_push, STACK *a, a, char *b, b, return, DUMMYARG)
+-DEFINEFUNC(void, sk_free, STACK *a, a, return, DUMMYARG)
+-DEFINEFUNC2(char *, sk_value, STACK *a, a, int b, b, return 0, return)
+-#endif
+ DEFINEFUNC(int, SSL_accept, SSL *a, a, return -1, return)
+ DEFINEFUNC(int, SSL_clear, SSL *a, a, return -1, return)
+-DEFINEFUNC3(char *, SSL_CIPHER_description, SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
+-DEFINEFUNC2(int, SSL_CIPHER_get_bits, SSL_CIPHER *a, a, int *b, b, return 0, return)
++DEFINEFUNC3(char *, SSL_CIPHER_description, const SSL_CIPHER *a, a, char *b, b, int c, c, return 0, return)
++DEFINEFUNC2(int, SSL_CIPHER_get_bits, const SSL_CIPHER *a, a, int *b, b, return 0, return)
+ DEFINEFUNC(int, SSL_connect, SSL *a, a, return -1, return)
+ DEFINEFUNC(int, SSL_CTX_check_private_key, const SSL_CTX *a, a, return -1, return)
+ DEFINEFUNC4(long, SSL_CTX_ctrl, SSL_CTX *a, a, int b, b, long c, c, void *d, d, return -1, return)
+@@ -287,8 +419,6 @@ DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return)
+ #else
+ DEFINEFUNC(long, SSL_get_verify_result, SSL *a, a, return -1, return)
+ #endif
+-DEFINEFUNC(int, SSL_library_init, void, DUMMYARG, return -1, return)
+-DEFINEFUNC(void, SSL_load_error_strings, void, DUMMYARG, return, DUMMYARG)
+ DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return 0, return)
+ DEFINEFUNC4(long, SSL_ctrl, SSL *a, a, int cmd, cmd, long larg, larg, void *parg, parg, return -1, return)
+ DEFINEFUNC3(int, SSL_read, SSL *a, a, void *b, b, int c, c, return -1, return)
+@@ -301,7 +431,6 @@ DEFINEFUNC(void, SSL_SESSION_free, SSL_SESSION *ses, ses, return, DUMMYARG)
+ DEFINEFUNC(SSL_SESSION*, SSL_get1_session, SSL *ssl, ssl, return 0, return)
+ DEFINEFUNC(SSL_SESSION*, SSL_get_session, const SSL *ssl, ssl, return 0, return)
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC5(int, SSL_get_ex_new_index, long argl, argl, void *argp, argp, CRYPTO_EX_new *new_func, new_func, CRYPTO_EX_dup *dup_func, dup_func, CRYPTO_EX_free *free_func, free_func, return -1, return)
+ DEFINEFUNC3(int, SSL_set_ex_data, SSL *ssl, ssl, int idx, idx, void *arg, arg, return 0, return)
+ DEFINEFUNC2(void *, SSL_get_ex_data, const SSL *ssl, ssl, int idx, idx, return NULL, return)
+ #endif
+@@ -310,51 +439,9 @@ DEFINEFUNC2(void, SSL_set_psk_client_callback, SSL* ssl, ssl, q_psk_client_callb
+ 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
+-DEFINEFUNC(const SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(const SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(const SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(const SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(const SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(const SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(const SSL_METHOD *, TLSv1_2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#else
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(SSL_METHOD *, SSLv2_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(SSL_METHOD *, SSLv3_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(SSL_METHOD *, SSLv23_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(SSL_METHOD *, TLSv1_client_method, DUMMYARG, DUMMYARG, return 0, return)
+-#ifndef OPENSSL_NO_SSL2
+-DEFINEFUNC(SSL_METHOD *, SSLv2_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-DEFINEFUNC(SSL_METHOD *, SSLv3_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+-DEFINEFUNC(SSL_METHOD *, SSLv23_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-DEFINEFUNC(SSL_METHOD *, TLSv1_server_method, DUMMYARG, DUMMYARG, return 0, return)
+-#endif
+ DEFINEFUNC3(int, SSL_write, SSL *a, a, const void *b, b, int c, c, return -1, return)
+ DEFINEFUNC2(int, X509_cmp, X509 *a, a, X509 *b, b, return -1, return)
++DEFINEFUNC4(int, X509_digest, const X509 *x509, x509, const EVP_MD *type, type, unsigned char *md, md, unsigned int *len, len, return -1, return)
+ #ifndef SSLEAY_MACROS
+ DEFINEFUNC(X509 *, X509_dup, X509 *a, a, return 0, return)
+ #endif
+@@ -378,6 +465,7 @@ DEFINEFUNC2(int, ASN1_STRING_print, BIO *a, a, ASN1_STRING *b, b, return 0, retu
+ DEFINEFUNC2(int, X509_check_issued, X509 *a, a, X509 *b, b, return -1, return)
+ DEFINEFUNC(X509_NAME *, X509_get_issuer_name, X509 *a, a, return 0, return)
+ DEFINEFUNC(X509_NAME *, X509_get_subject_name, X509 *a, a, return 0, return)
++DEFINEFUNC(ASN1_INTEGER *, X509_get_serialNumber, X509 *a, a, return 0, return)
+ DEFINEFUNC(int, X509_verify_cert, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(int, X509_NAME_entry_count, X509_NAME *a, a, return 0, return)
+ DEFINEFUNC2(X509_NAME_ENTRY *, X509_NAME_get_entry, X509_NAME *a, a, int b, b, return 0, return)
+@@ -393,25 +481,8 @@ DEFINEFUNC2(int, X509_STORE_CTX_set_purpose, X509_STORE_CTX *a, a, int b, b, ret
+ DEFINEFUNC(int, X509_STORE_CTX_get_error, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(int, X509_STORE_CTX_get_error_depth, X509_STORE_CTX *a, a, return -1, return)
+ DEFINEFUNC(X509 *, X509_STORE_CTX_get_current_cert, X509_STORE_CTX *a, a, return 0, return)
+-DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get_chain, X509_STORE_CTX *a, a, return 0, return)
+ DEFINEFUNC(X509_STORE_CTX *, X509_STORE_CTX_new, DUMMYARG, DUMMYARG, return 0, return)
+-#ifdef SSLEAY_MACROS
+-DEFINEFUNC2(int, i2d_DSAPrivateKey, const DSA *a, a, unsigned char **b, b, return -1, return)
+-DEFINEFUNC2(int, i2d_RSAPrivateKey, const RSA *a, a, unsigned char **b, b, return -1, return)
+-#ifndef OPENSSL_NO_EC
+-DEFINEFUNC2(int, i2d_ECPrivateKey, const EC_KEY *a, a, unsigned char **b, b, return -1, return)
+-#endif
+-DEFINEFUNC3(RSA *, d2i_RSAPrivateKey, RSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+-DEFINEFUNC3(DSA *, d2i_DSAPrivateKey, DSA **a, a, unsigned char **b, b, long c, c, return 0, return)
+-#ifndef OPENSSL_NO_EC
+-DEFINEFUNC3(EC_KEY *, d2i_ECPrivateKey, EC_KEY **a, a, unsigned char **b, b, long c, c, return 0, return)
+-#endif
+-#endif
+-DEFINEFUNC(void, OPENSSL_add_all_algorithms_noconf, void, DUMMYARG, return, DUMMYARG)
+-DEFINEFUNC(void, OPENSSL_add_all_algorithms_conf, void, DUMMYARG, return, DUMMYARG)
+ DEFINEFUNC3(int, SSL_CTX_load_verify_locations, SSL_CTX *ctx, ctx, const char *CAfile, CAfile, const char *CApath, CApath, return 0, return)
+-DEFINEFUNC(long, SSLeay, void, DUMMYARG, return 0, return)
+-DEFINEFUNC(const char *, SSLeay_version, int a, a, return 0, return)
+ DEFINEFUNC2(int, i2d_SSL_SESSION, SSL_SESSION *in, in, unsigned char **pp, pp, return 0, return)
+ DEFINEFUNC3(SSL_SESSION *, d2i_SSL_SESSION, SSL_SESSION **a, a, const unsigned char **pp, pp, long length, length, return 0, return)
+ #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+@@ -694,8 +765,8 @@ static QPair<QLibrary*, QLibrary*> loadOpenSsl()
+ #ifndef Q_OS_DARWIN
+ // second attempt: find the development files libssl.so and libcrypto.so
+ //
+- // disabled on OS X/iOS:
+- // OS X's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
++ // disabled on macOS/iOS:
++ // macOS's /usr/lib/libssl.dylib, /usr/lib/libcrypto.dylib will be picked up in the third
+ // attempt, _after_ <bundle>/Contents/Frameworks has been searched.
+ // iOS does not ship a system libssl.dylib, libcrypto.dylib in the first place.
+ libssl->setFileNameAndVersion(QLatin1String("ssl"), -1);
+@@ -754,8 +825,12 @@ bool q_resolveOpenSslSymbols()
+ static bool symbolsResolved = false;
+ static bool triedToResolveSymbols = false;
+ #ifndef QT_NO_THREAD
++#if QT_CONFIG(opensslv11)
++ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_OPENSSL_init_ssl));
++#else
+ QMutexLocker locker(QMutexPool::globalInstanceGet((void *)&q_SSL_library_init));
+ #endif
++#endif
+ if (symbolsResolved)
+ return true;
+ if (triedToResolveSymbols)
+@@ -771,11 +846,145 @@ bool q_resolveOpenSslSymbols()
+ // failed to load them
+ return false;
+
++#if QT_CONFIG(opensslv11)
++
++ RESOLVEFUNC(OPENSSL_init_ssl)
++ RESOLVEFUNC(OPENSSL_init_crypto)
++ RESOLVEFUNC(ASN1_STRING_get0_data)
++ RESOLVEFUNC(EVP_CIPHER_CTX_reset)
++ RESOLVEFUNC(EVP_PKEY_base_id)
++ RESOLVEFUNC(RSA_bits)
++ RESOLVEFUNC(OPENSSL_sk_new_null)
++ RESOLVEFUNC(OPENSSL_sk_push)
++ RESOLVEFUNC(OPENSSL_sk_free)
++ RESOLVEFUNC(OPENSSL_sk_num)
++ RESOLVEFUNC(OPENSSL_sk_pop_free)
++ RESOLVEFUNC(OPENSSL_sk_value)
++ RESOLVEFUNC(DH_get0_pqg)
++ RESOLVEFUNC(SSL_CTX_set_options)
++ RESOLVEFUNC(SSL_get_client_random)
++ RESOLVEFUNC(SSL_SESSION_get_master_key)
++ RESOLVEFUNC(SSL_session_reused)
++ RESOLVEFUNC(SSL_get_session)
++ RESOLVEFUNC(CRYPTO_get_ex_new_index)
++ RESOLVEFUNC(TLS_method)
++ RESOLVEFUNC(TLS_client_method)
++ RESOLVEFUNC(TLS_server_method)
++ RESOLVEFUNC(X509_STORE_CTX_get0_chain)
++ RESOLVEFUNC(X509_getm_notBefore)
++ RESOLVEFUNC(X509_getm_notAfter)
++ RESOLVEFUNC(X509_get_version)
++ RESOLVEFUNC(X509_get_pubkey)
++ RESOLVEFUNC(X509_STORE_set_verify_cb)
++ RESOLVEFUNC(CRYPTO_free)
++ RESOLVEFUNC(OpenSSL_version_num)
++ RESOLVEFUNC(OpenSSL_version)
++ if (!_q_OpenSSL_version) {
++ // Apparently, we were built with OpenSSL 1.1 enabled but are now using
++ // a wrong library.
++ delete libs.first;
++ delete libs.second;
++ qCWarning(lcSsl, "Incompatible version of OpenSSL");
++ return false;
++ }
++
++ RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint)
++ RESOLVEFUNC(DH_bits)
++ RESOLVEFUNC(DSA_bits)
++
++#else // !opensslv11
++
++ RESOLVEFUNC(ASN1_STRING_data)
++
+ #ifdef SSLEAY_MACROS
+ RESOLVEFUNC(ASN1_dup)
++#endif // SSLEAY_MACROS
++ RESOLVEFUNC(BIO_new_file)
++ RESOLVEFUNC(ERR_clear_error)
++ RESOLVEFUNC(CRYPTO_free)
++ RESOLVEFUNC(CRYPTO_num_locks)
++ RESOLVEFUNC(CRYPTO_set_id_callback)
++ RESOLVEFUNC(CRYPTO_set_locking_callback)
++ RESOLVEFUNC(ERR_peek_last_error)
++ RESOLVEFUNC(ERR_free_strings)
++ RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
++ RESOLVEFUNC(EVP_CIPHER_CTX_init)
++
++#ifdef SSLEAY_MACROS // ### verify
++ RESOLVEFUNC(PEM_ASN1_read_bio)
++#endif // SSLEAY_MACROS
++
++ RESOLVEFUNC(sk_new_null)
++ RESOLVEFUNC(sk_push)
++ RESOLVEFUNC(sk_free)
++ RESOLVEFUNC(sk_num)
++ RESOLVEFUNC(sk_pop_free)
++ RESOLVEFUNC(sk_value)
++ RESOLVEFUNC(SSL_library_init)
++ RESOLVEFUNC(SSL_load_error_strings)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(SSL_get_ex_new_index)
++#endif
++#ifndef OPENSSL_NO_SSL2
++ RESOLVEFUNC(SSLv2_client_method)
+ #endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++ RESOLVEFUNC(SSLv3_client_method)
++#endif
++ RESOLVEFUNC(SSLv23_client_method)
++ RESOLVEFUNC(TLSv1_client_method)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(TLSv1_1_client_method)
++ RESOLVEFUNC(TLSv1_2_client_method)
++#endif
++#ifndef OPENSSL_NO_SSL2
++ RESOLVEFUNC(SSLv2_server_method)
++#endif
++#ifndef OPENSSL_NO_SSL3_METHOD
++ RESOLVEFUNC(SSLv3_server_method)
++#endif
++ RESOLVEFUNC(SSLv23_server_method)
++ RESOLVEFUNC(TLSv1_server_method)
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ RESOLVEFUNC(TLSv1_1_server_method)
++ RESOLVEFUNC(TLSv1_2_server_method)
++#endif
++ RESOLVEFUNC(X509_STORE_CTX_get_chain)
++#ifdef SSLEAY_MACROS
++ RESOLVEFUNC(i2d_DSAPrivateKey)
++ RESOLVEFUNC(i2d_RSAPrivateKey)
++ RESOLVEFUNC(d2i_DSAPrivateKey)
++ RESOLVEFUNC(d2i_RSAPrivateKey)
++#endif
++ RESOLVEFUNC(CONF_get1_default_config_file)
++ RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
++ RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
++ RESOLVEFUNC(SSLeay)
++
++ if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
++ // OpenSSL 1.1 has deprecated and removed SSLeay. We consider a failure to
++ // resolve this symbol as a failure to resolve symbols.
++ // The right operand of '||' above is ... a bit of paranoia.
++ delete libs.first;
++ delete libs.second;
++ qCWarning(lcSsl, "Incompatible version of OpenSSL");
++ return false;
++ }
++
++
++ RESOLVEFUNC(SSLeay_version)
++
++#ifndef OPENSSL_NO_EC
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L)
++ RESOLVEFUNC(EC_curve_nist2nid)
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
++#endif // OPENSSL_NO_EC
++
++
++#endif // !opensslv11
++
+ RESOLVEFUNC(ASN1_INTEGER_get)
+- RESOLVEFUNC(ASN1_STRING_data)
+ RESOLVEFUNC(ASN1_STRING_length)
+ RESOLVEFUNC(ASN1_STRING_to_UTF8)
+ RESOLVEFUNC(BIO_ctrl)
+@@ -794,25 +1003,22 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(BN_is_word)
+ #endif
+ RESOLVEFUNC(BN_mod_word)
+- RESOLVEFUNC(CRYPTO_free)
+- RESOLVEFUNC(CRYPTO_num_locks)
+- RESOLVEFUNC(CRYPTO_set_id_callback)
+- RESOLVEFUNC(CRYPTO_set_locking_callback)
+ RESOLVEFUNC(DSA_new)
+ RESOLVEFUNC(DSA_free)
+ RESOLVEFUNC(ERR_error_string)
+ RESOLVEFUNC(ERR_get_error)
+- RESOLVEFUNC(ERR_free_strings)
+- RESOLVEFUNC(EVP_CIPHER_CTX_cleanup)
+- RESOLVEFUNC(EVP_CIPHER_CTX_init)
++ RESOLVEFUNC(EVP_CIPHER_CTX_new)
++ RESOLVEFUNC(EVP_CIPHER_CTX_free)
+ RESOLVEFUNC(EVP_CIPHER_CTX_ctrl)
+ RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length)
+ RESOLVEFUNC(EVP_CipherInit)
++ RESOLVEFUNC(EVP_CipherInit_ex)
+ RESOLVEFUNC(EVP_CipherUpdate)
+ RESOLVEFUNC(EVP_CipherFinal)
+ RESOLVEFUNC(EVP_des_cbc)
+ RESOLVEFUNC(EVP_des_ede3_cbc)
+ RESOLVEFUNC(EVP_rc2_cbc)
++ RESOLVEFUNC(EVP_sha1)
+ RESOLVEFUNC(EVP_PKEY_assign)
+ RESOLVEFUNC(EVP_PKEY_set1_RSA)
+ RESOLVEFUNC(EVP_PKEY_set1_DSA)
+@@ -834,9 +1040,8 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(i2t_ASN1_OBJECT)
+ RESOLVEFUNC(OBJ_obj2txt)
+ RESOLVEFUNC(OBJ_obj2nid)
+-#ifdef SSLEAY_MACROS // ### verify
+- RESOLVEFUNC(PEM_ASN1_read_bio)
+-#else
++
++#ifndef SSLEAY_MACROS
+ RESOLVEFUNC(PEM_read_bio_PrivateKey)
+ RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
+ RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
+@@ -849,7 +1054,8 @@ bool q_resolveOpenSslSymbols()
+ #ifndef OPENSSL_NO_EC
+ RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
+ #endif
+-#endif
++#endif // !SSLEAY_MACROS
++
+ RESOLVEFUNC(PEM_read_bio_PUBKEY)
+ RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
+ RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
+@@ -865,12 +1071,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(RAND_status)
+ RESOLVEFUNC(RSA_new)
+ RESOLVEFUNC(RSA_free)
+- RESOLVEFUNC(sk_new_null)
+- RESOLVEFUNC(sk_push)
+- RESOLVEFUNC(sk_free)
+- RESOLVEFUNC(sk_num)
+- RESOLVEFUNC(sk_pop_free)
+- RESOLVEFUNC(sk_value)
+ RESOLVEFUNC(SSL_CIPHER_description)
+ RESOLVEFUNC(SSL_CIPHER_get_bits)
+ RESOLVEFUNC(SSL_CTX_check_private_key)
+@@ -898,8 +1098,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_get_peer_cert_chain)
+ RESOLVEFUNC(SSL_get_peer_certificate)
+ RESOLVEFUNC(SSL_get_verify_result)
+- RESOLVEFUNC(SSL_library_init)
+- RESOLVEFUNC(SSL_load_error_strings)
+ RESOLVEFUNC(SSL_new)
+ RESOLVEFUNC(SSL_ctrl)
+ RESOLVEFUNC(SSL_read)
+@@ -912,7 +1110,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_get1_session)
+ RESOLVEFUNC(SSL_get_session)
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(SSL_get_ex_new_index)
+ RESOLVEFUNC(SSL_set_ex_data)
+ RESOLVEFUNC(SSL_get_ex_data)
+ #endif
+@@ -922,30 +1119,6 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(SSL_CTX_use_psk_identity_hint)
+ #endif
+ RESOLVEFUNC(SSL_write)
+-#ifndef OPENSSL_NO_SSL2
+- RESOLVEFUNC(SSLv2_client_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- RESOLVEFUNC(SSLv3_client_method)
+-#endif
+- RESOLVEFUNC(SSLv23_client_method)
+- RESOLVEFUNC(TLSv1_client_method)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(TLSv1_1_client_method)
+- RESOLVEFUNC(TLSv1_2_client_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL2
+- RESOLVEFUNC(SSLv2_server_method)
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+- RESOLVEFUNC(SSLv3_server_method)
+-#endif
+- RESOLVEFUNC(SSLv23_server_method)
+- RESOLVEFUNC(TLSv1_server_method)
+-#if OPENSSL_VERSION_NUMBER >= 0x10001000L
+- RESOLVEFUNC(TLSv1_1_server_method)
+- RESOLVEFUNC(TLSv1_2_server_method)
+-#endif
+ RESOLVEFUNC(X509_NAME_entry_count)
+ RESOLVEFUNC(X509_NAME_get_entry)
+ RESOLVEFUNC(X509_NAME_ENTRY_get_data)
+@@ -961,12 +1134,12 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(X509_STORE_CTX_get_error)
+ RESOLVEFUNC(X509_STORE_CTX_get_error_depth)
+ RESOLVEFUNC(X509_STORE_CTX_get_current_cert)
+- RESOLVEFUNC(X509_STORE_CTX_get_chain)
+ RESOLVEFUNC(X509_cmp)
+ #ifndef SSLEAY_MACROS
+ RESOLVEFUNC(X509_dup)
+ #endif
+ RESOLVEFUNC(X509_print)
++ RESOLVEFUNC(X509_digest)
+ RESOLVEFUNC(X509_EXTENSION_get_object)
+ RESOLVEFUNC(X509_free)
+ RESOLVEFUNC(X509_get_ext)
+@@ -982,20 +1155,11 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(X509_check_issued)
+ RESOLVEFUNC(X509_get_issuer_name)
+ RESOLVEFUNC(X509_get_subject_name)
++ RESOLVEFUNC(X509_get_serialNumber)
+ RESOLVEFUNC(X509_verify_cert)
+ RESOLVEFUNC(d2i_X509)
+ RESOLVEFUNC(i2d_X509)
+-#ifdef SSLEAY_MACROS
+- RESOLVEFUNC(i2d_DSAPrivateKey)
+- RESOLVEFUNC(i2d_RSAPrivateKey)
+- RESOLVEFUNC(d2i_DSAPrivateKey)
+- RESOLVEFUNC(d2i_RSAPrivateKey)
+-#endif
+- RESOLVEFUNC(OPENSSL_add_all_algorithms_noconf)
+- RESOLVEFUNC(OPENSSL_add_all_algorithms_conf)
+ RESOLVEFUNC(SSL_CTX_load_verify_locations)
+- RESOLVEFUNC(SSLeay)
+- RESOLVEFUNC(SSLeay_version)
+ RESOLVEFUNC(i2d_SSL_SESSION)
+ RESOLVEFUNC(d2i_SSL_SESSION)
+ #if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
+@@ -1019,27 +1183,14 @@ bool q_resolveOpenSslSymbols()
+ RESOLVEFUNC(EC_KEY_new_by_curve_name)
+ RESOLVEFUNC(EC_KEY_free)
+ RESOLVEFUNC(EC_get_builtin_curves)
+-#if OPENSSL_VERSION_NUMBER >= 0x10002000L
+- if (q_SSLeay() >= 0x10002000L)
+- RESOLVEFUNC(EC_curve_nist2nid)
+-#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
+ #endif // OPENSSL_NO_EC
+ RESOLVEFUNC(PKCS12_parse)
+ RESOLVEFUNC(d2i_PKCS12_bio)
+ RESOLVEFUNC(PKCS12_free)
+
++ symbolsResolved = true;
+ delete libs.first;
+ delete libs.second;
+- if (!_q_SSLeay || q_SSLeay() >= 0x10100000L) {
+- // OpenSSL 1.1 deprecated and removed SSLeay. We consider a failure to
+- // resolve this symbol as a failure to resolve symbols.
+- // The right operand of '||' above ... a bit of paranoia.
+- qCWarning(lcSsl, "Incompatible version of OpenSSL");
+- return false;
+- }
+-
+- symbolsResolved = true;
+-
+ return true;
+ }
+ #endif // QT_CONFIG(library)
+diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h
+index b35a895..796bf2d 100644
+--- a/src/network/ssl/qsslsocket_openssl_symbols_p.h
++++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h
+@@ -1,6 +1,6 @@
+ /****************************************************************************
+ **
+-** Copyright (C) 2016 The Qt Company Ltd.
++** Copyright (C) 2017 The Qt Company Ltd.
+ ** Copyright (C) 2014 BlackBerry Limited. All rights reserved.
+ ** Contact: https://www.qt.io/licensing/
+ **
+@@ -56,6 +56,7 @@
+ #ifndef QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+ #define QSSLSOCKET_OPENSSL_SYMBOLS_P_H
+
++
+ //
+ // W A R N I N G
+ // -------------
+@@ -215,17 +216,20 @@ QT_BEGIN_NAMESPACE
+
+ #endif // !defined QT_LINKED_OPENSSL
+
++#if QT_CONFIG(opensslv11)
++#include "qsslsocket_openssl11_symbols_p.h"
++#else
++#include "qsslsocket_opensslpre11_symbols_p.h"
++#endif // QT_CONFIG
++
+ bool q_resolveOpenSslSymbols();
+ long q_ASN1_INTEGER_get(ASN1_INTEGER *a);
+-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);
+ 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);
+-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
+@@ -247,26 +251,23 @@ BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w);
+ const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k);
+ int q_EC_GROUP_get_degree(const EC_GROUP* g);
+ #endif
+-int q_CRYPTO_num_locks();
+-void q_CRYPTO_set_locking_callback(void (*a)(int, int, const char *, int));
+-void q_CRYPTO_set_id_callback(unsigned long (*a)());
+-void q_CRYPTO_free(void *a);
+ DSA *q_DSA_new();
+ void q_DSA_free(DSA *a);
+ X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c);
+ char *q_ERR_error_string(unsigned long a, char *b);
+ unsigned long q_ERR_get_error();
+-void q_ERR_free_strings();
+-void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a);
+-void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a);
++EVP_CIPHER_CTX *q_EVP_CIPHER_CTX_new();
++void q_EVP_CIPHER_CTX_free(EVP_CIPHER_CTX *a);
+ int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr);
+ int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen);
+ int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc);
++int q_EVP_CipherInit_ex(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *cipher, ENGINE *impl, const unsigned char *key, const unsigned char *iv, int enc);
+ int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl);
+ int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl);
+ const EVP_CIPHER *q_EVP_des_cbc();
+ const EVP_CIPHER *q_EVP_des_ede3_cbc();
+ const EVP_CIPHER *q_EVP_rc2_cbc();
++const EVP_MD *q_EVP_sha1();
+ int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c);
+ Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b);
+ int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);
+@@ -310,7 +311,7 @@ int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned
+ int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigned char *d,
+ int e, pem_password_cb *f, void *g);
+ #endif
+-#endif
++#endif // SSLEAY_MACROS
+ 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);
+@@ -326,23 +327,10 @@ void q_RAND_seed(const void *a, int b);
+ int q_RAND_status();
+ RSA *q_RSA_new();
+ void q_RSA_free(RSA *a);
+-int q_sk_num(STACK *a);
+-void q_sk_pop_free(STACK *a, void (*b)(void *));
+-#if OPENSSL_VERSION_NUMBER >= 0x10000000L
+-_STACK *q_sk_new_null();
+-void q_sk_push(_STACK *st, void *data);
+-void q_sk_free(_STACK *a);
+-void * q_sk_value(STACK *a, int b);
+-#else
+-STACK *q_sk_new_null();
+-void q_sk_push(STACK *st, char *data);
+-void q_sk_free(STACK *a);
+-char * q_sk_value(STACK *a, int b);
+-#endif
+ int q_SSL_accept(SSL *a);
+ int q_SSL_clear(SSL *a);
+-char *q_SSL_CIPHER_description(SSL_CIPHER *a, char *b, int c);
+-int q_SSL_CIPHER_get_bits(SSL_CIPHER *a, int *b);
++char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c);
++int q_SSL_CIPHER_get_bits(const SSL_CIPHER *a, int *b);
+ int q_SSL_connect(SSL *a);
+ int q_SSL_CTX_check_private_key(const SSL_CTX *a);
+ long q_SSL_CTX_ctrl(SSL_CTX *a, int b, long c, void *d);
+@@ -374,8 +362,6 @@ int q_SSL_get_error(SSL *a, int b);
+ STACK_OF(X509) *q_SSL_get_peer_cert_chain(SSL *a);
+ X509 *q_SSL_get_peer_certificate(SSL *a);
+ long q_SSL_get_verify_result(const SSL *a);
+-int q_SSL_library_init();
+-void q_SSL_load_error_strings();
+ SSL *q_SSL_new(SSL_CTX *a);
+ long q_SSL_ctrl(SSL *ssl,int cmd, long larg, void *parg);
+ int q_SSL_read(SSL *a, void *b, int c);
+@@ -388,7 +374,6 @@ void q_SSL_SESSION_free(SSL_SESSION *ses);
+ SSL_SESSION *q_SSL_get1_session(SSL *ssl);
+ SSL_SESSION *q_SSL_get_session(const SSL *ssl);
+ #if OPENSSL_VERSION_NUMBER >= 0x10001000L
+-int q_SSL_get_ex_new_index(long argl, void *argp, CRYPTO_EX_new *new_func, CRYPTO_EX_dup *dup_func, CRYPTO_EX_free *free_func);
+ int q_SSL_set_ex_data(SSL *ssl, int idx, void *arg);
+ void *q_SSL_get_ex_data(const SSL *ssl, int idx);
+ #endif
+@@ -399,49 +384,6 @@ typedef unsigned int (*q_psk_server_callback_t)(SSL *ssl, const char *identity,
+ 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
+-const SSL_METHOD *q_SSLv2_client_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-const SSL_METHOD *q_SSLv3_client_method();
+-#endif
+-const SSL_METHOD *q_SSLv23_client_method();
+-const SSL_METHOD *q_TLSv1_client_method();
+-const SSL_METHOD *q_TLSv1_1_client_method();
+-const SSL_METHOD *q_TLSv1_2_client_method();
+-#ifndef OPENSSL_NO_SSL2
+-const SSL_METHOD *q_SSLv2_server_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-const SSL_METHOD *q_SSLv3_server_method();
+-#endif
+-const SSL_METHOD *q_SSLv23_server_method();
+-const SSL_METHOD *q_TLSv1_server_method();
+-const SSL_METHOD *q_TLSv1_1_server_method();
+-const SSL_METHOD *q_TLSv1_2_server_method();
+-#else
+-#ifndef OPENSSL_NO_SSL2
+-SSL_METHOD *q_SSLv2_client_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-SSL_METHOD *q_SSLv3_client_method();
+-#endif
+-SSL_METHOD *q_SSLv23_client_method();
+-SSL_METHOD *q_TLSv1_client_method();
+-SSL_METHOD *q_TLSv1_1_client_method();
+-SSL_METHOD *q_TLSv1_2_client_method();
+-#ifndef OPENSSL_NO_SSL2
+-SSL_METHOD *q_SSLv2_server_method();
+-#endif
+-#ifndef OPENSSL_NO_SSL3_METHOD
+-SSL_METHOD *q_SSLv3_server_method();
+-#endif
+-SSL_METHOD *q_SSLv23_server_method();
+-SSL_METHOD *q_TLSv1_server_method();
+-SSL_METHOD *q_TLSv1_1_server_method();
+-SSL_METHOD *q_TLSv1_2_server_method();
+-#endif
+ int q_SSL_write(SSL *a, const void *b, int c);
+ int q_X509_cmp(X509 *a, X509 *b);
+ #ifdef SSLEAY_MACROS
+@@ -452,6 +394,7 @@ void *q_ASN1_dup(i2d_of_void *i2d, d2i_of_void *d2i, char *x);
+ X509 *q_X509_dup(X509 *a);
+ #endif
+ void q_X509_print(BIO *a, X509*b);
++int q_X509_digest(const X509 *x509, const EVP_MD *type, unsigned char *md, unsigned int *len);
+ ASN1_OBJECT *q_X509_EXTENSION_get_object(X509_EXTENSION *a);
+ void q_X509_free(X509 *a);
+ X509_EXTENSION *q_X509_get_ext(X509 *a, int b);
+@@ -471,6 +414,7 @@ int q_ASN1_STRING_print(BIO *a, ASN1_STRING *b);
+ int q_X509_check_issued(X509 *a, X509 *b);
+ X509_NAME *q_X509_get_issuer_name(X509 *a);
+ X509_NAME *q_X509_get_subject_name(X509 *a);
++ASN1_INTEGER *q_X509_get_serialNumber(X509 *a);
+ int q_X509_verify_cert(X509_STORE_CTX *ctx);
+ int q_X509_NAME_entry_count(X509_NAME *a);
+ X509_NAME_ENTRY *q_X509_NAME_get_entry(X509_NAME *a,int b);
+@@ -488,7 +432,6 @@ int q_X509_STORE_CTX_set_purpose(X509_STORE_CTX *ctx, int purpose);
+ int q_X509_STORE_CTX_get_error(X509_STORE_CTX *ctx);
+ int q_X509_STORE_CTX_get_error_depth(X509_STORE_CTX *ctx);
+ X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx);
+-STACK_OF(X509) *q_X509_STORE_CTX_get_chain(X509_STORE_CTX *ctx);
+
+ // Diffie-Hellman support
+ DH *q_DH_new();
+@@ -522,34 +465,9 @@ int q_PKCS12_parse(PKCS12 *p12, const char *pass, EVP_PKEY **pkey, X509 **cert,
+ PKCS12 *q_d2i_PKCS12_bio(BIO *bio, PKCS12 **pkcs12);
+ void q_PKCS12_free(PKCS12 *pkcs12);
+
+-
+ #define q_BIO_get_mem_data(b, pp) (int)q_BIO_ctrl(b,BIO_CTRL_INFO,0,(char *)pp)
+ #define q_BIO_pending(b) (int)q_BIO_ctrl(b,BIO_CTRL_PENDING,0,NULL)
+-#ifdef SSLEAY_MACROS
+-int q_i2d_DSAPrivateKey(const DSA *a, unsigned char **pp);
+-int q_i2d_RSAPrivateKey(const RSA *a, unsigned char **pp);
+-RSA *q_d2i_RSAPrivateKey(RSA **a, unsigned char **pp, long length);
+-DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
+-#define q_PEM_read_bio_RSAPrivateKey(bp, x, cb, u) \
+- (RSA *)q_PEM_ASN1_read_bio( \
+- (void *(*)(void**, const unsigned char**, long int))q_d2i_RSAPrivateKey, PEM_STRING_RSA, bp, (void **)x, cb, u)
+-#define q_PEM_read_bio_DSAPrivateKey(bp, x, cb, u) \
+- (DSA *)q_PEM_ASN1_read_bio( \
+- (void *(*)(void**, const unsigned char**, long int))q_d2i_DSAPrivateKey, PEM_STRING_DSA, bp, (void **)x, cb, u)
+-#define q_PEM_write_bio_RSAPrivateKey(bp,x,enc,kstr,klen,cb,u) \
+- PEM_ASN1_write_bio((int (*)(void*, unsigned char**))q_i2d_RSAPrivateKey,PEM_STRING_RSA,\
+- bp,(char *)x,enc,kstr,klen,cb,u)
+-#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)
+-#define q_SKM_sk_num(type, st) ((int (*)(const STACK_OF(type) *))q_sk_num)(st)
+-#define q_SKM_sk_value(type, st,i) ((type * (*)(const STACK_OF(type) *, int))q_sk_value)(st, i)
+ #define q_sk_GENERAL_NAME_num(st) q_SKM_sk_num(GENERAL_NAME, (st))
+ #define q_sk_GENERAL_NAME_value(st, i) q_SKM_sk_value(GENERAL_NAME, (st), (i))
+ #define q_sk_X509_num(st) q_SKM_sk_num(X509, (st))
+@@ -558,18 +476,12 @@ DSA *q_d2i_DSAPrivateKey(DSA **a, unsigned char **pp, long length);
+ #define q_sk_SSL_CIPHER_value(st, i) q_SKM_sk_value(SSL_CIPHER, (st), (i))
+ #define q_SSL_CTX_add_extra_chain_cert(ctx,x509) \
+ q_SSL_CTX_ctrl(ctx,SSL_CTRL_EXTRA_CHAIN_CERT,0,(char *)x509)
+-#define q_X509_get_notAfter(x) X509_get_notAfter(x)
+-#define q_X509_get_notBefore(x) X509_get_notBefore(x)
+ #define q_EVP_PKEY_assign_RSA(pkey,rsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_RSA,\
+ (char *)(rsa))
+ #define q_EVP_PKEY_assign_DSA(pkey,dsa) q_EVP_PKEY_assign((pkey),EVP_PKEY_DSA,\
+ (char *)(dsa))
+ #define q_OpenSSL_add_all_algorithms() q_OPENSSL_add_all_algorithms_conf()
+-void q_OPENSSL_add_all_algorithms_noconf();
+-void q_OPENSSL_add_all_algorithms_conf();
+ int q_SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *CAfile, const char *CApath);
+-long q_SSLeay();
+-const char *q_SSLeay_version(int type);
+ int q_i2d_SSL_SESSION(SSL_SESSION *in, unsigned char **pp);
+ SSL_SESSION *q_d2i_SSL_SESSION(SSL_SESSION **a, const unsigned char **pp, long length);
+
+diff --git a/src/network/ssl/qsslsocket_opensslpre11.cpp b/src/network/ssl/qsslsocket_opensslpre11.cpp
+new file mode 100644
+index 0000000..e51888c
+--- /dev/null
++++ b/src/network/ssl/qsslsocket_opensslpre11.cpp
+@@ -0,0 +1,424 @@
++/****************************************************************************
++**
++** Copyright (C) 2017 The Qt Company Ltd.
++** Copyright (C) 2014 Governikus GmbH & Co. KG
++** Contact: https://www.qt.io/licensing/
++**
++** This file is part of the QtNetwork module of the Qt Toolkit.
++**
++** $QT_BEGIN_LICENSE:LGPL$
++** Commercial License Usage
++** Licensees holding valid commercial Qt licenses may use this file in
++** accordance with the commercial license agreement provided with the
++** Software or, alternatively, in accordance with the terms contained in
++** a written agreement between you and The Qt Company. For licensing terms
++** and conditions see https://www.qt.io/terms-conditions. For further
++** information use the contact form at https://www.qt.io/contact-us.
++**
++** GNU Lesser General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU Lesser
++** General Public License version 3 as published by the Free Software
++** Foundation and appearing in the file LICENSE.LGPL3 included in the
++** packaging of this file. Please review the following information to
++** ensure the GNU Lesser General Public License version 3 requirements
++** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
++**
++** GNU General Public License Usage
++** Alternatively, this file may be used under the terms of the GNU
++** General Public License version 2.0 or (at your option) the GNU General
++** Public license version 3 or any later version approved by the KDE Free
++** Qt Foundation. The licenses are as published by the Free Software
++** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
++** included in the packaging of this file. Please review the following
++** information to ensure the GNU General Public License requirements will
++** be met: https://www.gnu.org/licenses/gpl-2.0.html and
++** https://www.gnu.org/licenses/gpl-3.0.html.
++**
++** $QT_END_LICENSE$
++**
++****************************************************************************/
++
++/****************************************************************************
++**
++** In addition, as a special exception, the copyright holders listed above give
++** permission to link the code of its release of Qt with the OpenSSL project's
++** "OpenSSL" library (or modified versions of the "OpenSSL" library that use the
++** same license as the original version), and distribute the linked executables.
++**
++** You must comply with the GNU General Public License version 2 in all
++** respects for all of the code used other than the "OpenSSL" code. If you
++** modify this file, you may extend this exception to your version of the file,
++** but you are not obligated to do so. If you do not wish to do so, delete
++** this exception statement from your version of this file.
++**
++****************************************************************************/
++
++//#define QT_DECRYPT_SSL_TRAFFIC
++
++#include "qssl_p.h"
++#include "qsslsocket_openssl_p.h"
++#include "qsslsocket_openssl_symbols_p.h"
++#include "qsslsocket.h"
++#include "qsslkey.h"
++
++#include <QtCore/qdebug.h>
++#include <QtCore/qdir.h>
++#include <QtCore/qdiriterator.h>
++#include <QtCore/qthread.h>
++#include <QtCore/qfile.h>
++#include <QtCore/qmutex.h>
++#include <QtCore/qlibrary.h>
++
++QT_BEGIN_NAMESPACE
++
++/* \internal
++
++ From OpenSSL's thread(3) manual page:
++
++ OpenSSL can safely be used in multi-threaded applications provided that at
++ least two callback functions are set.
++
++ locking_function(int mode, int n, const char *file, int line) is needed to
++ perform locking on shared data structures. (Note that OpenSSL uses a
++ number of global data structures that will be implicitly shared
++ whenever multiple threads use OpenSSL.) Multi-threaded
++ applications will crash at random if it is not set. ...
++ ...
++ id_function(void) is a function that returns a thread ID. It is not
++ needed on Windows nor on platforms where getpid() returns a different
++ ID for each thread (most notably Linux)
++*/
++
++class QOpenSslLocks
++{
++public:
++ QOpenSslLocks()
++ : initLocker(QMutex::Recursive),
++ locksLocker(QMutex::Recursive)
++ {
++ QMutexLocker locker(&locksLocker);
++ int numLocks = q_CRYPTO_num_locks();
++ locks = new QMutex *[numLocks];
++ memset(locks, 0, numLocks * sizeof(QMutex *));
++ }
++ ~QOpenSslLocks()
++ {
++ QMutexLocker locker(&locksLocker);
++ for (int i = 0; i < q_CRYPTO_num_locks(); ++i)
++ delete locks[i];
++ delete [] locks;
++
++ QSslSocketPrivate::deinitialize();
++ }
++ QMutex *lock(int num)
++ {
++ QMutexLocker locker(&locksLocker);
++ QMutex *tmp = locks[num];
++ if (!tmp)
++ tmp = locks[num] = new QMutex(QMutex::Recursive);
++ return tmp;
++ }
++
++ QMutex *globalLock()
++ {
++ return &locksLocker;
++ }
++
++ QMutex *initLock()
++ {
++ return &initLocker;
++ }
++
++private:
++ QMutex initLocker;
++ QMutex locksLocker;
++ QMutex **locks;
++};
++
++Q_GLOBAL_STATIC(QOpenSslLocks, openssl_locks)
++
++extern "C" {
++static void locking_function(int mode, int lockNumber, const char *, int)
++{
++ QMutex *mutex = openssl_locks()->lock(lockNumber);
++
++ // Lock or unlock it
++ if (mode & CRYPTO_LOCK)
++ mutex->lock();
++ else
++ mutex->unlock();
++}
++static unsigned long id_function()
++{
++ return (quintptr)QThread::currentThreadId();
++}
++
++} // extern "C"
++
++static void q_OpenSSL_add_all_algorithms_safe()
++{
++#ifdef Q_OS_WIN
++ // Prior to version 1.0.1m an attempt to call OpenSSL_add_all_algorithms on
++ // Windows could result in 'exit' call from OPENSSL_config (QTBUG-43843).
++ // We can predict this and avoid OPENSSL_add_all_algorithms call.
++ // From OpenSSL docs:
++ // "An application does not need to add algorithms to use them explicitly,
++ // for example by EVP_sha1(). It just needs to add them if it (or any of
++ // the functions it calls) needs to lookup algorithms.
++ // The cipher and digest lookup functions are used in many parts of the
++ // library. If the table is not initialized several functions will
++ // misbehave and complain they cannot find algorithms. This includes the
++ // PEM, PKCS#12, SSL and S/MIME libraries. This is a common query in
++ // the OpenSSL mailing lists."
++ //
++ // Anyway, as a result, we chose not to call this function if it would exit.
++
++ if (q_SSLeay() < 0x100010DFL)
++ {
++ // Now, before we try to call it, check if an attempt to open config file
++ // will result in exit:
++ if (char *confFileName = q_CONF_get1_default_config_file()) {
++ BIO *confFile = q_BIO_new_file(confFileName, "r");
++ const auto lastError = q_ERR_peek_last_error();
++ q_CRYPTO_free(confFileName);
++ if (confFile) {
++ q_BIO_free(confFile);
++ } else {
++ q_ERR_clear_error();
++ if (ERR_GET_REASON(lastError) == ERR_R_SYS_LIB) {
++ qCWarning(lcSsl, "failed to open openssl.conf file");
++ return;
++ }
++ }
++ }
++ }
++#endif // Q_OS_WIN
++
++ q_OpenSSL_add_all_algorithms();
++}
++
++
++/*!
++ \internal
++*/
++void QSslSocketPrivate::deinitialize()
++{
++ q_CRYPTO_set_id_callback(0);
++ q_CRYPTO_set_locking_callback(0);
++ q_ERR_free_strings();
++}
++
++
++bool QSslSocketPrivate::ensureLibraryLoaded()
++{
++ if (!q_resolveOpenSslSymbols())
++ return false;
++
++ // Check if the library itself needs to be initialized.
++ QMutexLocker locker(openssl_locks()->initLock());
++
++ if (!s_libraryLoaded) {
++ s_libraryLoaded = true;
++
++ // Initialize OpenSSL.
++ q_CRYPTO_set_id_callback(id_function);
++ q_CRYPTO_set_locking_callback(locking_function);
++ if (q_SSL_library_init() != 1)
++ return false;
++ q_SSL_load_error_strings();
++ q_OpenSSL_add_all_algorithms_safe();
++
++#if OPENSSL_VERSION_NUMBER >= 0x10001000L
++ if (q_SSLeay() >= 0x10001000L)
++ QSslSocketBackendPrivate::s_indexForSSLExtraData = q_SSL_get_ex_new_index(0L, NULL, NULL, NULL, NULL);
++#endif
++
++ // Initialize OpenSSL's random seed.
++ if (!q_RAND_status()) {
++ qWarning("Random number generator not seeded, disabling SSL support");
++ return false;
++ }
++ }
++ return true;
++}
++
++void QSslSocketPrivate::ensureCiphersAndCertsLoaded()
++{
++ QMutexLocker locker(openssl_locks()->initLock());
++ if (s_loadedCiphersAndCerts)
++ return;
++ s_loadedCiphersAndCerts = true;
++
++ resetDefaultCiphers();
++ resetDefaultEllipticCurves();
++
++#if QT_CONFIG(library)
++ //load symbols needed to receive certificates from system store
++#if defined(Q_OS_WIN)
++ HINSTANCE hLib = LoadLibraryW(L"Crypt32");
++ if (hLib) {
++ ptrCertOpenSystemStoreW = (PtrCertOpenSystemStoreW)GetProcAddress(hLib, "CertOpenSystemStoreW");
++ ptrCertFindCertificateInStore = (PtrCertFindCertificateInStore)GetProcAddress(hLib, "CertFindCertificateInStore");
++ ptrCertCloseStore = (PtrCertCloseStore)GetProcAddress(hLib, "CertCloseStore");
++ if (!ptrCertOpenSystemStoreW || !ptrCertFindCertificateInStore || !ptrCertCloseStore)
++ qCWarning(lcSsl, "could not resolve symbols in crypt32 library"); // should never happen
++ } else {
++ qCWarning(lcSsl, "could not load crypt32 library"); // should never happen
++ }
++#elif defined(Q_OS_QNX)
++ s_loadRootCertsOnDemand = true;
++#elif defined(Q_OS_UNIX) && !defined(Q_OS_MACOS)
++ // check whether we can enable on-demand root-cert loading (i.e. check whether the sym links are there)
++ QList<QByteArray> dirs = unixRootCertDirectories();
++ QStringList symLinkFilter;
++ symLinkFilter << QLatin1String("[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f].[0-9]");
++ for (int a = 0; a < dirs.count(); ++a) {
++ QDirIterator iterator(QLatin1String(dirs.at(a)), symLinkFilter, QDir::Files);
++ if (iterator.hasNext()) {
++ s_loadRootCertsOnDemand = true;
++ break;
++ }
++ }
++#endif
++#endif // QT_CONFIG(library)
++ // if on-demand loading was not enabled, load the certs now
++ if (!s_loadRootCertsOnDemand)
++ setDefaultCaCertificates(systemCaCertificates());
++#ifdef Q_OS_WIN
++ //Enabled for fetching additional root certs from windows update on windows 6+
++ //This flag is set false by setDefaultCaCertificates() indicating the app uses
++ //its own cert bundle rather than the system one.
++ //Same logic that disables the unix on demand cert loading.
++ //Unlike unix, we do preload the certificates from the cert store.
++ if ((QSysInfo::windowsVersion() & QSysInfo::WV_NT_based) >= QSysInfo::WV_6_0)
++ s_loadRootCertsOnDemand = true;
++#endif
++}
++
++long QSslSocketPrivate::sslLibraryVersionNumber()
++{
++ if (!supportsSsl())
++ return 0;
++
++ return q_SSLeay();
++}
++
++QString QSslSocketPrivate::sslLibraryVersionString()
++{
++ if (!supportsSsl())
++ return QString();
++
++ const char *versionString = q_SSLeay_version(SSLEAY_VERSION);
++ if (!versionString)
++ return QString();
++
++ return QString::fromLatin1(versionString);
++}
++
++void QSslSocketBackendPrivate::continueHandshake()
++{
++ Q_Q(QSslSocket);
++ // if we have a max read buffer size, reset the plain socket's to match
++ if (readBufferMaxSize)
++ plainSocket->setReadBufferSize(readBufferMaxSize);
++
++ if (q_SSL_ctrl((ssl), SSL_CTRL_GET_SESSION_REUSED, 0, NULL))
++ configuration.peerSessionShared = true;
++
++#ifdef QT_DECRYPT_SSL_TRAFFIC
++ if (ssl->session && ssl->s3) {
++ const char *mk = reinterpret_cast<const char *>(ssl->session->master_key);
++ QByteArray masterKey(mk, ssl->session->master_key_length);
++ const char *random = reinterpret_cast<const char *>(ssl->s3->client_random);
++ QByteArray clientRandom(random, SSL3_RANDOM_SIZE);
++
++ // different format, needed for e.g. older Wireshark versions:
++// const char *sid = reinterpret_cast<const char *>(ssl->session->session_id);
++// QByteArray sessionID(sid, ssl->session->session_id_length);
++// QByteArray debugLineRSA("RSA Session-ID:");
++// debugLineRSA.append(sessionID.toHex().toUpper());
++// debugLineRSA.append(" Master-Key:");
++// debugLineRSA.append(masterKey.toHex().toUpper());
++// debugLineRSA.append("\n");
++
++ QByteArray debugLineClientRandom("CLIENT_RANDOM ");
++ debugLineClientRandom.append(clientRandom.toHex().toUpper());
++ debugLineClientRandom.append(" ");
++ debugLineClientRandom.append(masterKey.toHex().toUpper());
++ debugLineClientRandom.append("\n");
++
++ QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys");
++ QFile file(sslKeyFile);
++ if (!file.open(QIODevice::Append))
++ qCWarning(lcSsl) << "could not open file" << sslKeyFile << "for appending";
++ if (!file.write(debugLineClientRandom))
++ qCWarning(lcSsl) << "could not write to file" << sslKeyFile;
++ file.close();
++ } else {
++ qCWarning(lcSsl, "could not decrypt SSL traffic");
++ }
++#endif
++
++ // Cache this SSL session inside the QSslContext
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionSharing)) {
++ if (!sslContextPointer->cacheSession(ssl)) {
++ sslContextPointer.clear(); // we could not cache the session
++ } else {
++ // Cache the session for permanent usage as well
++ if (!(configuration.sslOptions & QSsl::SslOptionDisableSessionPersistence)) {
++ if (!sslContextPointer->sessionASN1().isEmpty())
++ configuration.sslSession = sslContextPointer->sessionASN1();
++ configuration.sslSessionTicketLifeTimeHint = sslContextPointer->sessionTicketLifeTimeHint();
++ }
++ }
++ }
++
++#if OPENSSL_VERSION_NUMBER >= 0x1000100fL && !defined(OPENSSL_NO_NEXTPROTONEG)
++
++ configuration.nextProtocolNegotiationStatus = sslContextPointer->npnContext().status;
++ if (sslContextPointer->npnContext().status == QSslConfiguration::NextProtocolNegotiationUnsupported) {
++ // we could not agree -> be conservative and use HTTP/1.1
++ configuration.nextNegotiatedProtocol = QByteArrayLiteral("http/1.1");
++ } else {
++ const unsigned char *proto = 0;
++ unsigned int proto_len = 0;
++#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
++ configuration.nextNegotiatedProtocol.clear();
++ }
++#endif // OPENSSL_VERSION_NUMBER >= 0x1000100fL ...
++
++#if OPENSSL_VERSION_NUMBER >= 0x10002000L
++ if (q_SSLeay() >= 0x10002000L && mode == QSslSocket::SslClientMode) {
++ EVP_PKEY *key;
++ if (q_SSL_get_server_tmp_key(ssl, &key))
++ configuration.ephemeralServerKey = QSslKey(key, QSsl::PublicKey);
++ }
++#endif // OPENSSL_VERSION_NUMBER >= 0x10002000L ...
++
++ connectionEncrypted = true;
++ emit q->encrypted();
++ if (autoStartHandshake && pendingClose) {
++ pendingClose = false;
++ q->disconnectFromHost();
++ }
++}
++
++QT_END_NAMESPACE
+diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri
+index 52ce2ee..949ebc3 100644
+--- a/src/network/ssl/ssl.pri
++++ b/src/network/ssl/ssl.pri
+@@ -60,13 +60,25 @@ qtConfig(ssl) {
+ 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 \
++ SOURCES += ssl/qsslsocket_openssl_symbols.cpp \
+ ssl/qssldiffiehellmanparameters_openssl.cpp \
++ ssl/qsslcertificate_openssl.cpp \
+ ssl/qsslellipticcurve_openssl.cpp \
+ ssl/qsslkey_openssl.cpp \
+ ssl/qsslsocket_openssl.cpp \
+- ssl/qsslsocket_openssl_symbols.cpp
++ ssl/qsslcontext_openssl.cpp
++
++ qtConfig(opensslv11) {
++ HEADERS += ssl/qsslsocket_openssl11_symbols_p.h
++ SOURCES += ssl/qsslsocket_openssl11.cpp \
++ ssl/qsslcontext_openssl11.cpp
++
++ QMAKE_CXXFLAGS += -DOPENSSL_API_COMPAT=0x10100000L
++ } else {
++ HEADERS += ssl/qsslsocket_opensslpre11_symbols_p.h
++ SOURCES += ssl/qsslsocket_opensslpre11.cpp \
++ ssl/qsslcontext_opensslpre11.cpp
++ }
+
+ darwin:SOURCES += ssl/qsslsocket_mac_shared.cpp
+
+--- a/config.tests/openssl/openssl.cpp 2019-05-28 23:31:56.451891872 +0200
++++ b/config.tests/openssl/openssl.cpp 2019-05-28 23:32:08.869892706 +0200
+@@ -39,8 +39,8 @@
+
+ #include <openssl/opensslv.h>
+
+-#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10000000L || OPENSSL_VERSION_NUMBER-0 >= 0x10100000L
+-# error "OpenSSL >= 1.0.0, and < 1.1.0 is required"
++#if !defined(OPENSSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER-0 < 0x10100000L
++# error "OpenSSL >= 1.1.0 is required"
+ #endif
+
+ #include <openssl/ssl.h>