Blob Blame Raw
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