diff options
Diffstat (limited to 'src/plugins/tls')
56 files changed, 2392 insertions, 3213 deletions
diff --git a/src/plugins/tls/CMakeLists.txt b/src/plugins/tls/CMakeLists.txt index a17cda9594..91b9267123 100644 --- a/src/plugins/tls/CMakeLists.txt +++ b/src/plugins/tls/CMakeLists.txt @@ -1,3 +1,6 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + if(QT_FEATURE_securetransport) add_subdirectory(securetransport) endif() diff --git a/src/plugins/tls/certonly/CMakeLists.txt b/src/plugins/tls/certonly/CMakeLists.txt index 275045dc49..495f408144 100644 --- a/src/plugins/tls/certonly/CMakeLists.txt +++ b/src/plugins/tls/certonly/CMakeLists.txt @@ -1,7 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QTlsBackendCertOnlyPlugin - OUTPUT_NAME certonlybackend + OUTPUT_NAME qcertonlybackend CLASS_NAME QTlsBackendCertOnly - TYPE tls + PLUGIN_TYPE tls DEFAULT_IF NOT QT_FEATURE_securetransport AND NOT (QT_FEATURE_openssl OR QT_FEATURE_openssl_linked) AND NOT QT_FEATURE_schannel SOURCES ../shared/qx509_base_p.h @@ -12,6 +15,6 @@ qt_internal_add_plugin(QTlsBackendCertOnlyPlugin ../shared/qasn1element.cpp qtlsbackend_cert.cpp qtlsbackend_cert_p.h - PUBLIC_LIBRARIES + LIBRARIES Qt::NetworkPrivate ) diff --git a/src/plugins/tls/certonly/qtlsbackend_cert.cpp b/src/plugins/tls/certonly/qtlsbackend_cert.cpp index c81eb0252e..da3baaba70 100644 --- a/src/plugins/tls/certonly/qtlsbackend_cert.cpp +++ b/src/plugins/tls/certonly/qtlsbackend_cert.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlsbackend_cert_p.h" @@ -47,8 +11,6 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.cert-only"); - QString QTlsBackendCertOnly::backendName() const { return builtinBackendNames[nameIndexCertOnly]; @@ -90,3 +52,5 @@ QTlsPrivate::X509DerReaderPtr QTlsBackendCertOnly::X509DerReader() const QT_END_NAMESPACE +#include "moc_qtlsbackend_cert_p.cpp" + diff --git a/src/plugins/tls/certonly/qtlsbackend_cert_p.h b/src/plugins/tls/certonly/qtlsbackend_cert_p.h index ddbe02e5a9..946e4b49dc 100644 --- a/src/plugins/tls/certonly/qtlsbackend_cert_p.h +++ b/src/plugins/tls/certonly/qtlsbackend_cert_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSBACKEND_CERT_P_H #define QTLSBACKEND_CERT_P_H diff --git a/src/plugins/tls/openssl/CMakeLists.txt b/src/plugins/tls/openssl/CMakeLists.txt index 266292c62a..0e0a7a1552 100644 --- a/src/plugins/tls/openssl/CMakeLists.txt +++ b/src/plugins/tls/openssl/CMakeLists.txt @@ -1,7 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QTlsBackendOpenSSLPlugin - OUTPUT_NAME opensslbackend + OUTPUT_NAME qopensslbackend CLASS_NAME QTlsBackendOpenSSL - TYPE tls + PLUGIN_TYPE tls SOURCES ../shared/qx509_base.cpp ../shared/qx509_base_p.h ../shared/qtlskey_base.cpp ../shared/qtlskey_base_p.h @@ -14,13 +17,17 @@ qt_internal_add_plugin(QTlsBackendOpenSSLPlugin qsslcontext_openssl.cpp qsslcontext_openssl_p.h qsslsocket_openssl_symbols.cpp qsslsocket_openssl_symbols_p.h qopenssl_p.h - PUBLIC_LIBRARIES + LIBRARIES Qt::NetworkPrivate Qt::CorePrivate DEFINES OPENSSL_API_COMPAT=0x10100000L ) +if (WIN32) # Windows header issues + set_target_properties(QTlsBackendOpenSSLPlugin PROPERTIES UNITY_BUILD OFF) +endif() + qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_dtls SOURCES qdtls_openssl.cpp qdtls_openssl_p.h @@ -35,13 +42,12 @@ qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION APPLE ${FWSecurity} ) -qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION ANDROID AND NOT ANDROID_EMBEDDED +qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION ANDROID SOURCES qsslsocket_openssl_android.cpp ) -qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_openssl - AND QT_FEATURE_ssl AND WIN32 +qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION WIN32 SOURCES qwindowscarootfetcher.cpp qwindowscarootfetcher_p.h ../shared/qwincrypt_p.h @@ -49,3 +55,9 @@ qt_internal_extend_target(QTlsBackendOpenSSLPlugin CONDITION QT_FEATURE_openssl crypt32 ) +if(QT_FEATURE_openssl_linked) + target_link_libraries(QTlsBackendOpenSSLPlugin PRIVATE WrapOpenSSL::WrapOpenSSL) +else() + qt_internal_add_target_include_dirs(QTlsBackendOpenSSLPlugin + WrapOpenSSLHeaders::WrapOpenSSLHeaders) +endif() diff --git a/src/plugins/tls/openssl/qdtls_openssl.cpp b/src/plugins/tls/openssl/qdtls_openssl.cpp index 55a82f7fd4..fc07a29ec8 100644 --- a/src/plugins/tls/openssl/qdtls_openssl.cpp +++ b/src/plugins/tls/openssl/qdtls_openssl.cpp @@ -1,47 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ - -#ifndef NOMINMAX -#define NOMINMAX -#endif // NOMINMAX - -#include <QtNetwork/private/qnativesocketengine_p.h> +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#include <QtNetwork/private/qnativesocketengine_p_p.h> #include "qsslsocket_openssl_symbols_p.h" #include "qdtls_openssl_p.h" @@ -218,7 +178,7 @@ extern "C" int q_generate_cookie_callback(SSL *ssl, unsigned char *dst, QMessageAuthenticationCode hmac(dtls->hashAlgorithm, dtls->secret); hmac.addData(peerData); - const QByteArray cookie = hmac.result(); + const QByteArrayView cookie = hmac.resultView(); Q_ASSERT(cookie.size() >= 0); // DTLS1_COOKIE_LENGTH is erroneously 256 bytes long, must be 255 - RFC 6347, 4.2.1. *cookieLength = qMin(DTLS1_COOKIE_LENGTH - 1, cookie.size()); @@ -241,7 +201,7 @@ extern "C" int q_verify_cookie_callback(SSL *ssl, const unsigned char *cookie, return 0; return newCookieLength == cookieLength - && !std::memcmp(cookie, newCookie, cookieLength); + && !q_CRYPTO_memcmp(cookie, newCookie, size_t(cookieLength)); } extern "C" int q_X509DtlsCallback(int ok, X509_STORE_CTX *ctx) @@ -605,7 +565,7 @@ bool DtlsState::init(QDtlsBasePrivate *dtlsBase, QUdpSocket *socket, Q_ASSERT(dtlsBase); Q_ASSERT(socket); - if (!tlsContext.data() && !initTls(dtlsBase)) + if (!tlsContext && !initTls(dtlsBase)) return false; udpSocket = socket; @@ -632,7 +592,7 @@ void DtlsState::reset() bool DtlsState::initTls(QDtlsBasePrivate *dtlsBase) { - if (tlsContext.data()) + if (tlsContext) return true; if (!QSslSocket::supportsSsl()) @@ -653,7 +613,7 @@ bool DtlsState::initTls(QDtlsBasePrivate *dtlsBase) static QString msgFunctionFailed(const char *function) { //: %1: Some function - return QDtls::tr("%1 failed").arg(QLatin1String(function)); + return QDtls::tr("%1 failed").arg(QLatin1StringView(function)); } bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase) @@ -716,7 +676,7 @@ bool DtlsState::initCtxAndConnection(QDtlsBasePrivate *dtlsBase) bool DtlsState::initBIO(QDtlsBasePrivate *dtlsBase) { Q_ASSERT(dtlsBase); - Q_ASSERT(tlsContext.data() && tlsConnection.data()); + Q_ASSERT(tlsContext && tlsConnection); BioMethod customMethod(q_BIO_meth_new(BIO_TYPE_DGRAM, dtlsbio::qdtlsMethodName), dtlsutil::delete_bio_method); @@ -1288,12 +1248,12 @@ unsigned QDtlsPrivateOpenSSL::pskClientCallback(const char *hint, char *identity return 0; // Copy data back into OpenSSL - const int identityLength = qMin(pskAuthenticator.identity().length(), + const int identityLength = qMin(pskAuthenticator.identity().size(), pskAuthenticator.maximumIdentityLength()); std::memcpy(identity, pskAuthenticator.identity().constData(), identityLength); identity[identityLength] = 0; - const int pskLength = qMin(pskAuthenticator.preSharedKey().length(), + const int pskLength = qMin(pskAuthenticator.preSharedKey().size(), pskAuthenticator.maximumPreSharedKeyLength()); std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength); @@ -1319,7 +1279,7 @@ unsigned QDtlsPrivateOpenSSL::pskServerCallback(const char *identity, unsigned c return 0; // Copy data back into OpenSSL - const int pskLength = qMin(pskAuthenticator.preSharedKey().length(), + const int pskLength = qMin(pskAuthenticator.preSharedKey().size(), pskAuthenticator.maximumPreSharedKeyLength()); std::memcpy(psk, pskAuthenticator.preSharedKey().constData(), pskLength); @@ -1364,7 +1324,7 @@ bool QDtlsPrivateOpenSSL::verifyPeer() // Translate errors from the error list into QSslErrors using CertClass = QTlsPrivate::X509CertificateOpenSSL; errors.reserve(errors.size() + opensslErrors.size()); - for (const auto &error : qAsConst(opensslErrors)) { + for (const auto &error : std::as_const(opensslErrors)) { const auto value = peerCertificateChain.value(error.depth); errors << CertClass::openSSLErrorToQSslError(error.code, value); } @@ -1421,9 +1381,12 @@ void QDtlsPrivateOpenSSL::fetchNegotiatedParameters() // TLS 1.2, that's how it's set by OpenSSL (and that's what they are?). switch (q_SSL_version(dtls.tlsConnection.data())) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case DTLS1_VERSION: sessionProtocol = QSsl::DtlsV1_0; break; +QT_WARNING_POP case DTLS1_2_VERSION: sessionProtocol = QSsl::DtlsV1_2; break; diff --git a/src/plugins/tls/openssl/qdtls_openssl_p.h b/src/plugins/tls/openssl/qdtls_openssl_p.h index d10d4ce584..44be86f1ed 100644 --- a/src/plugins/tls/openssl/qdtls_openssl_p.h +++ b/src/plugins/tls/openssl/qdtls_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDTLS_OPENSSL_P_H #define QDTLS_OPENSSL_P_H @@ -92,7 +56,7 @@ public: using BioMethod = QSharedPointer<BIO_METHOD>; BioMethod bioMethod; - using TlsContext = QSharedPointer<QSslContext>; + using TlsContext = std::shared_ptr<QSslContext>; TlsContext tlsContext; using TlsConnection = QSharedPointer<SSL>; diff --git a/src/plugins/tls/openssl/qopenssl_p.h b/src/plugins/tls/openssl/qopenssl_p.h index 6daf72a2f8..370b974630 100644 --- a/src/plugins/tls/openssl/qopenssl_p.h +++ b/src/plugins/tls/openssl/qopenssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** 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. -** -** $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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** diff --git a/src/plugins/tls/openssl/qsslcontext_openssl.cpp b/src/plugins/tls/openssl/qsslcontext_openssl.cpp index c0afc32e47..75c192bd01 100644 --- a/src/plugins/tls/openssl/qsslcontext_openssl.cpp +++ b/src/plugins/tls/openssl/qsslcontext_openssl.cpp @@ -1,44 +1,8 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// 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> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qssldiffiehellmanparameters.h> @@ -46,6 +10,7 @@ #include "qsslsocket_openssl_symbols_p.h" #include "qsslcontext_openssl_p.h" #include "qtlsbackend_openssl_p.h" +#include "qtlskey_openssl_p.h" #include "qopenssl_p.h" #include <QtNetwork/private/qssl_p.h> @@ -98,17 +63,20 @@ static inline QString msgErrorSettingEllipticCurves(const QString &why) return QSslSocket::tr("Error when setting the elliptic curves (%1)").arg(why); } -long QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) +qssloptions QSslContext::setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions) { - long options; + qssloptions options; switch (protocol) { - case QSsl::SecureProtocols: +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; break; case QSsl::TlsV1_1OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1; break; +QT_WARNING_POP + case QSsl::SecureProtocols: case QSsl::TlsV1_2OrLater: options = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1; break; @@ -169,21 +137,15 @@ QSslContext::~QSslContext() q_SSL_SESSION_free(session); } -QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) -{ - QSslContext *sslContext = new QSslContext(); - initSslContext(sslContext, mode, configuration, allowRootCertOnDemandLoading); - return sslContext; -} - -QSharedPointer<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) +std::shared_ptr<QSslContext> QSslContext::sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading) { - QSharedPointer<QSslContext> sslContext = QSharedPointer<QSslContext>::create(); - initSslContext(sslContext.data(), mode, configuration, allowRootCertOnDemandLoading); + struct AccessToPrivateCtor : QSslContext {}; + std::shared_ptr<QSslContext> sslContext = std::make_shared<AccessToPrivateCtor>(); + initSslContext(sslContext.get(), mode, configuration, allowRootCertOnDemandLoading); return sslContext; } -QSharedPointer<QSslContext> QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, +std::shared_ptr<QSslContext> QSslContext::sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, bool allowRootCertOnDemandLoading) { return sharedFromConfiguration(mode, privConfiguration, allowRootCertOnDemandLoading); @@ -256,7 +218,7 @@ SSL* QSslContext::createSsl() QList<QByteArray> protocols = sslConfiguration.d.constData()->nextAllowedProtocols; if (!protocols.isEmpty()) { m_supportedNPNVersions.clear(); - for (int a = 0; a < protocols.count(); ++a) { + for (int a = 0; a < protocols.size(); ++a) { if (protocols.at(a).size() > 255) { qCWarning(lcTlsBackend) << "TLS NPN extension" << protocols.at(a) << "is too long and will be ignored."; @@ -268,7 +230,7 @@ SSL* QSslContext::createSsl() } if (m_supportedNPNVersions.size()) { m_npnContext.data = reinterpret_cast<unsigned char *>(m_supportedNPNVersions.data()); - m_npnContext.len = m_supportedNPNVersions.count(); + m_npnContext.len = m_supportedNPNVersions.size(); m_npnContext.status = QSslConfiguration::NextProtocolNegotiationNone; // Callback's type has a parameter 'const unsigned char ** out' // since it was introduced in 1.0.2. Internally, OpenSSL's own code @@ -363,8 +325,11 @@ void QSslContext::initSslContext(QSslContext *sslContext, QSslSocket::SslMode mo bool isDtls = false; init_context: switch (sslContext->sslConfiguration.protocol()) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: case QSsl::DtlsV1_0OrLater: +QT_WARNING_POP case QSsl::DtlsV1_2: case QSsl::DtlsV1_2OrLater: #if QT_CONFIG(dtls) @@ -419,6 +384,8 @@ init_context: long maxVersion = anyVersion; switch (sslContext->sslConfiguration.protocol()) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0: minVersion = TLS1_VERSION; maxVersion = TLS1_VERSION; @@ -427,6 +394,7 @@ init_context: minVersion = TLS1_1_VERSION; maxVersion = TLS1_1_VERSION; break; +QT_WARNING_POP case QSsl::TlsV1_2: minVersion = TLS1_2_VERSION; maxVersion = TLS1_2_VERSION; @@ -443,7 +411,8 @@ init_context: break; // Ranges: case QSsl::AnyProtocol: - case QSsl::SecureProtocols: +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0OrLater: minVersion = TLS1_VERSION; maxVersion = 0; @@ -452,25 +421,30 @@ init_context: minVersion = TLS1_1_VERSION; maxVersion = 0; break; +QT_WARNING_POP + case QSsl::SecureProtocols: case QSsl::TlsV1_2OrLater: minVersion = TLS1_2_VERSION; maxVersion = 0; break; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: minVersion = DTLS1_VERSION; maxVersion = DTLS1_VERSION; break; case QSsl::DtlsV1_0OrLater: minVersion = DTLS1_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; +QT_WARNING_POP case QSsl::DtlsV1_2: minVersion = DTLS1_2_VERSION; maxVersion = DTLS1_2_VERSION; break; case QSsl::DtlsV1_2OrLater: minVersion = DTLS1_2_VERSION; - maxVersion = DTLS_MAX_VERSION; + maxVersion = 0; break; case QSsl::TlsV1_3OrLater: #ifdef TLS1_3_VERSION @@ -502,7 +476,7 @@ init_context: } // Enable bug workarounds. - const long options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); + const qssloptions options = setupOpenSslOptions(configuration.protocol(), configuration.d->sslOptions); q_SSL_CTX_set_options(sslContext->ctx, options); // Tell OpenSSL to release memory early @@ -617,6 +591,13 @@ init_context: if (configuration.d->privateKey.algorithm() == QSsl::Opaque) { sslContext->pkey = reinterpret_cast<EVP_PKEY *>(configuration.d->privateKey.handle()); } else { +#ifdef OPENSSL_NO_DEPRECATED_3_0 + auto qtKey = QTlsBackend::backend<QTlsPrivate::TlsKeyOpenSSL>(configuration.d->privateKey); + Q_ASSERT(qtKey); + sslContext->pkey = qtKey->genericKey; + Q_ASSERT(sslContext->pkey); + q_EVP_PKEY_up_ref(sslContext->pkey); +#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. @@ -629,7 +610,8 @@ init_context: #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 +#endif // OPENSSL_NO_EC +#endif // OPENSSL_NO_DEPRECATED_3_0 } auto pkey = sslContext->pkey; if (configuration.d->privateKey.algorithm() == QSsl::Opaque) @@ -650,7 +632,7 @@ init_context: // 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)) { + for (const QSslCertificate &cert : std::as_const(configuration.d->localCertificateChain)) { if (first) { first = false; continue; @@ -715,15 +697,21 @@ init_context: return; } - if (!dhparams.isEmpty()) { + if (dhparams.isEmpty()) { + q_SSL_CTX_set_dh_auto(sslContext->ctx, 1); + } else { +#ifndef OPENSSL_NO_DEPRECATED_3_0 const QByteArray ¶ms = dhparams.d->derData; const char *ptr = params.constData(); DH *dh = q_d2i_DHparams(nullptr, reinterpret_cast<const unsigned char **>(&ptr), - params.length()); + params.size()); if (dh == nullptr) qFatal("q_d2i_DHparams failed to convert QSslDiffieHellmanParameters to DER form"); q_SSL_CTX_set_tmp_dh(sslContext->ctx, dh); q_DH_free(dh); +#else + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif } #ifndef OPENSSL_NO_PSK diff --git a/src/plugins/tls/openssl/qsslcontext_openssl_p.h b/src/plugins/tls/openssl/qsslcontext_openssl_p.h index c350a93f5e..3bd39baf0c 100644 --- a/src/plugins/tls/openssl/qsslcontext_openssl_p.h +++ b/src/plugins/tls/openssl/qsslcontext_openssl_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QSSLCONTEXT_OPENSSL_P_H @@ -69,13 +33,12 @@ public: ~QSslContext(); - static QSslContext* fromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, - bool allowRootCertOnDemandLoading); - static QSharedPointer<QSslContext> sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, + static std::shared_ptr<QSslContext> sharedFromConfiguration(QSslSocket::SslMode mode, const QSslConfiguration &configuration, bool allowRootCertOnDemandLoading); - static QSharedPointer<QSslContext> sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, + static std::shared_ptr<QSslContext> sharedFromPrivateConfiguration(QSslSocket::SslMode mode, QSslConfigurationPrivate *privConfiguration, bool allowRootCertOnDemandLoading); - static long setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); + + static qssloptions setupOpenSslOptions(QSsl::SslProtocol protocol, QSsl::SslOptions sslOptions); QSslError::SslError error() const; QString errorString() const; @@ -105,7 +68,6 @@ public: protected: QSslContext(); - friend class QSharedPointer<QSslContext>; private: static void initSslContext(QSslContext* sslContext, QSslSocket::SslMode mode, const QSslConfiguration &configuration, diff --git a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp index a917a20744..16e31e605f 100644 --- a/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp +++ b/src/plugins/tls/openssl/qssldiffiehellmanparameters_openssl.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** 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. -** -** $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$ -** -****************************************************************************/ +// Copyright (C) 2015 Mikkel Krautz <mikkel@krautz.dk> +// Copyright (C) 2016 Richard J. Moore <rich@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -53,58 +17,9 @@ QT_BEGIN_NAMESPACE -namespace { - -#ifdef OPENSSL_NO_DEPRECATED_3_0 - -int q_DH_check(DH *dh, int *status) -{ - // DH_check was first deprecated in OpenSSL 3.0.0, as low-level - // API; the EVP_PKEY family of functions was advised as an alternative. - // As of now EVP_PKEY_params_check ends up calling ... DH_check, - // which is good enough. - - Q_ASSERT(dh); - Q_ASSERT(status); - - EVP_PKEY *key = q_EVP_PKEY_new(); - if (!key) { - qCWarning(lcSsl, "EVP_PKEY_new failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } - const auto keyDeleter = qScopeGuard([key](){ - q_EVP_PKEY_free(key); - }); - if (!q_EVP_PKEY_set1_DH(key, dh)) { - qCWarning(lcTlsBackend, "EVP_PKEY_set1_DH failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } +#ifndef OPENSSL_NO_DEPRECATED_3_0 - EVP_PKEY_CTX *keyCtx = q_EVP_PKEY_CTX_new(key, nullptr); - if (!keyCtx) { - qCWarning(lcTlsBackend, "EVP_PKEY_CTX_new failed"); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - return 0; - } - const auto ctxDeleter = qScopeGuard([keyCtx]{ - q_EVP_PKEY_CTX_free(keyCtx); - }); - - const int result = q_EVP_PKEY_param_check(keyCtx); - QTlsBackendOpenSSL::logAndClearErrorQueue(); - // Note: unlike DH_check, we cannot obtain the 'status', - // if the 'result' is 0 (actually the result is 1 only - // if this 'status' was 0). We could probably check the - // errors from the error queue, but it's not needed anyway - // - see the 'isSafeDH' below, how it returns immediately - // on 0. - Q_UNUSED(status); - - return result; -} -#endif // OPENSSL_NO_DEPRECATED_3_0 +namespace { bool isSafeDH(DH *dh) { @@ -153,8 +68,11 @@ bool isSafeDH(DH *dh) } // unnamed namespace +#endif + int QTlsBackendOpenSSL::dhParametersFromDer(const QByteArray &der, QByteArray *derData) const { +#ifndef OPENSSL_NO_DEPRECATED_3_0 Q_ASSERT(derData); if (der.isEmpty()) @@ -178,12 +96,17 @@ int QTlsBackendOpenSSL::dhParametersFromDer(const QByteArray &der, QByteArray *d } else { return DHParams::InvalidInputDataError; } - +#else + Q_UNUSED(der); + Q_UNUSED(derData); + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif return DHParams::NoError; } int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *data) const { +#ifndef OPENSSL_NO_DEPRECATED_3_0 Q_ASSERT(data); if (pem.isEmpty()) @@ -214,8 +137,9 @@ int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *d if (isSafeDH(dh)) { char *buf = nullptr; const int len = q_i2d_DHparams(dh, reinterpret_cast<unsigned char **>(&buf)); + const auto freeBuf = qScopeGuard([&] { q_OPENSSL_free(buf); }); if (len > 0) - *data = QByteArray(buf, len); + data->assign({buf, len}); else return DHParams::InvalidInputDataError; } else { @@ -224,7 +148,11 @@ int QTlsBackendOpenSSL::dhParametersFromPem(const QByteArray &pem, QByteArray *d } else { return DHParams::InvalidInputDataError; } - +#else + Q_UNUSED(pem); + Q_UNUSED(data); + qCWarning(lcTlsBackend, "Diffie-Hellman parameters are not supported, because OpenSSL v3 was built with deprecated API removed"); +#endif return DHParams::NoError; } diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp index 1c11377c0e..6c02215c55 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp +++ b/src/plugins/tls/openssl/qsslsocket_openssl_android.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -54,6 +18,8 @@ #include <QtCore/QJniEnvironment> #include <QtCore/QJniObject> +#include <QtCore/QList> +#include <QtCore/QByteArray> QT_BEGIN_NAMESPACE diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp index 6b4601163b..4aa9ca6fb1 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols.cpp @@ -1,43 +1,7 @@ -/**************************************************************************** -** -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// Copyright (C) 2016 Richard J. Moore <rich@kde.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -55,6 +19,7 @@ ****************************************************************************/ #include "qsslsocket_openssl_symbols_p.h" +#include "qtlsbackend_openssl_p.h" #include <QtNetwork/private/qssl_p.h> @@ -63,7 +28,6 @@ #elif QT_CONFIG(library) # include <QtCore/qlibrary.h> #endif -#include <QtCore/qmutex.h> #include <QtCore/qdatetime.h> #if defined(Q_OS_UNIX) #include <QtCore/qdir.h> @@ -80,6 +44,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + /* Note to maintainer: ------------------- @@ -149,9 +115,6 @@ DEFINEFUNC(int, EVP_PKEY_up_ref, EVP_PKEY *a, a, return 0, return) DEFINEFUNC2(EVP_PKEY_CTX *, EVP_PKEY_CTX_new, EVP_PKEY *pkey, pkey, ENGINE *e, e, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_param_check, EVP_PKEY_CTX *ctx, ctx, return 0, return) DEFINEFUNC(void, EVP_PKEY_CTX_free, EVP_PKEY_CTX *ctx, ctx, return, 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 nullptr, return) @@ -159,7 +122,7 @@ DEFINEFUNC2(void, OPENSSL_sk_push, OPENSSL_STACK *a, a, void *b, b, return, DUMM DEFINEFUNC(void, OPENSSL_sk_free, OPENSSL_STACK *a, a, return, DUMMYARG) DEFINEFUNC2(void *, OPENSSL_sk_value, OPENSSL_STACK *a, a, int b, b, return nullptr, 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) +DEFINEFUNC2(qssloptions, SSL_CTX_set_options, SSL_CTX *ctx, ctx, qssloptions op, op, return 0, return) using info_callback = void (*) (const SSL *ssl, int type, int val); DEFINEFUNC2(void, SSL_set_info_callback, SSL *ssl, ssl, info_callback cb, cb, return, return) DEFINEFUNC(const char *, SSL_alert_type_string, int value, value, return nullptr, return) @@ -183,6 +146,8 @@ DEFINEFUNC(const SSL_METHOD *, TLS_server_method, DUMMYARG, DUMMYARG, return nul DEFINEFUNC(void, X509_up_ref, X509 *a, a, return, DUMMYARG) DEFINEFUNC(ASN1_TIME *, X509_getm_notBefore, X509 *a, a, return nullptr, return) DEFINEFUNC(ASN1_TIME *, X509_getm_notAfter, X509 *a, a, return nullptr, return) +DEFINEFUNC2(void, ASN1_item_free, ASN1_VALUE *val, val, const ASN1_ITEM *it, it, return, return) +DEFINEFUNC(void, X509V3_conf_free, CONF_VALUE *val, val, return, return) DEFINEFUNC(long, X509_get_version, X509 *a, a, return -1, return) DEFINEFUNC(EVP_PKEY *, X509_get_pubkey, X509 *a, a, return nullptr, return) DEFINEFUNC2(void, X509_STORE_set_verify_cb, X509_STORE *a, a, X509_STORE_CTX_verify_cb verify_cb, verify_cb, return, DUMMYARG) @@ -190,11 +155,10 @@ DEFINEFUNC3(int, X509_STORE_set_ex_data, X509_STORE *a, a, int idx, idx, void *d DEFINEFUNC2(void *, X509_STORE_get_ex_data, X509_STORE *r, r, int idx, idx, return nullptr, return) DEFINEFUNC(STACK_OF(X509) *, X509_STORE_CTX_get0_chain, X509_STORE_CTX *a, a, return nullptr, return) DEFINEFUNC3(void, CRYPTO_free, void *str, str, const char *file, file, int line, line, return, DUMMYARG) +DEFINEFUNC3(int, CRYPTO_memcmp, const void * in_a, in_a, const void * in_b, in_b, size_t len, len, return 1, return); DEFINEFUNC(long, OpenSSL_version_num, void, DUMMYARG, return 0, return) DEFINEFUNC(const char *, OpenSSL_version, int a, a, return nullptr, 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) #if QT_CONFIG(dtls) DEFINEFUNC2(int, DTLSv1_listen, SSL *s, s, BIO_ADDR *c, c, return -1, return) @@ -239,6 +203,7 @@ DEFINEFUNC6(int, OCSP_basic_sign, OCSP_BASICRESP *br, br, X509 *signer, signer, const EVP_MD *dg, dg, STACK_OF(X509) *cs, cs, unsigned long flags, flags, return 0, return) #endif // ocsp +DEFINEFUNC(void, AUTHORITY_INFO_ACCESS_free, AUTHORITY_INFO_ACCESS *p, p, return, return) DEFINEFUNC2(void, BIO_set_data, BIO *a, a, void *ptr, ptr, return, DUMMYARG) DEFINEFUNC(void *, BIO_get_data, BIO *a, a, return nullptr, return) DEFINEFUNC2(void, BIO_set_init, BIO *a, a, int init, init, return, DUMMYARG) @@ -258,12 +223,6 @@ DEFINEFUNC3(int, BIO_read, BIO *a, a, void *b, b, int c, c, return -1, 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) 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 nullptr, return) -DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) -#endif -DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, 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 nullptr, return) DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return nullptr, return) DEFINEFUNC3(void, ERR_error_string_n, unsigned long e, e, char *b, b, size_t len, len, return, DUMMYARG) @@ -290,21 +249,7 @@ DEFINEFUNC(const EVP_CIPHER *, EVP_aes_192_cbc, DUMMYARG, DUMMYARG, return nullp DEFINEFUNC(const EVP_CIPHER *, EVP_aes_256_cbc, DUMMYARG, DUMMYARG, return nullptr, return) #endif DEFINEFUNC(const EVP_MD *, EVP_sha1, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, void *r, r, 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) -DEFINEFUNC2(int, EVP_PKEY_set1_DH, EVP_PKEY *a, a, DH *b, b, return -1, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) -#endif -DEFINEFUNC2(int, EVP_PKEY_cmp, const EVP_PKEY *a, a, const EVP_PKEY *b, b, return -1, return) DEFINEFUNC(void, EVP_PKEY_free, EVP_PKEY *a, a, return, DUMMYARG) -DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return) -DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return) -DEFINEFUNC(DH *, EVP_PKEY_get1_DH, EVP_PKEY *a, a, return nullptr, return) -#ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return) -#endif DEFINEFUNC(EVP_PKEY *, EVP_PKEY_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(int, EVP_PKEY_type, int a, a, return NID_undef, return) DEFINEFUNC2(int, i2d_X509, X509 *a, a, unsigned char **b, b, return -1, return) @@ -316,31 +261,14 @@ 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) DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) - -#ifndef OPENSSL_NO_EC -DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -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) -DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) -#endif // OPENSSL_NO_EC -DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) -DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) DEFINEFUNC7(int, PEM_write_bio_PrivateKey, BIO *a, a, EVP_PKEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_PrivateKey_traditional, BIO *a, a, EVP_PKEY *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) DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) -DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) -DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) DEFINEFUNC2(int, PEM_write_bio_PUBKEY, BIO *a, a, EVP_PKEY *b, b, return 0, return) DEFINEFUNC2(void, RAND_seed, const void *a, a, int b, b, return, DUMMYARG) DEFINEFUNC(int, RAND_status, void, DUMMYARG, return -1, return) DEFINEFUNC2(int, RAND_bytes, unsigned char *b, b, int n, n, return 0, return) -DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return) -DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) 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, const SSL_CIPHER *a, a, char *b, b, int c, c, return nullptr, return) @@ -359,7 +287,6 @@ DEFINEFUNC2(void, SSL_CTX_set_verify_depth, SSL_CTX *a, a, int b, b, return, DUM DEFINEFUNC2(int, SSL_CTX_use_certificate, SSL_CTX *a, a, X509 *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_certificate_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC2(int, SSL_CTX_use_PrivateKey, SSL_CTX *a, a, EVP_PKEY *b, b, return -1, return) -DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) DEFINEFUNC3(int, SSL_CTX_use_PrivateKey_file, SSL_CTX *a, a, const char *b, b, int c, c, return -1, return) DEFINEFUNC(X509_STORE *, SSL_CTX_get_cert_store, const SSL_CTX *a, a, return nullptr, return) DEFINEFUNC(SSL_CONF_CTX *, SSL_CONF_CTX_new, DUMMYARG, DUMMYARG, return nullptr, return); @@ -374,7 +301,16 @@ DEFINEFUNC(const SSL_CIPHER *, SSL_get_current_cipher, SSL *a, a, return nullptr DEFINEFUNC(int, SSL_version, const SSL *a, a, return 0, return) DEFINEFUNC2(int, SSL_get_error, SSL *a, a, int b, b, return -1, return) DEFINEFUNC(STACK_OF(X509) *, SSL_get_peer_cert_chain, SSL *a, a, return nullptr, return) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +DEFINEFUNC(X509 *, SSL_get1_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_get_bits, const EVP_PKEY *pkey, pkey, return -1, return) +DEFINEFUNC(int, EVP_PKEY_get_base_id, const EVP_PKEY *pkey, pkey, return -1, return) +#else DEFINEFUNC(X509 *, SSL_get_peer_certificate, SSL *a, a, return nullptr, return) +DEFINEFUNC(int, EVP_PKEY_base_id, EVP_PKEY *a, a, return NID_undef, return) +#endif // OPENSSL_VERSION_MAJOR >= 3 + DEFINEFUNC(long, SSL_get_verify_result, const SSL *a, a, return -1, return) DEFINEFUNC(SSL *, SSL_new, SSL_CTX *a, a, return nullptr, return) DEFINEFUNC(SSL_CTX *, SSL_get_SSL_CTX, SSL *a, a, return nullptr, return) @@ -491,19 +427,22 @@ DEFINEFUNC2(void *, BIO_get_ex_data, BIO *b, b, int idx, idx, return nullptr, re DEFINEFUNC3(int, BIO_set_ex_data, BIO *b, b, int idx, idx, void *data, data, return -1, return) DEFINEFUNC3(void *, CRYPTO_malloc, size_t num, num, const char *file, file, int line, line, return nullptr, return) + +#ifndef OPENSSL_NO_DEPRECATED_3_0 DEFINEFUNC(DH *, DH_new, DUMMYARG, DUMMYARG, return nullptr, return) DEFINEFUNC(void, DH_free, DH *dh, dh, return, DUMMYARG) +DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, 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) + DEFINEFUNC3(DH *, d2i_DHparams, DH**a, a, const unsigned char **pp, pp, long length, length, return nullptr, return) DEFINEFUNC2(int, i2d_DHparams, DH *a, a, unsigned char **p, p, return -1, return) -#ifndef OPENSSL_NO_DEPRECATED_3_0 -DEFINEFUNC2(int, DH_check, DH *dh, dh, int *codes, codes, return 0, return) -#endif // OPENSSL_NO_DEPRECATED_3_0 + +DEFINEFUNC4(DH *, PEM_read_bio_DHparams, BIO *a, a, DH **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +#endif DEFINEFUNC3(BIGNUM *, BN_bin2bn, const unsigned char *s, s, int len, len, BIGNUM *ret, ret, return nullptr, return) + #ifndef OPENSSL_NO_EC -DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) -DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) -DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) DEFINEFUNC2(size_t, EC_get_builtin_curves, EC_builtin_curve * r, r, size_t nitems, nitems, return 0, return) DEFINEFUNC(int, EC_curve_nist2nid, const char *name, name, return 0, return) #endif // OPENSSL_NO_EC @@ -513,6 +452,65 @@ DEFINEFUNC5(int, PKCS12_parse, PKCS12 *p12, p12, const char *pass, pass, EVP_PKE DEFINEFUNC2(PKCS12 *, d2i_PKCS12_bio, BIO *bio, bio, PKCS12 **pkcs12, pkcs12, return nullptr, return); DEFINEFUNC(void, PKCS12_free, PKCS12 *pkcs12, pkcs12, return, DUMMYARG) +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) + +DEFINEFUNC2(int, PEM_write_bio_DSA_PUBKEY, BIO *a, a, DSA *b, b, return 0, return) +DEFINEFUNC2(int, PEM_write_bio_RSA_PUBKEY, BIO *a, a, RSA *b, b, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_DSAPrivateKey, BIO *a, a, DSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) +DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) + +DEFINEFUNC2(int, SSL_CTX_use_RSAPrivateKey, SSL_CTX *a, a, RSA *b, b, return -1, return) + +DEFINEFUNC(DSA *, DSA_new, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(void, DSA_free, DSA *a, a, return, DUMMYARG) + +DEFINEFUNC(RSA *, RSA_new, DUMMYARG, DUMMYARG, return nullptr, return) +DEFINEFUNC(void, RSA_free, RSA *a, a, return, DUMMYARG) + +DEFINEFUNC(int, RSA_bits, RSA *a, a, return 0, return) +DEFINEFUNC(int, DSA_bits, DSA *a, a, return 0, return) +DEFINEFUNC(int, DH_bits, DH *dh, dh, return 0, return) + +DEFINEFUNC(DSA *, EVP_PKEY_get1_DSA, EVP_PKEY *a, a, return nullptr, return) +DEFINEFUNC(RSA *, EVP_PKEY_get1_RSA, EVP_PKEY *a, a, return nullptr, return) +DEFINEFUNC(DH *, EVP_PKEY_get1_DH, EVP_PKEY *a, a, return nullptr, return) + +DEFINEFUNC2(int, EVP_PKEY_cmp, const EVP_PKEY *a, a, const EVP_PKEY *b, b, return -1, return) +DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, void *r, r, 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) +DEFINEFUNC2(int, EVP_PKEY_set1_DH, EVP_PKEY *a, a, DH *b, b, return -1, return) + +#ifndef OPENSSL_NO_EC + +DEFINEFUNC4(EC_KEY *, PEM_read_bio_EC_PUBKEY, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) +DEFINEFUNC4(EC_KEY *, PEM_read_bio_ECPrivateKey, BIO *a, a, EC_KEY **b, b, pem_password_cb *c, c, void *d, d, return nullptr, return) + +DEFINEFUNC2(int, PEM_write_bio_EC_PUBKEY, BIO *a, a, EC_KEY *b, b, return 0, return) +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) + +DEFINEFUNC(const EC_GROUP*, EC_KEY_get0_group, const EC_KEY* k, k, return nullptr, return) +DEFINEFUNC(int, EC_GROUP_get_degree, const EC_GROUP* g, g, return 0, return) + +DEFINEFUNC2(int, EVP_PKEY_set1_EC_KEY, EVP_PKEY *a, a, EC_KEY *b, b, return -1, return) +DEFINEFUNC(EC_KEY *, EVP_PKEY_get1_EC_KEY, EVP_PKEY *a, a, return nullptr, return) + +DEFINEFUNC(EC_KEY *, EC_KEY_dup, const EC_KEY *ec, ec, return nullptr, return) +DEFINEFUNC(EC_KEY *, EC_KEY_new_by_curve_name, int nid, nid, return nullptr, return) +DEFINEFUNC(void, EC_KEY_free, EC_KEY *ecdh, ecdh, return, DUMMYARG) + +#endif // OPENSSL_NO_EC + + + +#endif + #define RESOLVEFUNC(func) \ if (!(_q_##func = _q_PTR_##func(libs.ssl->resolve(#func))) \ && !(_q_##func = _q_PTR_##func(libs.crypto->resolve(#func)))) \ @@ -557,9 +555,9 @@ struct LibGreaterThan typedef bool result_type; result_type operator()(QStringView lhs, QStringView rhs) const { - const auto lhsparts = lhs.split(QLatin1Char('.')); - const auto rhsparts = rhs.split(QLatin1Char('.')); - Q_ASSERT(lhsparts.count() > 1 && rhsparts.count() > 1); + const auto lhsparts = lhs.split(u'.'); + const auto rhsparts = rhs.split(u'.'); + Q_ASSERT(lhsparts.size() > 1 && rhsparts.size() > 1); // note: checking rhs < lhs, the same as lhs > rhs return std::lexicographical_compare(rhsparts.begin() + 1, rhsparts.end(), @@ -589,8 +587,7 @@ static QStringList libraryPathList() { QStringList paths; # ifdef Q_OS_DARWIN - paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")) - .split(QLatin1Char(':'), Qt::SkipEmptyParts); + paths = QString::fromLatin1(qgetenv("DYLD_LIBRARY_PATH")).split(u':', Qt::SkipEmptyParts); // search in .app/Contents/Frameworks UInt32 packageType; @@ -601,15 +598,14 @@ static QStringList libraryPathList() paths << bundleUrl.resolved(frameworksUrl).path(); } # else - paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")) - .split(QLatin1Char(':'), Qt::SkipEmptyParts); + paths = QString::fromLatin1(qgetenv("LD_LIBRARY_PATH")).split(u':', Qt::SkipEmptyParts); # endif - paths << QLatin1String("/lib") << QLatin1String("/usr/lib") << QLatin1String("/usr/local/lib"); - paths << QLatin1String("/lib64") << QLatin1String("/usr/lib64") << QLatin1String("/usr/local/lib64"); - paths << QLatin1String("/lib32") << QLatin1String("/usr/lib32") << QLatin1String("/usr/local/lib32"); + paths << "/lib"_L1 << "/usr/lib"_L1 << "/usr/local/lib"_L1; + paths << "/lib64"_L1 << "/usr/lib64"_L1 << "/usr/local/lib64"_L1; + paths << "/lib32"_L1 << "/usr/lib32"_L1 << "/usr/local/lib32"_L1; #if defined(Q_OS_ANDROID) - paths << QLatin1String("/system/lib"); + paths << "/system/lib"_L1; #elif defined(Q_OS_LINUX) // discover paths of already loaded libraries QDuplicateTracker<QString> loadedPaths; @@ -621,7 +617,7 @@ static QStringList libraryPathList() } Q_NEVER_INLINE -static QStringList findAllLibs(QLatin1String filter) +static QStringList findAllLibs(QLatin1StringView filter) { const QStringList paths = libraryPathList(); QStringList found; @@ -632,8 +628,8 @@ static QStringList findAllLibs(QLatin1String filter) QStringList entryList = dir.entryList(filters, QDir::Files); std::sort(entryList.begin(), entryList.end(), LibGreaterThan()); - for (const QString &entry : qAsConst(entryList)) - found << path + QLatin1Char('/') + entry; + for (const QString &entry : std::as_const(entryList)) + found << path + u'/' + entry; } return found; @@ -641,22 +637,28 @@ static QStringList findAllLibs(QLatin1String filter) static QStringList findAllLibSsl() { - return findAllLibs(QLatin1String("libssl.*")); + return findAllLibs("libssl.*"_L1); } static QStringList findAllLibCrypto() { - return findAllLibs(QLatin1String("libcrypto.*")); + return findAllLibs("libcrypto.*"_L1); } # endif +#if (OPENSSL_VERSION_NUMBER >> 28) < 3 +#define QT_OPENSSL_VERSION "1_1" +#elif OPENSSL_VERSION_MAJOR == 3 // Starting with 3.0 this define is available +#define QT_OPENSSL_VERSION "3" +#endif // > 3 intentionally left undefined + #ifdef Q_OS_WIN struct LoadedOpenSsl { std::unique_ptr<QSystemLibrary> ssl, crypto; }; -static bool tryToLoadOpenSslWin32Library(QLatin1String ssleay32LibName, QLatin1String libeay32LibName, LoadedOpenSsl &result) +static bool tryToLoadOpenSslWin32Library(QLatin1StringView ssleay32LibName, QLatin1StringView libeay32LibName, LoadedOpenSsl &result) { auto ssleay32 = std::make_unique<QSystemLibrary>(ssleay32LibName); if (!ssleay32->load(false)) { @@ -678,7 +680,8 @@ static LoadedOpenSsl loadOpenSsl() LoadedOpenSsl result; // With OpenSSL 1.1 the names have changed to libssl-1_1 and libcrypto-1_1 for builds using - // MSVC and GCC, with architecture suffixes for non-x86 builds. + // MSVC and GCC. For 3.0 the version suffix changed again, to just '3'. + // For non-x86 builds, an architecture suffix is also appended. #if defined(Q_PROCESSOR_X86_64) #define QT_SSL_SUFFIX "-x64" @@ -690,13 +693,13 @@ static LoadedOpenSsl loadOpenSsl() #define QT_SSL_SUFFIX #endif - tryToLoadOpenSslWin32Library(QLatin1String("libssl-1_1" QT_SSL_SUFFIX), - QLatin1String("libcrypto-1_1" QT_SSL_SUFFIX), result); + tryToLoadOpenSslWin32Library("libssl-" QT_OPENSSL_VERSION QT_SSL_SUFFIX ""_L1, + "libcrypto-" QT_OPENSSL_VERSION QT_SSL_SUFFIX ""_L1, result); #undef QT_SSL_SUFFIX return result; } -#else +#else // !Q_OS_WIN: struct LoadedOpenSsl { std::unique_ptr<QLibrary> ssl, crypto; @@ -746,10 +749,22 @@ static LoadedOpenSsl loadOpenSsl() #ifdef Q_OS_OPENBSD libcrypto->setLoadHints(QLibrary::ExportExternalSymbolsHint); #endif -#if defined(SHLIB_VERSION_NUMBER) && !defined(Q_OS_QNX) // on QNX, the libs are always libssl.so and libcrypto.so + +#if !defined(Q_OS_QNX) // on QNX, the libs are always libssl.so and libcrypto.so + +#if defined(OPENSSL_SHLIB_VERSION) + // OpenSSL v.3 does not have SLIB_VERSION_NUMBER but has OPENSSL_SHLIB_VERSION. + // The comment about OPENSSL_SHLIB_VERSION in opensslv.h is a bit troublesome: + // "This is defined in free form." + auto shlibVersion = QString("%1"_L1).arg(OPENSSL_SHLIB_VERSION); + libssl->setFileNameAndVersion("ssl"_L1, shlibVersion); + libcrypto->setFileNameAndVersion("crypto"_L1, shlibVersion); +#elif defined(SHLIB_VERSION_NUMBER) // first attempt: the canonical name is libssl.so.<SHLIB_VERSION_NUMBER> - libssl->setFileNameAndVersion(QLatin1String("ssl"), QLatin1String(SHLIB_VERSION_NUMBER)); - libcrypto->setFileNameAndVersion(QLatin1String("crypto"), QLatin1String(SHLIB_VERSION_NUMBER)); + libssl->setFileNameAndVersion("ssl"_L1, SHLIB_VERSION_NUMBER ""_L1); + libcrypto->setFileNameAndVersion("crypto"_L1, SHLIB_VERSION_NUMBER ""_L1); +#endif // OPENSSL_SHLIB_VERSION + if (libcrypto->load() && libssl->load()) { // libssl.so.<SHLIB_VERSION_NUMBER> and libcrypto.so.<SHLIB_VERSION_NUMBER> found return result; @@ -757,7 +772,7 @@ static LoadedOpenSsl loadOpenSsl() libssl->unload(); libcrypto->unload(); } -#endif +#endif // !defined(Q_OS_QNX) #ifndef Q_OS_DARWIN // second attempt: find the development files libssl.so and libcrypto.so @@ -775,13 +790,13 @@ static LoadedOpenSsl loadOpenSsl() return suffix; }; - static QString suffix = QString::fromLatin1(openSSLSuffix("_1_1")); + static QString suffix = QString::fromLatin1(openSSLSuffix("_" QT_OPENSSL_VERSION)); - libssl->setFileNameAndVersion(QLatin1String("ssl") + suffix, -1); - libcrypto->setFileNameAndVersion(QLatin1String("crypto") + suffix, -1); + libssl->setFileNameAndVersion("ssl"_L1 + suffix, -1); + libcrypto->setFileNameAndVersion("crypto"_L1 + suffix, -1); # else - libssl->setFileNameAndVersion(QLatin1String("ssl"), -1); - libcrypto->setFileNameAndVersion(QLatin1String("crypto"), -1); + libssl->setFileNameAndVersion("ssl"_L1, -1); + libcrypto->setFileNameAndVersion("crypto"_L1, -1); # endif if (libcrypto->load() && libssl->load()) { // libssl.so.0 and libcrypto.so.0 found @@ -797,6 +812,11 @@ static LoadedOpenSsl loadOpenSsl() const QStringList cryptoList = findAllLibCrypto(); for (const QString &crypto : cryptoList) { +#ifdef Q_OS_DARWIN + // Clients should not load the unversioned libcrypto dylib as it does not have a stable ABI + if (crypto.endsWith("libcrypto.dylib")) + continue; +#endif libcrypto->setFileNameAndVersion(crypto, -1); if (libcrypto->load()) { QFileInfo fi(crypto); @@ -830,380 +850,405 @@ static LoadedOpenSsl loadOpenSsl() } #endif -static QBasicMutex symbolResolveMutex; -static QBasicAtomicInt symbolsResolved = Q_BASIC_ATOMIC_INITIALIZER(false); -static bool triedToResolveSymbols = false; - bool q_resolveOpenSslSymbols() { - if (symbolsResolved.loadAcquire()) - return true; - QMutexLocker locker(&symbolResolveMutex); - if (symbolsResolved.loadRelaxed()) - return true; - if (triedToResolveSymbols) - return false; - triedToResolveSymbols = true; - - LoadedOpenSsl libs = loadOpenSsl(); - if (!libs.ssl || !libs.crypto) - // failed to load them - return false; - - RESOLVEFUNC(OPENSSL_init_ssl) - RESOLVEFUNC(OPENSSL_init_crypto) - RESOLVEFUNC(ASN1_STRING_get0_data) - RESOLVEFUNC(EVP_CIPHER_CTX_reset) - RESOLVEFUNC(EVP_PKEY_up_ref) - RESOLVEFUNC(EVP_PKEY_CTX_new) - RESOLVEFUNC(EVP_PKEY_param_check) - RESOLVEFUNC(EVP_PKEY_CTX_free) - 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_set_info_callback) - RESOLVEFUNC(SSL_alert_type_string) - RESOLVEFUNC(SSL_alert_desc_string_long) - RESOLVEFUNC(SSL_CTX_get_security_level) - RESOLVEFUNC(SSL_CTX_set_security_level) + static bool symbolsResolved = []() { + LoadedOpenSsl libs = loadOpenSsl(); + if (!libs.ssl || !libs.crypto) { + qCWarning(lcTlsBackend, "Failed to load libssl/libcrypto."); + return false; + } + + RESOLVEFUNC(OPENSSL_init_ssl) + RESOLVEFUNC(OPENSSL_init_crypto) + RESOLVEFUNC(ASN1_STRING_get0_data) + RESOLVEFUNC(EVP_CIPHER_CTX_reset) + RESOLVEFUNC(AUTHORITY_INFO_ACCESS_free) + RESOLVEFUNC(EVP_PKEY_up_ref) + RESOLVEFUNC(EVP_PKEY_CTX_new) + RESOLVEFUNC(EVP_PKEY_param_check) + RESOLVEFUNC(EVP_PKEY_CTX_free) + 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(SSL_CTX_set_options) + RESOLVEFUNC(SSL_set_info_callback) + RESOLVEFUNC(SSL_alert_type_string) + RESOLVEFUNC(SSL_alert_desc_string_long) + RESOLVEFUNC(SSL_CTX_get_security_level) + RESOLVEFUNC(SSL_CTX_set_security_level) #ifdef TLS1_3_VERSION - RESOLVEFUNC(SSL_CTX_set_ciphersuites) - RESOLVEFUNC(SSL_set_psk_use_session_callback) - RESOLVEFUNC(SSL_CTX_sess_set_new_cb) - RESOLVEFUNC(SSL_SESSION_is_resumable) + RESOLVEFUNC(SSL_CTX_set_ciphersuites) + RESOLVEFUNC(SSL_set_psk_use_session_callback) + RESOLVEFUNC(SSL_CTX_sess_set_new_cb) + RESOLVEFUNC(SSL_SESSION_is_resumable) #endif // TLS 1.3 or OpenSSL > 1.1.1 - RESOLVEFUNC(SSL_get_client_random) - RESOLVEFUNC(SSL_SESSION_get_master_key) - RESOLVEFUNC(SSL_session_reused) - RESOLVEFUNC(SSL_get_session) - RESOLVEFUNC(SSL_set_options) - RESOLVEFUNC(CRYPTO_get_ex_new_index) - RESOLVEFUNC(TLS_method) - RESOLVEFUNC(TLS_client_method) - RESOLVEFUNC(TLS_server_method) - RESOLVEFUNC(X509_up_ref) - 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(X509_STORE_set_ex_data) - RESOLVEFUNC(X509_STORE_get_ex_data) - 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. - qCWarning(lcTlsBackend, "Incompatible version of OpenSSL"); - return false; - } + RESOLVEFUNC(SSL_get_client_random) + RESOLVEFUNC(SSL_SESSION_get_master_key) + RESOLVEFUNC(SSL_session_reused) + RESOLVEFUNC(SSL_get_session) + RESOLVEFUNC(SSL_set_options) + RESOLVEFUNC(CRYPTO_get_ex_new_index) + RESOLVEFUNC(TLS_method) + RESOLVEFUNC(TLS_client_method) + RESOLVEFUNC(TLS_server_method) + RESOLVEFUNC(X509_up_ref) + RESOLVEFUNC(X509_STORE_CTX_get0_chain) + RESOLVEFUNC(X509_getm_notBefore) + RESOLVEFUNC(X509_getm_notAfter) + RESOLVEFUNC(ASN1_item_free) + RESOLVEFUNC(X509V3_conf_free) + RESOLVEFUNC(X509_get_version) + RESOLVEFUNC(X509_get_pubkey) + RESOLVEFUNC(X509_STORE_set_verify_cb) + RESOLVEFUNC(X509_STORE_set_ex_data) + RESOLVEFUNC(X509_STORE_get_ex_data) + RESOLVEFUNC(CRYPTO_free) + RESOLVEFUNC(CRYPTO_memcmp) + RESOLVEFUNC(OpenSSL_version_num) + RESOLVEFUNC(OpenSSL_version) + + if (!_q_OpenSSL_version || !_q_OpenSSL_version_num) { + // Apparently, we were built with OpenSSL 1.1 enabled but are now using + // a wrong library. + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL"); + return false; + } - RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint) - RESOLVEFUNC(DH_bits) - RESOLVEFUNC(DSA_bits) +#if OPENSSL_VERSION_NUMBER >= 0x30000000 + if (q_OpenSSL_version_num() < 0x30000000) { + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL (built with OpenSSL >= 3.x, runtime version is < 3.x)"); + return false; + } +#else + if (q_OpenSSL_version_num() >= 0x30000000) { + qCWarning(lcTlsBackend, "Incompatible version of OpenSSL (built with OpenSSL 1.x, runtime version is >= 3.x)"); + return false; + } +#endif // OPENSSL_VERSION_NUMBER + + RESOLVEFUNC(SSL_SESSION_get_ticket_lifetime_hint) #if QT_CONFIG(dtls) - RESOLVEFUNC(DTLSv1_listen) - RESOLVEFUNC(BIO_ADDR_new) - RESOLVEFUNC(BIO_ADDR_free) - RESOLVEFUNC(BIO_meth_new) - RESOLVEFUNC(BIO_meth_free) - RESOLVEFUNC(BIO_meth_set_write) - RESOLVEFUNC(BIO_meth_set_read) - RESOLVEFUNC(BIO_meth_set_puts) - RESOLVEFUNC(BIO_meth_set_ctrl) - RESOLVEFUNC(BIO_meth_set_create) - RESOLVEFUNC(BIO_meth_set_destroy) + RESOLVEFUNC(DTLSv1_listen) + RESOLVEFUNC(BIO_ADDR_new) + RESOLVEFUNC(BIO_ADDR_free) + RESOLVEFUNC(BIO_meth_new) + RESOLVEFUNC(BIO_meth_free) + RESOLVEFUNC(BIO_meth_set_write) + RESOLVEFUNC(BIO_meth_set_read) + RESOLVEFUNC(BIO_meth_set_puts) + RESOLVEFUNC(BIO_meth_set_ctrl) + RESOLVEFUNC(BIO_meth_set_create) + RESOLVEFUNC(BIO_meth_set_destroy) #endif // dtls #if QT_CONFIG(ocsp) - RESOLVEFUNC(OCSP_SINGLERESP_get0_id) - RESOLVEFUNC(d2i_OCSP_RESPONSE) - RESOLVEFUNC(OCSP_RESPONSE_free) - RESOLVEFUNC(OCSP_response_status) - RESOLVEFUNC(OCSP_response_get1_basic) - RESOLVEFUNC(OCSP_BASICRESP_free) - RESOLVEFUNC(OCSP_basic_verify) - RESOLVEFUNC(OCSP_resp_count) - RESOLVEFUNC(OCSP_resp_get0) - RESOLVEFUNC(OCSP_single_get0_status) - RESOLVEFUNC(OCSP_check_validity) - RESOLVEFUNC(OCSP_cert_to_id) - RESOLVEFUNC(OCSP_id_get0_info) - RESOLVEFUNC(OCSP_resp_get0_certs) - RESOLVEFUNC(OCSP_basic_sign) - RESOLVEFUNC(OCSP_response_create) - RESOLVEFUNC(i2d_OCSP_RESPONSE) - RESOLVEFUNC(OCSP_basic_add1_status) - RESOLVEFUNC(OCSP_BASICRESP_new) - RESOLVEFUNC(OCSP_CERTID_free) - RESOLVEFUNC(OCSP_cert_to_id) - RESOLVEFUNC(OCSP_id_cmp) + RESOLVEFUNC(OCSP_SINGLERESP_get0_id) + RESOLVEFUNC(d2i_OCSP_RESPONSE) + RESOLVEFUNC(OCSP_RESPONSE_free) + RESOLVEFUNC(OCSP_response_status) + RESOLVEFUNC(OCSP_response_get1_basic) + RESOLVEFUNC(OCSP_BASICRESP_free) + RESOLVEFUNC(OCSP_basic_verify) + RESOLVEFUNC(OCSP_resp_count) + RESOLVEFUNC(OCSP_resp_get0) + RESOLVEFUNC(OCSP_single_get0_status) + RESOLVEFUNC(OCSP_check_validity) + RESOLVEFUNC(OCSP_cert_to_id) + RESOLVEFUNC(OCSP_id_get0_info) + RESOLVEFUNC(OCSP_resp_get0_certs) + RESOLVEFUNC(OCSP_basic_sign) + RESOLVEFUNC(OCSP_response_create) + RESOLVEFUNC(i2d_OCSP_RESPONSE) + RESOLVEFUNC(OCSP_basic_add1_status) + RESOLVEFUNC(OCSP_BASICRESP_new) + RESOLVEFUNC(OCSP_CERTID_free) + RESOLVEFUNC(OCSP_cert_to_id) + RESOLVEFUNC(OCSP_id_cmp) #endif // ocsp - RESOLVEFUNC(BIO_set_data) - RESOLVEFUNC(BIO_get_data) - RESOLVEFUNC(BIO_set_init) - RESOLVEFUNC(BIO_get_shutdown) - RESOLVEFUNC(BIO_set_shutdown) - RESOLVEFUNC(ASN1_INTEGER_get) - RESOLVEFUNC(ASN1_INTEGER_cmp) - RESOLVEFUNC(ASN1_STRING_length) - RESOLVEFUNC(ASN1_STRING_to_UTF8) - RESOLVEFUNC(ASN1_TIME_to_tm) - RESOLVEFUNC(BIO_ctrl) - RESOLVEFUNC(BIO_free) - RESOLVEFUNC(BIO_new) - RESOLVEFUNC(BIO_new_mem_buf) - RESOLVEFUNC(BIO_read) - RESOLVEFUNC(BIO_s_mem) - RESOLVEFUNC(BIO_write) - RESOLVEFUNC(BIO_set_flags) - RESOLVEFUNC(BIO_clear_flags) - RESOLVEFUNC(BIO_set_ex_data) - RESOLVEFUNC(BIO_get_ex_data) - -#ifndef OPENSSL_NO_EC - RESOLVEFUNC(EC_KEY_get0_group) - RESOLVEFUNC(EC_GROUP_get_degree) -#endif - RESOLVEFUNC(BN_num_bits) - RESOLVEFUNC(BN_is_word) - RESOLVEFUNC(BN_mod_word) - RESOLVEFUNC(DSA_new) - RESOLVEFUNC(DSA_free) - RESOLVEFUNC(ERR_error_string) - RESOLVEFUNC(ERR_error_string_n) - RESOLVEFUNC(ERR_get_error) - 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_get_digestbyname) + RESOLVEFUNC(BIO_set_data) + RESOLVEFUNC(BIO_get_data) + RESOLVEFUNC(BIO_set_init) + RESOLVEFUNC(BIO_get_shutdown) + RESOLVEFUNC(BIO_set_shutdown) + RESOLVEFUNC(ASN1_INTEGER_get) + RESOLVEFUNC(ASN1_INTEGER_cmp) + RESOLVEFUNC(ASN1_STRING_length) + RESOLVEFUNC(ASN1_STRING_to_UTF8) + RESOLVEFUNC(ASN1_TIME_to_tm) + RESOLVEFUNC(BIO_ctrl) + RESOLVEFUNC(BIO_free) + RESOLVEFUNC(BIO_new) + RESOLVEFUNC(BIO_new_mem_buf) + RESOLVEFUNC(BIO_read) + RESOLVEFUNC(BIO_s_mem) + RESOLVEFUNC(BIO_write) + RESOLVEFUNC(BIO_set_flags) + RESOLVEFUNC(BIO_clear_flags) + RESOLVEFUNC(BIO_set_ex_data) + RESOLVEFUNC(BIO_get_ex_data) + RESOLVEFUNC(BN_num_bits) + RESOLVEFUNC(BN_is_word) + RESOLVEFUNC(BN_mod_word) + RESOLVEFUNC(ERR_error_string) + RESOLVEFUNC(ERR_error_string_n) + RESOLVEFUNC(ERR_get_error) + 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_get_digestbyname) #ifndef OPENSSL_NO_DES - RESOLVEFUNC(EVP_des_cbc) - RESOLVEFUNC(EVP_des_ede3_cbc) + RESOLVEFUNC(EVP_des_cbc) + RESOLVEFUNC(EVP_des_ede3_cbc) #endif #ifndef OPENSSL_NO_RC2 - RESOLVEFUNC(EVP_rc2_cbc) + RESOLVEFUNC(EVP_rc2_cbc) #endif #ifndef OPENSSL_NO_AES - RESOLVEFUNC(EVP_aes_128_cbc) - RESOLVEFUNC(EVP_aes_192_cbc) - RESOLVEFUNC(EVP_aes_256_cbc) + RESOLVEFUNC(EVP_aes_128_cbc) + RESOLVEFUNC(EVP_aes_192_cbc) + RESOLVEFUNC(EVP_aes_256_cbc) #endif - RESOLVEFUNC(EVP_sha1) - RESOLVEFUNC(EVP_PKEY_assign) - RESOLVEFUNC(EVP_PKEY_set1_RSA) - RESOLVEFUNC(EVP_PKEY_set1_DSA) - RESOLVEFUNC(EVP_PKEY_set1_DH) + RESOLVEFUNC(EVP_sha1) + RESOLVEFUNC(EVP_PKEY_free) + RESOLVEFUNC(EVP_PKEY_new) + RESOLVEFUNC(EVP_PKEY_type) + RESOLVEFUNC(OBJ_nid2sn) + RESOLVEFUNC(OBJ_nid2ln) + RESOLVEFUNC(OBJ_sn2nid) + RESOLVEFUNC(OBJ_ln2nid) + RESOLVEFUNC(i2t_ASN1_OBJECT) + RESOLVEFUNC(OBJ_obj2txt) + RESOLVEFUNC(OBJ_obj2nid) + RESOLVEFUNC(PEM_read_bio_PrivateKey) + RESOLVEFUNC(PEM_write_bio_PrivateKey) + RESOLVEFUNC(PEM_write_bio_PrivateKey_traditional) + RESOLVEFUNC(PEM_read_bio_PUBKEY) + RESOLVEFUNC(PEM_write_bio_PUBKEY) + RESOLVEFUNC(RAND_seed) + RESOLVEFUNC(RAND_status) + RESOLVEFUNC(RAND_bytes) + RESOLVEFUNC(SSL_CIPHER_description) + RESOLVEFUNC(SSL_CIPHER_get_bits) + RESOLVEFUNC(SSL_get_rbio) + RESOLVEFUNC(SSL_CTX_check_private_key) + RESOLVEFUNC(SSL_CTX_ctrl) + RESOLVEFUNC(SSL_CTX_free) + RESOLVEFUNC(SSL_CTX_new) + RESOLVEFUNC(SSL_CTX_set_cipher_list) + RESOLVEFUNC(SSL_CTX_callback_ctrl) + RESOLVEFUNC(SSL_CTX_set_default_verify_paths) + RESOLVEFUNC(SSL_CTX_set_verify) + RESOLVEFUNC(SSL_CTX_set_verify_depth) + RESOLVEFUNC(SSL_CTX_use_certificate) + RESOLVEFUNC(SSL_CTX_use_certificate_file) + RESOLVEFUNC(SSL_CTX_use_PrivateKey) + RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) + RESOLVEFUNC(SSL_CTX_get_cert_store); + RESOLVEFUNC(SSL_CONF_CTX_new); + RESOLVEFUNC(SSL_CONF_CTX_free); + RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); + RESOLVEFUNC(SSL_CONF_CTX_set_flags); + RESOLVEFUNC(SSL_CONF_CTX_finish); + RESOLVEFUNC(SSL_CONF_cmd); + RESOLVEFUNC(SSL_accept) + RESOLVEFUNC(SSL_clear) + RESOLVEFUNC(SSL_connect) + RESOLVEFUNC(SSL_free) + RESOLVEFUNC(SSL_get_ciphers) + RESOLVEFUNC(SSL_get_current_cipher) + RESOLVEFUNC(SSL_version) + RESOLVEFUNC(SSL_get_error) + RESOLVEFUNC(SSL_get_peer_cert_chain) + +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 + RESOLVEFUNC(SSL_get1_peer_certificate) + RESOLVEFUNC(EVP_PKEY_get_bits) + RESOLVEFUNC(EVP_PKEY_get_base_id) +#else + RESOLVEFUNC(SSL_get_peer_certificate) + RESOLVEFUNC(EVP_PKEY_base_id) +#endif // OPENSSL_VERSION_MAJOR >= 3 + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + RESOLVEFUNC(DH_new) + RESOLVEFUNC(DH_free) + RESOLVEFUNC(DH_check) + RESOLVEFUNC(DH_get0_pqg) + + RESOLVEFUNC(d2i_DHparams) + RESOLVEFUNC(i2d_DHparams) + + RESOLVEFUNC(PEM_read_bio_DHparams) + + RESOLVEFUNC(EVP_PKEY_assign) + RESOLVEFUNC(EVP_PKEY_cmp) + + RESOLVEFUNC(EVP_PKEY_set1_RSA) + RESOLVEFUNC(EVP_PKEY_set1_DSA) + RESOLVEFUNC(EVP_PKEY_set1_DH) + + RESOLVEFUNC(EVP_PKEY_get1_DSA) + RESOLVEFUNC(EVP_PKEY_get1_RSA) + RESOLVEFUNC(EVP_PKEY_get1_DH) + + RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) + + RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) + RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) + RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) + RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) + + RESOLVEFUNC(DSA_new) + RESOLVEFUNC(DSA_free) + + RESOLVEFUNC(RSA_new) + RESOLVEFUNC(RSA_free) + + RESOLVEFUNC(DH_bits) + RESOLVEFUNC(DSA_bits) + RESOLVEFUNC(RSA_bits) #ifndef OPENSSL_NO_EC - RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) - RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) - RESOLVEFUNC(PEM_read_bio_ECPrivateKey) - RESOLVEFUNC(PEM_write_bio_ECPrivateKey) - RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) - RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) + + RESOLVEFUNC(EVP_PKEY_set1_EC_KEY) + RESOLVEFUNC(EVP_PKEY_get1_EC_KEY) + RESOLVEFUNC(PEM_read_bio_EC_PUBKEY) + RESOLVEFUNC(PEM_read_bio_ECPrivateKey) + RESOLVEFUNC(PEM_write_bio_EC_PUBKEY) + RESOLVEFUNC(PEM_write_bio_ECPrivateKey) + RESOLVEFUNC(EC_KEY_get0_group) + RESOLVEFUNC(EC_GROUP_get_degree) + RESOLVEFUNC(EC_KEY_dup) + RESOLVEFUNC(EC_KEY_new_by_curve_name) + RESOLVEFUNC(EC_KEY_free) + #endif // OPENSSL_NO_EC - RESOLVEFUNC(EVP_PKEY_cmp) - RESOLVEFUNC(EVP_PKEY_free) - RESOLVEFUNC(EVP_PKEY_get1_DSA) - RESOLVEFUNC(EVP_PKEY_get1_RSA) - RESOLVEFUNC(EVP_PKEY_get1_DH) - RESOLVEFUNC(EVP_PKEY_new) - RESOLVEFUNC(EVP_PKEY_type) - RESOLVEFUNC(OBJ_nid2sn) - RESOLVEFUNC(OBJ_nid2ln) - RESOLVEFUNC(OBJ_sn2nid) - RESOLVEFUNC(OBJ_ln2nid) - RESOLVEFUNC(i2t_ASN1_OBJECT) - RESOLVEFUNC(OBJ_obj2txt) - RESOLVEFUNC(OBJ_obj2nid) - RESOLVEFUNC(PEM_read_bio_PrivateKey) - RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) - RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) - RESOLVEFUNC(PEM_read_bio_DHparams) - RESOLVEFUNC(PEM_write_bio_DSAPrivateKey) - RESOLVEFUNC(PEM_write_bio_RSAPrivateKey) - RESOLVEFUNC(PEM_write_bio_PrivateKey) - RESOLVEFUNC(PEM_read_bio_PUBKEY) - RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) - RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_DSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_RSA_PUBKEY) - RESOLVEFUNC(PEM_write_bio_PUBKEY) - RESOLVEFUNC(RAND_seed) - RESOLVEFUNC(RAND_status) - RESOLVEFUNC(RAND_bytes) - RESOLVEFUNC(RSA_new) - RESOLVEFUNC(RSA_free) - RESOLVEFUNC(SSL_CIPHER_description) - RESOLVEFUNC(SSL_CIPHER_get_bits) - RESOLVEFUNC(SSL_get_rbio) - RESOLVEFUNC(SSL_CTX_check_private_key) - RESOLVEFUNC(SSL_CTX_ctrl) - RESOLVEFUNC(SSL_CTX_free) - RESOLVEFUNC(SSL_CTX_new) - RESOLVEFUNC(SSL_CTX_set_cipher_list) - RESOLVEFUNC(SSL_CTX_callback_ctrl) - RESOLVEFUNC(SSL_CTX_set_default_verify_paths) - RESOLVEFUNC(SSL_CTX_set_verify) - RESOLVEFUNC(SSL_CTX_set_verify_depth) - RESOLVEFUNC(SSL_CTX_use_certificate) - RESOLVEFUNC(SSL_CTX_use_certificate_file) - RESOLVEFUNC(SSL_CTX_use_PrivateKey) - RESOLVEFUNC(SSL_CTX_use_RSAPrivateKey) - RESOLVEFUNC(SSL_CTX_use_PrivateKey_file) - RESOLVEFUNC(SSL_CTX_get_cert_store); - RESOLVEFUNC(SSL_CONF_CTX_new); - RESOLVEFUNC(SSL_CONF_CTX_free); - RESOLVEFUNC(SSL_CONF_CTX_set_ssl_ctx); - RESOLVEFUNC(SSL_CONF_CTX_set_flags); - RESOLVEFUNC(SSL_CONF_CTX_finish); - RESOLVEFUNC(SSL_CONF_cmd); - RESOLVEFUNC(SSL_accept) - RESOLVEFUNC(SSL_clear) - RESOLVEFUNC(SSL_connect) - RESOLVEFUNC(SSL_free) - RESOLVEFUNC(SSL_get_ciphers) - RESOLVEFUNC(SSL_get_current_cipher) - RESOLVEFUNC(SSL_version) - RESOLVEFUNC(SSL_get_error) - RESOLVEFUNC(SSL_get_peer_cert_chain) - RESOLVEFUNC(SSL_get_peer_certificate) - RESOLVEFUNC(SSL_get_verify_result) - RESOLVEFUNC(SSL_new) - RESOLVEFUNC(SSL_get_SSL_CTX) - RESOLVEFUNC(SSL_ctrl) - RESOLVEFUNC(SSL_read) - RESOLVEFUNC(SSL_set_accept_state) - RESOLVEFUNC(SSL_set_bio) - RESOLVEFUNC(SSL_set_connect_state) - RESOLVEFUNC(SSL_shutdown) - RESOLVEFUNC(SSL_in_init) - RESOLVEFUNC(SSL_get_shutdown) - RESOLVEFUNC(SSL_set_session) - RESOLVEFUNC(SSL_SESSION_free) - RESOLVEFUNC(SSL_get1_session) - RESOLVEFUNC(SSL_get_session) - RESOLVEFUNC(SSL_set_ex_data) - RESOLVEFUNC(SSL_get_ex_data) - RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx) +#endif // OPENSSL_NO_DEPRECATED_3_0 + + RESOLVEFUNC(SSL_get_verify_result) + RESOLVEFUNC(SSL_new) + RESOLVEFUNC(SSL_get_SSL_CTX) + RESOLVEFUNC(SSL_ctrl) + RESOLVEFUNC(SSL_read) + RESOLVEFUNC(SSL_set_accept_state) + RESOLVEFUNC(SSL_set_bio) + RESOLVEFUNC(SSL_set_connect_state) + RESOLVEFUNC(SSL_shutdown) + RESOLVEFUNC(SSL_in_init) + RESOLVEFUNC(SSL_get_shutdown) + RESOLVEFUNC(SSL_set_session) + RESOLVEFUNC(SSL_SESSION_free) + RESOLVEFUNC(SSL_get1_session) + RESOLVEFUNC(SSL_get_session) + RESOLVEFUNC(SSL_set_ex_data) + RESOLVEFUNC(SSL_get_ex_data) + RESOLVEFUNC(SSL_get_ex_data_X509_STORE_CTX_idx) #ifndef OPENSSL_NO_PSK - RESOLVEFUNC(SSL_set_psk_client_callback) - RESOLVEFUNC(SSL_set_psk_server_callback) - RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) + RESOLVEFUNC(SSL_set_psk_client_callback) + RESOLVEFUNC(SSL_set_psk_server_callback) + RESOLVEFUNC(SSL_CTX_use_psk_identity_hint) #endif // !OPENSSL_NO_PSK - RESOLVEFUNC(SSL_write) - RESOLVEFUNC(X509_NAME_entry_count) - RESOLVEFUNC(X509_NAME_get_entry) - RESOLVEFUNC(X509_NAME_ENTRY_get_data) - RESOLVEFUNC(X509_NAME_ENTRY_get_object) - RESOLVEFUNC(X509_PUBKEY_get) - RESOLVEFUNC(X509_STORE_free) - RESOLVEFUNC(X509_STORE_new) - RESOLVEFUNC(X509_STORE_add_cert) - RESOLVEFUNC(X509_STORE_CTX_free) - RESOLVEFUNC(X509_STORE_CTX_init) - RESOLVEFUNC(X509_STORE_CTX_new) - RESOLVEFUNC(X509_STORE_CTX_set_purpose) - RESOLVEFUNC(X509_STORE_CTX_get_error) - RESOLVEFUNC(X509_STORE_CTX_get_error_depth) - RESOLVEFUNC(X509_STORE_CTX_get_current_cert) - RESOLVEFUNC(X509_STORE_CTX_get0_store) - RESOLVEFUNC(X509_cmp) - RESOLVEFUNC(X509_STORE_CTX_get_ex_data) - RESOLVEFUNC(X509_dup) - RESOLVEFUNC(X509_print) - RESOLVEFUNC(X509_digest) - RESOLVEFUNC(X509_EXTENSION_get_object) - RESOLVEFUNC(X509_free) - RESOLVEFUNC(X509_gmtime_adj) - RESOLVEFUNC(ASN1_TIME_free) - RESOLVEFUNC(X509_get_ext) - RESOLVEFUNC(X509_get_ext_count) - RESOLVEFUNC(X509_get_ext_d2i) - RESOLVEFUNC(X509V3_EXT_get) - RESOLVEFUNC(X509V3_EXT_d2i) - RESOLVEFUNC(X509_EXTENSION_get_critical) - RESOLVEFUNC(X509_EXTENSION_get_data) - RESOLVEFUNC(BASIC_CONSTRAINTS_free) - RESOLVEFUNC(AUTHORITY_KEYID_free) - RESOLVEFUNC(GENERAL_NAME_free) - RESOLVEFUNC(ASN1_STRING_print) - 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) + RESOLVEFUNC(SSL_write) + RESOLVEFUNC(X509_NAME_entry_count) + RESOLVEFUNC(X509_NAME_get_entry) + RESOLVEFUNC(X509_NAME_ENTRY_get_data) + RESOLVEFUNC(X509_NAME_ENTRY_get_object) + RESOLVEFUNC(X509_PUBKEY_get) + RESOLVEFUNC(X509_STORE_free) + RESOLVEFUNC(X509_STORE_new) + RESOLVEFUNC(X509_STORE_add_cert) + RESOLVEFUNC(X509_STORE_CTX_free) + RESOLVEFUNC(X509_STORE_CTX_init) + RESOLVEFUNC(X509_STORE_CTX_new) + RESOLVEFUNC(X509_STORE_CTX_set_purpose) + RESOLVEFUNC(X509_STORE_CTX_get_error) + RESOLVEFUNC(X509_STORE_CTX_get_error_depth) + RESOLVEFUNC(X509_STORE_CTX_get_current_cert) + RESOLVEFUNC(X509_STORE_CTX_get0_store) + RESOLVEFUNC(X509_cmp) + RESOLVEFUNC(X509_STORE_CTX_get_ex_data) + RESOLVEFUNC(X509_dup) + RESOLVEFUNC(X509_print) + RESOLVEFUNC(X509_digest) + RESOLVEFUNC(X509_EXTENSION_get_object) + RESOLVEFUNC(X509_free) + RESOLVEFUNC(X509_gmtime_adj) + RESOLVEFUNC(ASN1_TIME_free) + RESOLVEFUNC(X509_get_ext) + RESOLVEFUNC(X509_get_ext_count) + RESOLVEFUNC(X509_get_ext_d2i) + RESOLVEFUNC(X509V3_EXT_get) + RESOLVEFUNC(X509V3_EXT_d2i) + RESOLVEFUNC(X509_EXTENSION_get_critical) + RESOLVEFUNC(X509_EXTENSION_get_data) + RESOLVEFUNC(BASIC_CONSTRAINTS_free) + RESOLVEFUNC(AUTHORITY_KEYID_free) + RESOLVEFUNC(GENERAL_NAME_free) + RESOLVEFUNC(ASN1_STRING_print) + 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) #if OPENSSL_VERSION_MAJOR < 3 - RESOLVEFUNC(SSL_CTX_load_verify_locations) + RESOLVEFUNC(SSL_CTX_load_verify_locations) #else - RESOLVEFUNC(SSL_CTX_load_verify_dir) + RESOLVEFUNC(SSL_CTX_load_verify_dir) #endif // OPENSSL_VERSION_MAJOR - RESOLVEFUNC(i2d_SSL_SESSION) - RESOLVEFUNC(d2i_SSL_SESSION) + RESOLVEFUNC(i2d_SSL_SESSION) + RESOLVEFUNC(d2i_SSL_SESSION) #ifndef OPENSSL_NO_NEXTPROTONEG - RESOLVEFUNC(SSL_select_next_proto) - RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) - RESOLVEFUNC(SSL_get0_next_proto_negotiated) - RESOLVEFUNC(SSL_set_alpn_protos) - RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) - RESOLVEFUNC(SSL_get0_alpn_selected) + RESOLVEFUNC(SSL_select_next_proto) + RESOLVEFUNC(SSL_CTX_set_next_proto_select_cb) + RESOLVEFUNC(SSL_get0_next_proto_negotiated) + RESOLVEFUNC(SSL_set_alpn_protos) + RESOLVEFUNC(SSL_CTX_set_alpn_select_cb) + RESOLVEFUNC(SSL_get0_alpn_selected) #endif // !OPENSSL_NO_NEXTPROTONEG #if QT_CONFIG(dtls) - RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) - RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) - RESOLVEFUNC(DTLS_server_method) - RESOLVEFUNC(DTLS_client_method) + RESOLVEFUNC(SSL_CTX_set_cookie_generate_cb) + RESOLVEFUNC(SSL_CTX_set_cookie_verify_cb) + RESOLVEFUNC(DTLS_server_method) + RESOLVEFUNC(DTLS_client_method) #endif // dtls - RESOLVEFUNC(CRYPTO_malloc) - RESOLVEFUNC(DH_new) - RESOLVEFUNC(DH_free) - RESOLVEFUNC(d2i_DHparams) - RESOLVEFUNC(i2d_DHparams) -#ifndef OPENSSL_NO_DEPRECATED_3_0 - RESOLVEFUNC(DH_check) -#endif // OPENSSL_NO_DEPRECATED_3_0 - RESOLVEFUNC(BN_bin2bn) + RESOLVEFUNC(CRYPTO_malloc) + RESOLVEFUNC(BN_bin2bn) #ifndef OPENSSL_NO_EC - RESOLVEFUNC(EC_KEY_dup) - RESOLVEFUNC(EC_KEY_new_by_curve_name) - RESOLVEFUNC(EC_KEY_free) - RESOLVEFUNC(EC_get_builtin_curves) + RESOLVEFUNC(EC_get_builtin_curves) #endif // OPENSSL_NO_EC - RESOLVEFUNC(PKCS12_parse) - RESOLVEFUNC(d2i_PKCS12_bio) - RESOLVEFUNC(PKCS12_free) + RESOLVEFUNC(PKCS12_parse) + RESOLVEFUNC(d2i_PKCS12_bio) + RESOLVEFUNC(PKCS12_free) + return true; + }(); - symbolsResolved.storeRelease(true); - return true; + return symbolsResolved; } #endif // QT_CONFIG(library) diff --git a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h index 1eb6387c23..a93c110b3f 100644 --- a/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h +++ b/src/plugins/tls/openssl/qsslsocket_openssl_symbols_p.h @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Copyright (C) 2014 BlackBerry Limited. All rights reserved. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// Copyright (C) 2014 BlackBerry Limited. All rights reserved. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only /**************************************************************************** ** @@ -221,7 +185,11 @@ QT_BEGIN_NAMESPACE // **************** Static declarations ****************** #endif // !defined QT_LINKED_OPENSSL - +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +typedef uint64_t qssloptions; +#else +typedef unsigned long qssloptions; +#endif // TODO: the following lines previously were a part of 1.1 - specific header. // To reduce the amount of the change, I'm directly copying and pasting the // content of the header here. Later, can be better sorted/split into groups, @@ -232,14 +200,12 @@ const unsigned char * q_ASN1_STRING_get0_data(const ASN1_STRING *x); BIO *q_BIO_new(const BIO_METHOD *a); const BIO_METHOD *q_BIO_s_mem(); -int q_DSA_bits(DSA *a); +void q_AUTHORITY_INFO_ACCESS_free(AUTHORITY_INFO_ACCESS *a); int q_EVP_CIPHER_CTX_reset(EVP_CIPHER_CTX *c); int q_EVP_PKEY_up_ref(EVP_PKEY *a); EVP_PKEY_CTX *q_EVP_PKEY_CTX_new(EVP_PKEY *pkey, ENGINE *e); void q_EVP_PKEY_CTX_free(EVP_PKEY_CTX *ctx); int q_EVP_PKEY_param_check(EVP_PKEY_CTX *ctx); -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(); @@ -247,7 +213,7 @@ 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); +qssloptions q_SSL_CTX_set_options(SSL_CTX *ctx, qssloptions 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); @@ -257,6 +223,8 @@ 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); +void q_ASN1_item_free(ASN1_VALUE *val, const ASN1_ITEM *it); +void q_X509V3_conf_free(CONF_VALUE *val); void q_X509_up_ref(X509 *a); long q_X509_get_version(X509 *a); @@ -265,8 +233,6 @@ void q_X509_STORE_set_verify_cb(X509_STORE *ctx, X509_STORE_CTX_verify_cb verify int q_X509_STORE_set_ex_data(X509_STORE *ctx, int idx, void *data); void *q_X509_STORE_get_ex_data(X509_STORE *r, int idx); 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) @@ -281,7 +247,6 @@ int q_DH_bits(DH *dh); | 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); @@ -380,13 +345,6 @@ int q_BN_num_bits(const BIGNUM *a); int q_BN_is_word(BIGNUM *a, BN_ULONG w); BN_ULONG q_BN_mod_word(const BIGNUM *a, BN_ULONG w); -#ifndef OPENSSL_NO_EC -const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); -int q_EC_GROUP_get_degree(const EC_GROUP* g); -#endif // OPENSSL_NO_EC - -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); void q_ERR_error_string_n(unsigned long e, char *buf, size_t len); @@ -417,23 +375,8 @@ const EVP_CIPHER *q_EVP_aes_256_cbc(); #endif // OPENSSL_NO_AES const EVP_MD *q_EVP_sha1(); -int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r); -int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); -int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); -int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b); -#ifndef OPENSSL_NO_EC -int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b); -#endif - -int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); void q_EVP_PKEY_free(EVP_PKEY *a); -RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); -DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); -DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a); -#ifndef OPENSSL_NO_EC -EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a); -#endif int q_EVP_PKEY_type(int a); EVP_PKEY *q_EVP_PKEY_new(); int q_i2d_X509(X509 *a, unsigned char **b); @@ -446,36 +389,17 @@ int q_OBJ_obj2txt(char *buf, int buf_len, ASN1_OBJECT *obj, int no_name); int q_OBJ_obj2nid(const ASN1_OBJECT *a); #define q_EVP_get_digestbynid(a) q_EVP_get_digestbyname(q_OBJ_nid2sn(a)) EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); -DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); -RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); - -#ifndef OPENSSL_NO_EC -EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -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); -EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); -#endif // OPENSSL_NO_EC -DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); -int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); -int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d, - int e, pem_password_cb *f, void *g); int q_PEM_write_bio_PrivateKey(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d, int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_PrivateKey_traditional(BIO *a, EVP_PKEY *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); 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); -int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); -int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); int q_PEM_write_bio_PUBKEY(BIO *a, EVP_PKEY *b); void q_RAND_seed(const void *a, int b); int q_RAND_status(); int q_RAND_bytes(unsigned char *b, int n); -RSA *q_RSA_new(); -void q_RSA_free(RSA *a); int q_SSL_accept(SSL *a); int q_SSL_clear(SSL *a); char *q_SSL_CIPHER_description(const SSL_CIPHER *a, char *b, int c); @@ -497,7 +421,6 @@ long q_SSL_CTX_callback_ctrl(SSL_CTX *, int, GenericCallbackType); int q_SSL_CTX_use_certificate(SSL_CTX *a, X509 *b); int q_SSL_CTX_use_certificate_file(SSL_CTX *a, const char *b, int c); int q_SSL_CTX_use_PrivateKey(SSL_CTX *a, EVP_PKEY *b); -int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b); int q_SSL_CTX_use_PrivateKey_file(SSL_CTX *a, const char *b, int c); X509_STORE *q_SSL_CTX_get_cert_store(const SSL_CTX *a); SSL_CONF_CTX *q_SSL_CONF_CTX_new(); @@ -512,7 +435,6 @@ const SSL_CIPHER *q_SSL_get_current_cipher(SSL *a); int q_SSL_version(const SSL *a); 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); SSL *q_SSL_new(SSL_CTX *a); SSL_CTX *q_SSL_get_SSL_CTX(SSL *a); @@ -580,23 +502,24 @@ X509 *q_X509_STORE_CTX_get_current_cert(X509_STORE_CTX *ctx); X509_STORE *q_X509_STORE_CTX_get0_store(X509_STORE_CTX *ctx); // Diffie-Hellman support +#ifndef OPENSSL_NO_DEPRECATED_3_0 DH *q_DH_new(); void q_DH_free(DH *dh); +int q_DH_check(DH *dh, int *codes); +void q_DH_get0_pqg(const DH *dh, const BIGNUM **p, const BIGNUM **q, const BIGNUM **g); + DH *q_d2i_DHparams(DH **a, const unsigned char **pp, long length); int q_i2d_DHparams(DH *a, unsigned char **p); -#ifndef OPENSSL_NO_DEPRECATED_3_0 -int q_DH_check(DH *dh, int *codes); +DH *q_PEM_read_bio_DHparams(BIO *a, DH **b, pem_password_cb *c, void *d); #endif // OPENSSL_NO_DEPRECATED_3_0 BIGNUM *q_BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret); #define q_SSL_CTX_set_tmp_dh(ctx, dh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_DH, 0, (char *)dh) +#define q_SSL_CTX_set_dh_auto(ctx, onoff) q_SSL_CTX_ctrl(ctx,SSL_CTRL_SET_DH_AUTO,onoff,NULL) #ifndef OPENSSL_NO_EC // EC Diffie-Hellman support -EC_KEY *q_EC_KEY_dup(const EC_KEY *src); -EC_KEY *q_EC_KEY_new_by_curve_name(int nid); -void q_EC_KEY_free(EC_KEY *ecdh); #define q_SSL_CTX_set_tmp_ecdh(ctx, ecdh) q_SSL_CTX_ctrl((ctx), SSL_CTRL_SET_TMP_ECDH, 0, (char *)ecdh) // EC curves management @@ -625,10 +548,6 @@ void q_GENERAL_NAME_free(GENERAL_NAME *a); #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_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() #if OPENSSL_VERSION_MAJOR < 3 @@ -746,6 +665,9 @@ int q_OCSP_id_cmp(OCSP_CERTID *a, OCSP_CERTID *b); void *q_CRYPTO_malloc(size_t num, const char *file, int line); #define q_OPENSSL_malloc(num) q_CRYPTO_malloc(num, "", 0) +void q_CRYPTO_free(void *str, const char *file, int line); +# define q_OPENSSL_free(addr) q_CRYPTO_free(addr, "", 0) +int q_CRYPTO_memcmp(const void * in_a, const void * in_b, size_t len); void q_SSL_set_info_callback(SSL *ssl, void (*cb) (const SSL *ssl, int type, int val)); const char *q_SSL_alert_type_string(int value); @@ -754,6 +676,90 @@ const char *q_SSL_alert_desc_string_long(int value); int q_SSL_CTX_get_security_level(const SSL_CTX *ctx); void q_SSL_CTX_set_security_level(SSL_CTX *ctx, int level); +// Here we have the ones that make difference between OpenSSL pre/post v3: +#if defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3 +X509 *q_SSL_get1_peer_certificate(SSL *a); +#define q_SSL_get_peer_certificate q_SSL_get1_peer_certificate +int q_EVP_PKEY_get_bits(const EVP_PKEY *pkey); +int q_EVP_PKEY_get_base_id(const EVP_PKEY *pkey); +#define q_EVP_PKEY_base_id q_EVP_PKEY_get_base_id +#else +X509 *q_SSL_get_peer_certificate(SSL *a); +int q_EVP_PKEY_base_id(EVP_PKEY *a); +#endif // OPENSSL_VERSION_MAJOR >= 3 + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +DSA *q_DSA_new(); +void q_DSA_free(DSA *a); + +RSA *q_RSA_new(); +void q_RSA_free(RSA *a); + +#ifndef OPENSSL_NO_EC + +EC_KEY *q_EC_KEY_dup(const EC_KEY *src); +EC_KEY *q_EC_KEY_new_by_curve_name(int nid); +void q_EC_KEY_free(EC_KEY *ecdh); + +#endif // OPENSSL_NO_EC + +int q_SSL_CTX_use_RSAPrivateKey(SSL_CTX *a, RSA *b); + +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); + +DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); +RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); + +int q_PEM_write_bio_DSA_PUBKEY(BIO *a, DSA *b); +int q_PEM_write_bio_RSA_PUBKEY(BIO *a, RSA *b); + +int q_PEM_write_bio_DSAPrivateKey(BIO *a, DSA *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); +int q_PEM_write_bio_RSAPrivateKey(BIO *a, RSA *b, const EVP_CIPHER *c, unsigned char *d, + int e, pem_password_cb *f, void *g); + +RSA *q_EVP_PKEY_get1_RSA(EVP_PKEY *a); +DSA *q_EVP_PKEY_get1_DSA(EVP_PKEY *a); +DH *q_EVP_PKEY_get1_DH(EVP_PKEY *a); + +int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); +int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); +int q_EVP_PKEY_set1_DH(EVP_PKEY *a, DH *b); + +int q_DH_bits(DH *dh); +int q_RSA_bits(RSA *a); +int q_DSA_bits(DSA *a); + +int q_EVP_PKEY_assign(EVP_PKEY *a, int b, void *r); +int q_EVP_PKEY_cmp(const EVP_PKEY *a, const EVP_PKEY *b); + +#ifndef OPENSSL_NO_EC + +EC_KEY *q_PEM_read_bio_EC_PUBKEY(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); +EC_KEY *q_PEM_read_bio_ECPrivateKey(BIO *a, EC_KEY **b, pem_password_cb *c, void *d); + +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); +int q_PEM_write_bio_EC_PUBKEY(BIO *a, EC_KEY *b); + +EC_KEY *q_EVP_PKEY_get1_EC_KEY(EVP_PKEY *a); +int q_EVP_PKEY_set1_EC_KEY(EVP_PKEY *a, EC_KEY *b); + +const EC_GROUP* q_EC_KEY_get0_group(const EC_KEY* k); +int q_EC_GROUP_get_degree(const EC_GROUP* g); + +#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)) + + +#endif // OPENSSL_NO_EC + +#endif // OPENSSL_NO_DEPRECATED_3_0 + QT_END_NAMESPACE #endif diff --git a/src/plugins/tls/openssl/qtls_openssl.cpp b/src/plugins/tls/openssl/qtls_openssl.cpp index 9ed9ab7538..57d09a649b 100644 --- a/src/plugins/tls/openssl/qtls_openssl.cpp +++ b/src/plugins/tls/openssl/qtls_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qx509_openssl_p.h" @@ -60,6 +24,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace { QSsl::AlertLevel tlsAlertLevel(int value) @@ -83,9 +49,9 @@ QSsl::AlertLevel tlsAlertLevel(int value) QString tlsAlertDescription(int value) { - QString description = QLatin1String(q_SSL_alert_desc_string_long(value)); + QString description = QLatin1StringView(q_SSL_alert_desc_string_long(value)); if (!description.size()) - description = QLatin1String("no description provided"); + description = "no description provided"_L1; return description; } @@ -126,7 +92,7 @@ QSslCertificate findCertificateToFetch(const QList<QSslError> &tlsErrors, bool c if (checkAIA) { const auto extensions = certToFetch.extensions(); for (const auto &ext : extensions) { - if (ext.oid() == QStringLiteral("1.3.6.1.5.5.7.1.1")) // See RFC 4325 + if (ext.oid() == u"1.3.6.1.5.5.7.1.1") // See RFC 4325 return certToFetch; } //The only reason we check this extensions is because an application set trusted @@ -169,9 +135,25 @@ int q_X509Callback(int ok, X509_STORE_CTX *ctx) // To retrieve this pointer the X509_STORE_CTX_get_ex_data() function can be // used with the correct index." const auto offset = QTlsBackendOpenSSL::s_indexForSSLExtraData - + TlsCryptographOpenSSL::errorOffsetInExData; - if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data(ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()))) + + TlsCryptographOpenSSL::errorOffsetInExData; + if (SSL *ssl = static_cast<SSL *>(q_X509_STORE_CTX_get_ex_data( + ctx, q_SSL_get_ex_data_X509_STORE_CTX_idx()))) { + + // We may be in a renegotiation, check if we are inside a call to SSL_read: + const auto tlsOffset = QTlsBackendOpenSSL::s_indexForSSLExtraData + + TlsCryptographOpenSSL::socketOffsetInExData; + auto tls = static_cast<TlsCryptographOpenSSL *>(q_SSL_get_ex_data(ssl, tlsOffset)); + Q_ASSERT(tls); + if (tls->isInSslRead()) { + // We are in a renegotiation, make a note of this for later. + // We'll check that the certificate is the same as the one we got during + // the initial handshake + tls->setRenegotiated(true); + return 1; + } + errors = ErrorListPtr(q_SSL_get_ex_data(ssl, offset)); + } } if (!errors) { @@ -258,15 +240,22 @@ static unsigned q_ssl_psk_restore_client(SSL *ssl, const char *hint, char *ident Q_ASSERT(tls->d); Q_ASSERT(tls->d->tlsMode() == QSslSocket::SslClientMode); #endif + unsigned retVal = 0; + + // Let developers opt-in to having the normal PSK callback get called for TLS 1.3 + // PSK (which works differently in a few ways, and is called at the start of every connection). + // When they do opt-in we just call the old callback from here. + if (qEnvironmentVariableIsSet("QT_USE_TLS_1_3_PSK")) + retVal = q_ssl_psk_client_callback(ssl, hint, identity, max_identity_len, psk, max_psk_len); + q_SSL_set_psk_client_callback(ssl, &q_ssl_psk_client_callback); - return 0; + return retVal; } static int q_ssl_psk_use_session_callback(SSL *ssl, const EVP_MD *md, const unsigned char **id, size_t *idlen, SSL_SESSION **sess) { - Q_UNUSED(ssl); Q_UNUSED(md); Q_UNUSED(id); Q_UNUSED(idlen); @@ -326,7 +315,7 @@ int qt_OCSP_status_server_callback(SSL *ssl, void *ocspRequest) return SSL_TLSEXT_ERR_ALERT_FATAL; std::copy(response.data(), response.data() + response.size(), derCopy); - // We don't check the return value: internally OpenSSL simply assignes the + // We don't check the return value: internally OpenSSL simply assigns the // pointer (it assumes it now owns this memory btw!) and the length. q_SSL_set_tlsext_status_ocsp_resp(ssl, derCopy, response.size()); @@ -472,7 +461,7 @@ bool qt_OCSP_certificate_match(OCSP_SINGLERESP *singleResponse, X509 *peerCert, const QSharedPointer<OCSP_CERTID> guard(recreatedId, q_OCSP_CERTID_free); if (q_OCSP_id_cmp(const_cast<OCSP_CERTID *>(certId), recreatedId)) { - qDebug(lcTlsBackend, "Certificate ID mismatch"); + qCDebug(lcTlsBackend, "Certificate ID mismatch"); return false; } // Bingo! @@ -501,16 +490,16 @@ void TlsCryptographOpenSSL::init(QSslSocket *qObj, QSslSocketPrivate *dObj) handshakeInterrupted = false; fetchAuthorityInformation = false; - caToFetch = QSslCertificate{}; + caToFetch.reset(); } -void TlsCryptographOpenSSL::checkSettingSslContext(QSharedPointer<QSslContext> tlsContext) +void TlsCryptographOpenSSL::checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) { - if (sslContextPointer.isNull()) - sslContextPointer = tlsContext; + if (!sslContextPointer) + sslContextPointer = std::move(tlsContext); } -QSharedPointer<QSslContext> TlsCryptographOpenSSL::sslContext() const +std::shared_ptr<QSslContext> TlsCryptographOpenSSL::sslContext() const { return sslContextPointer; } @@ -588,7 +577,7 @@ bool TlsCryptographOpenSSL::startHandshake() auto configuration = q->sslConfiguration(); if (!errorsReportedFromCallback) { const auto &peerCertificateChain = configuration.peerCertificateChain(); - for (const auto ¤tError : qAsConst(lastErrors)) { + for (const auto ¤tError : std::as_const(lastErrors)) { emit q->peerVerifyError(QTlsPrivate::X509CertificateOpenSSL::openSSLErrorToQSslError(currentError.code, peerCertificateChain.value(currentError.depth))); if (q->state() != QAbstractSocket::ConnectedState) @@ -708,7 +697,7 @@ bool TlsCryptographOpenSSL::startHandshake() // Translate errors from the error list into QSslErrors. errors.reserve(errors.size() + errorList.size()); - for (const auto &error : qAsConst(errorList)) + for (const auto &error : std::as_const(errorList)) errors << X509CertificateOpenSSL::openSSLErrorToQSslError(error.code, peerCertificateChain.value(error.depth)); if (!errors.isEmpty()) { @@ -760,7 +749,7 @@ void TlsCryptographOpenSSL::enableHandshakeContinuation() void TlsCryptographOpenSSL::cancelCAFetch() { fetchAuthorityInformation = false; - caToFetch = QSslCertificate{}; + caToFetch.reset(); } void TlsCryptographOpenSSL::continueHandshake() @@ -799,7 +788,7 @@ void TlsCryptographOpenSSL::continueHandshake() debugLineClientRandom.append(masterKey.toHex().toUpper()); debugLineClientRandom.append("\n"); - QString sslKeyFile = QDir::tempPath() + QLatin1String("/qt-ssl-keys"); + QString sslKeyFile = QDir::tempPath() + "/qt-ssl-keys"_L1; QFile file(sslKeyFile); if (!file.open(QIODevice::Append)) qCWarning(lcTlsBackend) << "could not open file" << sslKeyFile << "for appending"; @@ -815,7 +804,7 @@ void TlsCryptographOpenSSL::continueHandshake() // Cache this SSL session inside the QSslContext if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionSharing))) { if (!sslContextPointer->cacheSession(ssl)) { - sslContextPointer.clear(); // we could not cache the session + sslContextPointer.reset(); // we could not cache the session } else { // Cache the session for permanent usage as well if (!(configuration.testSslOption(QSsl::SslOptionDisableSessionPersistence))) { @@ -1040,7 +1029,25 @@ void TlsCryptographOpenSSL::transmit() break; } // Don't use SSL_pending(). It's very unreliable. + inSslRead = true; readBytes = q_SSL_read(ssl, buffer.reserve(bytesToRead), bytesToRead); + inSslRead = false; + if (renegotiated) { + renegotiated = false; + X509 *x509 = q_SSL_get_peer_certificate(ssl); + const auto peerCertificate = + QTlsPrivate::X509CertificateOpenSSL::certificateFromX509(x509); + // Fail the renegotiate if the certificate has changed, else: continue. + if (peerCertificate != q->peerCertificate()) { + const ScopedBool bg(inSetAndEmitError, true); + setErrorAndEmit( + d, QAbstractSocket::RemoteHostClosedError, + QSslSocket::tr( + "TLS certificate unexpectedly changed during renegotiation!")); + q->abort(); + return; + } + } if (readBytes > 0) { #ifdef QSSLSOCKET_DEBUG qCDebug(lcTlsBackend) << "TlsCryptographOpenSSL::transmit: decrypted" << readBytes << "bytes"; @@ -1127,6 +1134,7 @@ void TlsCryptographOpenSSL::disconnected() Q_ASSERT(d); auto *plainSocket = d->plainTcpSocket(); Q_ASSERT(plainSocket); + d->setEncrypted(false); if (plainSocket->bytesAvailable() <= 0) { destroySslContext(); @@ -1158,10 +1166,13 @@ QSsl::SslProtocol TlsCryptographOpenSSL::sessionProtocol() const const int ver = q_SSL_version(ssl); switch (ver) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case 0x301: return QSsl::TlsV1_0; case 0x302: return QSsl::TlsV1_1; +QT_WARNING_POP case 0x303: return QSsl::TlsV1_2; case 0x304: @@ -1363,7 +1374,7 @@ bool TlsCryptographOpenSSL::initSslContext() if (sslContextPointer->error() != QSslError::NoError) { setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError, sslContextPointer->errorString()); - sslContextPointer.clear(); // deletes the QSslContext + sslContextPointer.reset(); return false; } @@ -1491,7 +1502,7 @@ void TlsCryptographOpenSSL::destroySslContext() q_SSL_free(ssl); ssl = nullptr; } - sslContextPointer.clear(); + sslContextPointer.reset(); } void TlsCryptographOpenSSL::storePeerCertificates() @@ -1715,11 +1726,11 @@ unsigned TlsCryptographOpenSSL::pskClientTlsCallback(const char *hint, char *ide return 0; // Copy data back into OpenSSL - const int identityLength = qMin(authenticator.identity().length(), authenticator.maximumIdentityLength()); + const int identityLength = qMin(authenticator.identity().size(), authenticator.maximumIdentityLength()); std::memcpy(identity, authenticator.identity().constData(), identityLength); identity[identityLength] = 0; - const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength()); + const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength()); std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength); return pskLength; } @@ -1741,11 +1752,21 @@ unsigned TlsCryptographOpenSSL::pskServerTlsCallback(const char *identity, unsig return 0; // Copy data back into OpenSSL - const int pskLength = qMin(authenticator.preSharedKey().length(), authenticator.maximumPreSharedKeyLength()); + const int pskLength = qMin(authenticator.preSharedKey().size(), authenticator.maximumPreSharedKeyLength()); std::memcpy(psk, authenticator.preSharedKey().constData(), pskLength); return pskLength; } +bool TlsCryptographOpenSSL::isInSslRead() const +{ + return inSslRead; +} + +void TlsCryptographOpenSSL::setRenegotiated(bool renegotiated) +{ + this->renegotiated = renegotiated; +} + #ifdef Q_OS_WIN void TlsCryptographOpenSSL::fetchCaRootForCert(const QSslCertificate &cert) @@ -1782,7 +1803,7 @@ void TlsCryptographOpenSSL::caRootLoaded(QSslCertificate cert, QSslCertificate t Q_ASSERT(q); //Done, fetched already: - caToFetch = QSslCertificate{}; + caToFetch.reset(); if (fetchAuthorityInformation) { if (!q->sslConfiguration().caCertificates().contains(trustedRoot)) diff --git a/src/plugins/tls/openssl/qtls_openssl_p.h b/src/plugins/tls/openssl/qtls_openssl_p.h index 48c9223f99..65d21a395b 100644 --- a/src/plugins/tls/openssl/qtls_openssl_p.h +++ b/src/plugins/tls/openssl/qtls_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLS_OPENSSL_P_H #define QTLS_OPENSSL_P_H @@ -80,8 +44,8 @@ public: ~TlsCryptographOpenSSL(); void init(QSslSocket *qObj, QSslSocketPrivate *dObj) override; - void checkSettingSslContext(QSharedPointer<QSslContext> tlsContext) override; - QSharedPointer<QSslContext> sslContext() const override; + void checkSettingSslContext(std::shared_ptr<QSslContext> tlsContext) override; + std::shared_ptr<QSslContext> sslContext() const override; QList<QSslError> tlsErrors() const override; @@ -121,6 +85,9 @@ public: unsigned pskServerTlsCallback(const char *identity, unsigned char *psk, unsigned max_psk_len); + bool isInSslRead() const; + void setRenegotiated(bool renegotiated); + #ifdef Q_OS_WIN void fetchCaRootForCert(const QSslCertificate &cert); void caRootLoaded(QSslCertificate certificate, QSslCertificate trustedRoot); @@ -133,7 +100,7 @@ private: bool initSslContext(); void destroySslContext(); - QSharedPointer<QSslContext> sslContextPointer; + std::shared_ptr<QSslContext> sslContextPointer; SSL *ssl = nullptr; // TLSTODO: RAII. QList<QSslErrorEntry> errorList; @@ -144,7 +111,7 @@ private: QList<QOcspResponse> ocspResponses; - // This decription will go to setErrorAndEmit(SslHandshakeError, ocspErrorDescription) + // This description will go to setErrorAndEmit(SslHandshakeError, ocspErrorDescription) QString ocspErrorDescription; // These will go to sslErrors() QList<QSslError> ocspErrors; @@ -153,13 +120,16 @@ private: bool handshakeInterrupted = false; bool fetchAuthorityInformation = false; - QSslCertificate caToFetch; + std::optional<QSslCertificate> caToFetch; bool inSetAndEmitError = false; bool pendingFatalAlert = false; bool errorsReportedFromCallback = false; bool shutdown = false; + + bool inSslRead = false; + bool renegotiated = false; }; } // namespace QTlsPrivate diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp index 544ce1bcef..d73515724b 100644 --- a/src/plugins/tls/openssl/qtlsbackend_openssl.cpp +++ b/src/plugins/tls/openssl/qtlsbackend_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -53,10 +17,11 @@ #include <QtNetwork/qssl.h> #include <QtCore/qdir.h> -#include <QtCore/qdiriterator.h> +#include <QtCore/qdirlisting.h> #include <QtCore/qlist.h> #include <QtCore/qmutex.h> #include <QtCore/qscopeguard.h> +#include <QtCore/qset.h> #include "qopenssl_p.h" @@ -64,9 +29,15 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl"); +using namespace Qt::StringLiterals; -Q_GLOBAL_STATIC(QRecursiveMutex, qt_opensslInitMutex) +#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) +constexpr auto DefaultWarningLevel = QtCriticalMsg; +#else +constexpr auto DefaultWarningLevel = QtDebugMsg; +#endif + +Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.ossl", DefaultWarningLevel); static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphers, QList<QSslCipher> &defaultCiphers) @@ -79,9 +50,9 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe const auto ciph = QTlsBackendOpenSSL::qt_OpenSSL_cipher_to_QSslCipher(cipher); if (!ciph.isNull()) { // Unconditionally exclude ADH and AECDH ciphers since they offer no MITM protection - if (!ciph.name().toLower().startsWith(QLatin1String("adh")) && - !ciph.name().toLower().startsWith(QLatin1String("exp-adh")) && - !ciph.name().toLower().startsWith(QLatin1String("aecdh"))) { + if (!ciph.name().toLower().startsWith("adh"_L1) && + !ciph.name().toLower().startsWith("exp-adh"_L1) && + !ciph.name().toLower().startsWith("aecdh"_L1)) { ciphers << ciph; if (ciph.usedBits() >= 128) @@ -92,8 +63,6 @@ static void q_loadCiphersForConnection(SSL *connection, QList<QSslCipher> &ciphe } } -bool QTlsBackendOpenSSL::s_libraryLoaded = false; -bool QTlsBackendOpenSSL::s_loadedCiphersAndCerts = false; int QTlsBackendOpenSSL::s_indexForSSLExtraData = -1; QString QTlsBackendOpenSSL::getErrorsFromOpenSsl() @@ -103,9 +72,9 @@ QString QTlsBackendOpenSSL::getErrorsFromOpenSsl() unsigned long errNum; while ((errNum = q_ERR_get_error())) { if (!errorString.isEmpty()) - errorString.append(QLatin1String(", ")); + errorString.append(", "_L1); q_ERR_error_string_n(errNum, buf, sizeof buf); - errorString.append(QString::fromLatin1(buf)); // error is ascii according to man ERR_error_string + errorString.append(QLatin1StringView(buf)); // error is ascii according to man ERR_error_string } return errorString; } @@ -119,18 +88,16 @@ void QTlsBackendOpenSSL::logAndClearErrorQueue() void QTlsBackendOpenSSL::clearErrorQueue() { - const auto errs = getErrorsFromOpenSsl(); - Q_UNUSED(errs); + while (q_ERR_get_error()) + ; } bool QTlsBackendOpenSSL::ensureLibraryLoaded() { - if (!q_resolveOpenSslSymbols()) - return false; - - const QMutexLocker locker(qt_opensslInitMutex()); + static bool libraryLoaded = []() { + if (!q_resolveOpenSslSymbols()) + return false; - if (!s_libraryLoaded) { // Initialize OpenSSL. if (q_OPENSSL_init_ssl(0, nullptr) != 1) return false; @@ -152,10 +119,10 @@ bool QTlsBackendOpenSSL::ensureLibraryLoaded() return false; } - s_libraryLoaded = true; - } + return true; + }(); - return true; + return libraryLoaded; } QString QTlsBackendOpenSSL::backendName() const @@ -208,11 +175,24 @@ void QTlsBackendOpenSSL::ensureInitialized() const void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const { - const QMutexLocker locker(qt_opensslInitMutex()); + Q_CONSTINIT static bool initializationStarted = false; + Q_CONSTINIT static QAtomicInt initialized = Q_BASIC_ATOMIC_INITIALIZER(0); + Q_CONSTINIT static QRecursiveMutex initMutex; + + if (initialized.loadAcquire()) + return; - if (s_loadedCiphersAndCerts) + const QMutexLocker locker(&initMutex); + + if (initializationStarted || initialized.loadAcquire()) return; - s_loadedCiphersAndCerts = true; + + // Indicate that the initialization has already started in the current + // thread in case of recursive calls. The atomic variable cannot be used + // for this because it is checked without holding the init mutex. + initializationStarted = true; + + auto guard = qScopeGuard([] { initialized.storeRelease(1); }); resetDefaultCiphers(); resetDefaultEllipticCurves(); @@ -223,12 +203,12 @@ void QTlsBackendOpenSSL::ensureCiphersAndCertsLoaded() const QSslSocketPrivate::setRootCertOnDemandLoadingSupported(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 = QSslSocketPrivate::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()) { + const QList<QByteArray> dirs = QSslSocketPrivate::unixRootCertDirectories(); + const QStringList symLinkFilter{ + u"[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]"_s}; + for (const auto &dir : dirs) { + QDirListing dirList(QString::fromLatin1(dir), symLinkFilter, QDir::Files); + if (dirList.cbegin() != dirList.cend()) { // Not empty QSslSocketPrivate::setRootCertOnDemandLoadingSupported(true); break; } @@ -291,10 +271,13 @@ QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const protocols << QSsl::AnyProtocol; protocols << QSsl::SecureProtocols; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::TlsV1_0; protocols << QSsl::TlsV1_0OrLater; protocols << QSsl::TlsV1_1; protocols << QSsl::TlsV1_1OrLater; +QT_WARNING_POP protocols << QSsl::TlsV1_2; protocols << QSsl::TlsV1_2OrLater; @@ -304,8 +287,11 @@ QList<QSsl::SslProtocol> QTlsBackendOpenSSL::supportedProtocols() const #endif // TLS1_3_VERSION #if QT_CONFIG(dtls) +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::DtlsV1_0; protocols << QSsl::DtlsV1_0OrLater; +QT_WARNING_POP protocols << QSsl::DtlsV1_2; protocols << QSsl::DtlsV1_2OrLater; #endif // dtls @@ -318,8 +304,12 @@ QList<QSsl::SupportedFeature> QTlsBackendOpenSSL::supportedFeatures() const QList<QSsl::SupportedFeature> features; features << QSsl::SupportedFeature::CertificateVerification; + +#if !defined(OPENSSL_NO_TLSEXT) features << QSsl::SupportedFeature::ClientSideAlpn; features << QSsl::SupportedFeature::ServerSideAlpn; +#endif // !OPENSSL_NO_TLSEXT + features << QSsl::SupportedFeature::Ocsp; features << QSsl::SupportedFeature::Psk; features << QSsl::SupportedFeature::SessionTicket; @@ -357,8 +347,7 @@ QTlsPrivate::X509Certificate *QTlsBackendOpenSSL::createCertificate() const namespace QTlsPrivate { -// TLSTODO: remove. -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) +#ifdef Q_OS_ANDROID QList<QByteArray> fetchSslCertificateData(); #endif @@ -374,7 +363,9 @@ QList<QSslCertificate> systemCaCertificates() QList<QSslCertificate> systemCerts; #if defined(Q_OS_WIN) HCERTSTORE hSystemStore; - hSystemStore = CertOpenSystemStoreW(0, L"ROOT"); + hSystemStore = + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT"); if (hSystemStore) { PCCERT_CONTEXT pc = nullptr; while (1) { @@ -388,50 +379,30 @@ QList<QSslCertificate> systemCaCertificates() } CertCloseStore(hSystemStore, 0); } +#elif defined(Q_OS_ANDROID) + const QList<QByteArray> certData = fetchSslCertificateData(); + for (auto certDatum : certData) + systemCerts.append(QSslCertificate::fromData(certDatum, QSsl::Der)); #elif defined(Q_OS_UNIX) - QSet<QString> certFiles; - QDir currentDir; - QStringList nameFilters; - QList<QByteArray> directories; - QSsl::EncodingFormat platformEncodingFormat; -# ifndef Q_OS_ANDROID - directories = QSslSocketPrivate::unixRootCertDirectories(); - nameFilters << QLatin1String("*.pem") << QLatin1String("*.crt"); - platformEncodingFormat = QSsl::Pem; -# else - // Q_OS_ANDROID - QByteArray ministroPath = qgetenv("MINISTRO_SSL_CERTS_PATH"); // Set by Ministro - directories << ministroPath; - nameFilters << QLatin1String("*.der"); - platformEncodingFormat = QSsl::Der; -# ifndef Q_OS_ANDROID_EMBEDDED - if (ministroPath.isEmpty()) { - QList<QByteArray> certificateData = fetchSslCertificateData(); - for (int i = 0; i < certificateData.size(); ++i) { - systemCerts.append(QSslCertificate::fromData(certificateData.at(i), QSsl::Der)); - } - } else -# endif //Q_OS_ANDROID_EMBEDDED -# endif //Q_OS_ANDROID { - currentDir.setNameFilters(nameFilters); - for (int a = 0; a < directories.count(); a++) { - currentDir.setPath(QLatin1String(directories.at(a))); - QDirIterator it(currentDir); - while (it.hasNext()) { - it.next(); + const QList<QByteArray> directories = QSslSocketPrivate::unixRootCertDirectories(); + QSet<QString> certFiles = { + QStringLiteral("/etc/pki/tls/certs/ca-bundle.crt"), // Fedora, Mandriva + QStringLiteral("/usr/local/share/certs/ca-root-nss.crt") // FreeBSD's ca_root_nss + }; + QDir currentDir; + currentDir.setNameFilters(QStringList{QStringLiteral("*.pem"), QStringLiteral("*.crt")}); + for (const auto &directory : directories) { + currentDir.setPath(QLatin1StringView(directory)); + for (const auto &dirEntry : QDirListing(currentDir)) { // use canonical path here to not load the same certificate twice if symlinked - certFiles.insert(it.fileInfo().canonicalFilePath()); + certFiles.insert(dirEntry.canonicalFilePath()); } } - for (const QString& file : qAsConst(certFiles)) - systemCerts.append(QSslCertificate::fromPath(file, platformEncodingFormat)); -# ifndef Q_OS_ANDROID - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/etc/pki/tls/certs/ca-bundle.crt"), QSsl::Pem)); // Fedora, Mandriva - systemCerts.append(QSslCertificate::fromPath(QLatin1String("/usr/local/share/certs/ca-root-nss.crt"), QSsl::Pem)); // FreeBSD's ca_root_nss -# endif + for (const QString& file : std::as_const(certFiles)) + systemCerts.append(QSslCertificate::fromPath(file, QSsl::Pem)); } -#endif +#endif // platform #ifdef QSSLSOCKET_DEBUG qCDebug(lcTlsBackend) << "systemCaCertificates retrieval time " << timer.elapsed() << "ms"; qCDebug(lcTlsBackend) << "imported " << systemCerts.count() << " certificates"; @@ -636,3 +607,5 @@ void QTlsBackendOpenSSL::forceAutotestSecurityLevel() } QT_END_NAMESPACE + +#include "moc_qtlsbackend_openssl_p.cpp" diff --git a/src/plugins/tls/openssl/qtlsbackend_openssl_p.h b/src/plugins/tls/openssl/qtlsbackend_openssl_p.h index 93b6442a59..b9f1f95df0 100644 --- a/src/plugins/tls/openssl/qtlsbackend_openssl_p.h +++ b/src/plugins/tls/openssl/qtlsbackend_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSBACKEND_OPENSSL_P_H #define QTLSBACKEND_OPENSSL_P_H @@ -77,16 +41,13 @@ public: static void logAndClearErrorQueue(); static void clearErrorQueue(); - static bool ensureLibraryLoaded(); // Index used in SSL_get_ex_data to get the matching TlsCryptographerOpenSSL: - static bool s_libraryLoaded; - static bool s_loadedCiphersAndCerts; static int s_indexForSSLExtraData; static QString msgErrorsDuringHandshake(); static QSslCipher qt_OpenSSL_cipher_to_QSslCipher(const SSL_CIPHER *cipher); private: - + static bool ensureLibraryLoaded(); QString backendName() const override; bool isValid() const override; long tlsLibraryVersionNumber() const override; @@ -134,6 +95,8 @@ private: void forceAutotestSecurityLevel() override; }; +Q_DECLARE_LOGGING_CATEGORY(lcTlsBackend) + QT_END_NAMESPACE #endif // QTLSBACKEND_OPENSSL_P_H diff --git a/src/plugins/tls/openssl/qtlskey_openssl.cpp b/src/plugins/tls/openssl/qtlskey_openssl.cpp index 5333623d70..294fc2ffcd 100644 --- a/src/plugins/tls/openssl/qtlskey_openssl.cpp +++ b/src/plugins/tls/openssl/qtlskey_openssl.cpp @@ -1,43 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" +#include "qtlsbackend_openssl_p.h" #include "qtlskey_openssl_p.h" #include <QtNetwork/private/qsslkey_p.h> @@ -84,6 +49,16 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA void *phrase = const_cast<char *>(passPhrase.data()); +#ifdef OPENSSL_NO_DEPRECATED_3_0 + if (type == QSsl::PublicKey) + genericKey = q_PEM_read_bio_PUBKEY(bio, nullptr, nullptr, phrase); + else + genericKey = q_PEM_read_bio_PrivateKey(bio, nullptr, nullptr, phrase); + keyIsNull = !genericKey; + if (keyIsNull) + QTlsBackendOpenSSL::logAndClearErrorQueue(); +#else + if (algorithm == QSsl::Rsa) { RSA *result = (type == QSsl::PublicKey) ? q_PEM_read_bio_RSA_PUBKEY(bio, &rsa, nullptr, phrase) @@ -112,8 +87,10 @@ void TlsKeyOpenSSL::decodePem(KeyType type, KeyAlgorithm algorithm, const QByteA : q_PEM_read_bio_ECPrivateKey(bio, &ec, nullptr, phrase); if (ec && ec == result) keyIsNull = false; -#endif +#endif // OPENSSL_NO_EC } + +#endif // OPENSSL_NO_DEPRECATED_3_0 } QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QByteArray> *headers) const @@ -124,19 +101,19 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy QByteArray der(pem); int headerIndex = der.indexOf(header); - int footerIndex = der.indexOf(footer, headerIndex + header.length()); + int footerIndex = der.indexOf(footer, headerIndex + header.size()); if (type() != QSsl::PublicKey) { if (headerIndex == -1 || footerIndex == -1) { header = pkcs8Header(true); footer = pkcs8Footer(true); headerIndex = der.indexOf(header); - footerIndex = der.indexOf(footer, headerIndex + header.length()); + footerIndex = der.indexOf(footer, headerIndex + header.size()); } if (headerIndex == -1 || footerIndex == -1) { header = pkcs8Header(false); footer = pkcs8Footer(false); headerIndex = der.indexOf(header); - footerIndex = der.indexOf(footer, headerIndex + header.length()); + footerIndex = der.indexOf(footer, headerIndex + header.size()); } } if (headerIndex == -1 || footerIndex == -1) @@ -147,7 +124,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy if (der.contains("Proc-Type:")) { // taken from QHttpNetworkReplyPrivate::parseHeader int i = 0; - while (i < der.count()) { + while (i < der.size()) { int j = der.indexOf(':', i); // field-name if (j == -1) break; @@ -166,7 +143,7 @@ QByteArray TlsKeyOpenSSL::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy int length = i -(hasCR ? 1: 0) - j; value += der.mid(j, length).trimmed(); j = ++i; - } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t')); + } while (i < der.size() && (der.at(i) == ' ' || der.at(i) == '\t')); if (i == -1) break; // something is wrong @@ -182,6 +159,7 @@ void TlsKeyOpenSSL::clear(bool deep) { keyIsNull = true; +#ifndef OPENSSL_NO_DEPRECATED_3_0 if (algorithm() == QSsl::Rsa && rsa) { if (deep) q_RSA_free(rsa); @@ -204,18 +182,30 @@ void TlsKeyOpenSSL::clear(bool deep) ec = nullptr; } #endif +#endif // OPENSSL_NO_DEPRECATED_3_0 + if (algorithm() == QSsl::Opaque && opaque) { if (deep) q_EVP_PKEY_free(opaque); opaque = nullptr; } + + if (genericKey) { + // None of the above cleared it. genericKey is either + // initialised by PEM read operation, or from X509, and + // we are the owners and not sharing. So we free it. + q_EVP_PKEY_free(genericKey); + genericKey = nullptr; + } } Qt::HANDLE TlsKeyOpenSSL::handle() const { - switch (keyAlgorithm) { - case QSsl::Opaque: + if (keyAlgorithm == QSsl::Opaque) return Qt::HANDLE(opaque); + +#ifndef OPENSSL_NO_DEPRECATED_3_0 + switch (keyAlgorithm) { case QSsl::Rsa: return Qt::HANDLE(rsa); case QSsl::Dsa: @@ -229,6 +219,11 @@ Qt::HANDLE TlsKeyOpenSSL::handle() const default: return Qt::HANDLE(nullptr); } +#else + qCWarning(lcTlsBackend, + "This version of OpenSSL disabled direct manipulation with RSA/DSA/DH/EC_KEY structures, consider using QSsl::Opaque instead."); + return Qt::HANDLE(genericKey); +#endif } int TlsKeyOpenSSL::length() const @@ -236,6 +231,7 @@ int TlsKeyOpenSSL::length() const if (isNull() || algorithm() == QSsl::Opaque) return -1; +#ifndef OPENSSL_NO_DEPRECATED_3_0 switch (algorithm()) { case QSsl::Rsa: return q_RSA_bits(rsa); @@ -250,6 +246,10 @@ int TlsKeyOpenSSL::length() const default: return -1; } +#else // OPENSSL_NO_DEPRECATED_3_0 + Q_ASSERT(genericKey); + return q_EVP_PKEY_get_bits(genericKey); +#endif // OPENSSL_NO_DEPRECATED_3_0 } QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const @@ -272,54 +272,61 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const const auto bioRaii = qScopeGuard([bio]{q_BIO_free(bio);}); - bool fail = false; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +#define write_pubkey(alg, key) q_PEM_write_bio_##alg##_PUBKEY(bio, key) +#define write_privatekey(alg, key) \ + q_PEM_write_bio_##alg##PrivateKey(bio, key, cipher, (uchar *)passPhrase.data(), \ + passPhrase.size(), nullptr, nullptr) + +#else + +#define write_pubkey(alg, key) q_PEM_write_bio_PUBKEY(bio, genericKey) +#define write_privatekey(alg, key) \ + q_PEM_write_bio_PrivateKey_traditional(bio, genericKey, cipher, (uchar *)passPhrase.data(), passPhrase.size(), nullptr, nullptr) + +#endif // OPENSSL_NO_DEPRECATED_3_0 + bool fail = false; if (algorithm() == QSsl::Rsa) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_RSA_PUBKEY(bio, rsa)) - fail = true; - } else { - if (!q_PEM_write_bio_RSAPrivateKey( - bio, rsa, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_pubkey(RSA, rsa)) fail = true; - } + } else if (!write_privatekey(RSA, rsa)) { + fail = true; } } else if (algorithm() == QSsl::Dsa) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_DSA_PUBKEY(bio, dsa)) - fail = true; - } else { - if (!q_PEM_write_bio_DSAPrivateKey( - bio, dsa, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_pubkey(DSA, dsa)) fail = true; - } + } else if (!write_privatekey(DSA, dsa)) { + fail = true; } } else if (algorithm() == QSsl::Dh) { +#ifdef OPENSSL_NO_DEPRECATED_3_0 + EVP_PKEY *result = genericKey; +#else EVP_PKEY *result = q_EVP_PKEY_new(); + const auto guard = qScopeGuard([result]{if (result) q_EVP_PKEY_free(result);}); if (!result || !q_EVP_PKEY_set1_DH(result, dh)) { fail = true; - } else if (type() == QSsl::PublicKey) { + } else +#endif + if (type() == QSsl::PublicKey) { if (!q_PEM_write_bio_PUBKEY(bio, result)) fail = true; - } else if (!q_PEM_write_bio_PrivateKey( - bio, result, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + } else if (!q_PEM_write_bio_PrivateKey(bio, result, cipher, (uchar *)passPhrase.data(), + passPhrase.size(), nullptr, nullptr)) { fail = true; } - q_EVP_PKEY_free(result); #ifndef OPENSSL_NO_EC } else if (algorithm() == QSsl::Ec) { if (type() == QSsl::PublicKey) { - if (!q_PEM_write_bio_EC_PUBKEY(bio, ec)) + if (!write_pubkey(EC, ec)) fail = true; } else { - if (!q_PEM_write_bio_ECPrivateKey( - bio, ec, cipher, (uchar *)passPhrase.data(), - passPhrase.size(), nullptr, nullptr)) { + if (!write_privatekey(EC, ec)) fail = true; - } } #endif } else { @@ -332,6 +339,8 @@ QByteArray TlsKeyOpenSSL::toPem(const QByteArray &passPhrase) const const long size = q_BIO_get_mem_data(bio, &data); if (size > 0 && data) pem = QByteArray(data, size); + } else { + QTlsBackendOpenSSL::logAndClearErrorQueue(); } return pem; @@ -356,34 +365,37 @@ bool TlsKeyOpenSSL::fromEVP_PKEY(EVP_PKEY *pkey) if (!pkey) return false; +#ifndef OPENSSL_NO_DEPRECATED_3_0 +#define get_key(key, alg) key = q_EVP_PKEY_get1_##alg(pkey) +#else +#define get_key(key, alg) q_EVP_PKEY_up_ref(pkey); genericKey = pkey; +#endif + switch (q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey))) { case EVP_PKEY_RSA: keyIsNull = false; keyAlgorithm = QSsl::Rsa; keyType = QSsl::PrivateKey; - rsa = q_EVP_PKEY_get1_RSA(pkey); - + get_key(rsa, RSA); return true; case EVP_PKEY_DSA: keyIsNull = false; keyAlgorithm = QSsl::Dsa; keyType = QSsl::PrivateKey; - dsa = q_EVP_PKEY_get1_DSA(pkey); - + get_key(dsa, DSA); return true; case EVP_PKEY_DH: keyIsNull = false; keyAlgorithm = QSsl::Dh; keyType = QSsl::PrivateKey; - dh = q_EVP_PKEY_get1_DH(pkey); + get_key(dh, DH); return true; #ifndef OPENSSL_NO_EC case EVP_PKEY_EC: keyIsNull = false; keyAlgorithm = QSsl::Ec; keyType = QSsl::PrivateKey; - ec = q_EVP_PKEY_get1_EC_KEY(pkey); - + get_key(ec, EC_KEY); return true; #endif default:; @@ -437,7 +449,12 @@ QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, EVP_CIPHER_CTX *ctx = q_EVP_CIPHER_CTX_new(); q_EVP_CIPHER_CTX_reset(ctx); - q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc); + if (q_EVP_CipherInit(ctx, type, nullptr, nullptr, enc) != 1) { + q_EVP_CIPHER_CTX_free(ctx); + QTlsBackendOpenSSL::logAndClearErrorQueue(); + return {}; + } + q_EVP_CIPHER_CTX_set_key_length(ctx, key.size()); if (cipher == Cipher::Rc2Cbc) q_EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), nullptr); @@ -478,21 +495,31 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x) tlsKey->keyType = QSsl::PublicKey; +#ifndef OPENSSL_NO_DEPRECATED_3_0 + +#define get_pubkey(keyName, alg) tlsKey->keyName = q_EVP_PKEY_get1_##alg(pkey) + +#else + +#define get_pubkey(a, b) tlsKey->genericKey = pkey + +#endif + EVP_PKEY *pkey = q_X509_get_pubkey(x); Q_ASSERT(pkey); const int keyType = q_EVP_PKEY_type(q_EVP_PKEY_base_id(pkey)); if (keyType == EVP_PKEY_RSA) { - tlsKey->rsa = q_EVP_PKEY_get1_RSA(pkey); + get_pubkey(rsa, RSA); tlsKey->keyAlgorithm = QSsl::Rsa; tlsKey->keyIsNull = false; } else if (keyType == EVP_PKEY_DSA) { - tlsKey->dsa = q_EVP_PKEY_get1_DSA(pkey); + get_pubkey(dsa, DSA); tlsKey->keyAlgorithm = QSsl::Dsa; tlsKey->keyIsNull = false; #ifndef OPENSSL_NO_EC } else if (keyType == EVP_PKEY_EC) { - tlsKey->ec = q_EVP_PKEY_get1_EC_KEY(pkey); + get_pubkey(ec, EC_KEY); tlsKey->keyAlgorithm = QSsl::Ec; tlsKey->keyIsNull = false; #endif @@ -502,7 +529,10 @@ TlsKeyOpenSSL *TlsKeyOpenSSL::publicKeyFromX509(X509 *x) // error? (key is null) } +#ifndef OPENSSL_NO_DEPRECATED_3_0 q_EVP_PKEY_free(pkey); +#endif + return keyRaii.release(); } diff --git a/src/plugins/tls/openssl/qtlskey_openssl_p.h b/src/plugins/tls/openssl/qtlskey_openssl_p.h index 815770112f..4ee16ffc29 100644 --- a/src/plugins/tls/openssl/qtlskey_openssl_p.h +++ b/src/plugins/tls/openssl/qtlskey_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_OPENSSL_H #define QTLSKEY_OPENSSL_H @@ -67,6 +31,14 @@ #include <openssl/dsa.h> #include <openssl/dh.h> +#ifdef OPENSSL_NO_DEPRECATED_3_0 +typedef struct evp_pkey_st EVP_PKEY; +typedef struct dsa_st DSA; +typedef struct rsa_st RSA; +typedef struct dh_st DH; +typedef struct ec_key_st EC_KEY; +#endif // OPENSSL_NO_DEPRECATED_3_0 + QT_BEGIN_NAMESPACE QT_REQUIRE_CONFIG(ssl); @@ -115,6 +87,7 @@ public: #ifndef OPENSSL_NO_EC EC_KEY *ec; #endif + EVP_PKEY *genericKey; }; bool fromEVP_PKEY(EVP_PKEY *pkey); diff --git a/src/plugins/tls/openssl/qwindowscarootfetcher.cpp b/src/plugins/tls/openssl/qwindowscarootfetcher.cpp index 45ecbce258..a18aae0b71 100644 --- a/src/plugins/tls/openssl/qwindowscarootfetcher.cpp +++ b/src/plugins/tls/openssl/qwindowscarootfetcher.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qwindowscarootfetcher_p.h" #include "qx509_openssl_p.h" @@ -84,7 +48,7 @@ const QList<QSslCertificate> buildVerifiedChain(const QList<QSslCertificate> &ca // by setting custom CA certificates. We convert wincrypt's // structures in QSslCertificate and give OpenSSL the second // chance to verify the now (apparently) complete chain. - // In addition, wincrypt gives us a benifit of some checks + // In addition, wincrypt gives us a benefit of some checks // we don't have in OpenSSL back-end. Q_ASSERT(chainContext); @@ -281,3 +245,5 @@ QHCertStorePointer QWindowsCaRootFetcher::createAdditionalStore() const } QT_END_NAMESPACE + +#include "moc_qwindowscarootfetcher_p.cpp" diff --git a/src/plugins/tls/openssl/qwindowscarootfetcher_p.h b/src/plugins/tls/openssl/qwindowscarootfetcher_p.h index ed649b0936..715fd19945 100644 --- a/src/plugins/tls/openssl/qwindowscarootfetcher_p.h +++ b/src/plugins/tls/openssl/qwindowscarootfetcher_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QWINDOWSCAROOTFETCHER_P_H #define QWINDOWSCAROOTFETCHER_P_H diff --git a/src/plugins/tls/openssl/qx509_openssl.cpp b/src/plugins/tls/openssl/qx509_openssl.cpp index bf52c9345c..0cd3749f88 100644 --- a/src/plugins/tls/openssl/qx509_openssl.cpp +++ b/src/plugins/tls/openssl/qx509_openssl.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qsslsocket_openssl_symbols_p.h" #include "qtlsbackend_openssl_p.h" @@ -48,15 +12,18 @@ #include <QtNetwork/qsslsocket.h> #include <QtNetwork/qhostaddress.h> -#include <QtCore/qvarlengtharray.h> -#include <QtCore/qscopeguard.h> -#include <QtCore/qdatetime.h> -#include <QtCore/qiodevice.h> #include <QtCore/qendian.h> +#include <QtCore/qdatetime.h> #include <QtCore/qhash.h> +#include <QtCore/qiodevice.h> +#include <QtCore/qscopeguard.h> +#include <QtCore/qtimezone.h> +#include <QtCore/qvarlengtharray.h> QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace QTlsPrivate { namespace { @@ -111,7 +78,7 @@ QDateTime dateTimeFromASN1(const ASN1_TIME *aTime) if (q_ASN1_TIME_to_tm(aTime, &lTime)) { QDate resDate(lTime.tm_year + 1900, lTime.tm_mon + 1, lTime.tm_mday); QTime resTime(lTime.tm_hour, lTime.tm_min, lTime.tm_sec); - result = QDateTime(resDate, resTime, Qt::UTC); + result = QDateTime(resDate, resTime, QTimeZone::UTC); } return result; @@ -197,10 +164,27 @@ QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) } void *ext_internal = q_X509V3_EXT_d2i(ext); + if (!ext_internal) + return {}; + + const auto extCleaner = qScopeGuard([meth, ext_internal]{ + Q_ASSERT(ext_internal && meth); + + if (meth->it) + q_ASN1_item_free(static_cast<ASN1_VALUE *>(ext_internal), ASN1_ITEM_ptr(meth->it)); + else if (meth->ext_free) + meth->ext_free(ext_internal); + else + qCWarning(lcTlsBackend, "No method to free an unknown extension, a potential memory leak?"); + }); // If this extension can be converted - if (meth->i2v && ext_internal) { + if (meth->i2v) { STACK_OF(CONF_VALUE) *val = meth->i2v(meth, ext_internal, nullptr); + const auto stackCleaner = qScopeGuard([val]{ + if (val) + q_OPENSSL_sk_pop_free((OPENSSL_STACK *)val, (void(*)(void*))q_X509V3_conf_free); + }); QVariantMap map; QVariantList list; @@ -222,10 +206,12 @@ QVariant x509UnknownExtensionToValue(X509_EXTENSION *ext) return map; else return list; - } else if (meth->i2s && ext_internal) { - QVariant result(QString::fromUtf8(meth->i2s(meth, ext_internal))); + } else if (meth->i2s) { + const char *hexString = meth->i2s(meth, ext_internal); + QVariant result(hexString ? QString::fromUtf8(hexString) : QString{}); + q_OPENSSL_free((void *)hexString); return result; - } else if (meth->i2r && ext_internal) { + } else if (meth->i2r) { QByteArray result; BIO *bio = q_BIO_new(q_BIO_s_mem()); @@ -254,6 +240,31 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) { ASN1_OBJECT *obj = q_X509_EXTENSION_get_object(ext); int nid = q_OBJ_obj2nid(obj); + + // We cast away the const-ness here because some versions of openssl + // don't use const for the parameters in the functions pointers stored + // in the object. + X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); + + void *ext_internal = nullptr; // The value, returned by X509V3_EXT_d2i. + const auto extCleaner = qScopeGuard([meth, &ext_internal]() { + if (!meth || !ext_internal) + return; + + if (meth->it) + q_ASN1_item_free(static_cast<ASN1_VALUE *>(ext_internal), ASN1_ITEM_ptr(meth->it)); + else if (meth->ext_free) + meth->ext_free(ext_internal); + else + qWarning(lcTlsBackend, "Cannot free an extension, a potential memory leak?"); + }); + + const char * hexString = nullptr; // The value returned by meth->i2s. + const auto hexStringCleaner = qScopeGuard([&hexString](){ + if (hexString) + q_OPENSSL_free((void*)hexString); + }); + switch (nid) { case NID_basic_constraints: { @@ -261,9 +272,9 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) if (!basic) return {}; QVariantMap result; - result[QLatin1String("ca")] = basic->ca ? true : false; + result["ca"_L1] = basic->ca ? true : false; if (basic->pathlen) - result[QLatin1String("pathLenConstraint")] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen); + result["pathLenConstraint"_L1] = (qlonglong)q_ASN1_INTEGER_get(basic->pathlen); q_BASIC_CONSTRAINTS_free(basic); return result; @@ -295,21 +306,18 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) } } - q_OPENSSL_sk_pop_free((OPENSSL_STACK*)info, reinterpret_cast<void(*)(void *)>(q_OPENSSL_sk_free)); + q_AUTHORITY_INFO_ACCESS_free(info); return result; } break; case NID_subject_key_identifier: { - void *ext_internal = q_X509V3_EXT_d2i(ext); + ext_internal = q_X509V3_EXT_d2i(ext); if (!ext_internal) return {}; - // we cast away the const-ness here because some versions of openssl - // don't use const for the parameters in the functions pointers stored - // in the object. - X509V3_EXT_METHOD *meth = const_cast<X509V3_EXT_METHOD *>(q_X509V3_EXT_get(ext)); - return QVariant(QString::fromUtf8(meth->i2s(meth, ext_internal))); + hexString = meth->i2s(meth, ext_internal); + return QVariant(QString::fromUtf8(hexString)); } break; case NID_authority_key_identifier: @@ -323,7 +331,7 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) if (auth_key->keyid) { QByteArray keyid(reinterpret_cast<const char *>(auth_key->keyid->data), auth_key->keyid->length); - result[QLatin1String("keyid")] = keyid.toHex(); + result["keyid"_L1] = keyid.toHex(); } // issuer @@ -331,7 +339,7 @@ QVariant x509ExtensionToValue(X509_EXTENSION *ext) // serial if (auth_key->serial) - result[QLatin1String("serial")] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial); + result["serial"_L1] = (qlonglong)q_ASN1_INTEGER_get(auth_key->serial); q_AUTHORITY_KEYID_free(auth_key); return result; @@ -609,7 +617,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca const QString &hostName) { // This was previously QSslSocketPrivate::verify(). - if (certificateChain.count() <= 0) + if (certificateChain.size() <= 0) return {QSslError(QSslError::UnspecifiedError)}; QList<QSslError> errors; @@ -633,7 +641,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // certificate will be searched. Make sure to not have expired // certificates mixed with valid ones. // - // See also: QSslContext::fromConfiguration() + // See also: QSslContext::sharedFromConfiguration() if (caCertificate.expiryDate() >= now) { q_X509_STORE_add_cert(certStore, reinterpret_cast<X509 *>(caCertificate.handle())); } @@ -651,7 +659,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // Build the chain of intermediate certificates STACK_OF(X509) *intermediates = nullptr; - if (certificateChain.length() > 1) { + if (certificateChain.size() > 1) { intermediates = (STACK_OF(X509) *) q_OPENSSL_sk_new_null(); if (!intermediates) { @@ -703,7 +711,7 @@ QList<QSslError> X509CertificateOpenSSL::verify(const QList<QSslCertificate> &ca // Translate errors from the error list into QSslErrors. errors.reserve(errors.size() + lastErrors.size()); - for (const auto &error : qAsConst(lastErrors)) + for (const auto &error : std::as_const(lastErrors)) errors << openSSLErrorToQSslError(error.code, certificateChain.value(error.depth)); return errors; diff --git a/src/plugins/tls/openssl/qx509_openssl_p.h b/src/plugins/tls/openssl/qx509_openssl_p.h index 19f2f7614e..3b2e06f343 100644 --- a/src/plugins/tls/openssl/qx509_openssl_p.h +++ b/src/plugins/tls/openssl/qx509_openssl_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509_OPENSSL_P_H #define QX509_OPENSSL_P_H diff --git a/src/plugins/tls/schannel/CMakeLists.txt b/src/plugins/tls/schannel/CMakeLists.txt index 9f347416a4..a7f7fcd99f 100644 --- a/src/plugins/tls/schannel/CMakeLists.txt +++ b/src/plugins/tls/schannel/CMakeLists.txt @@ -1,8 +1,11 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QSchannelBackendPlugin - OUTPUT_NAME schannelbackend + OUTPUT_NAME qschannelbackend CLASS_NAME QSchannelBackend - TYPE tls - DEFAULT_IF WINDOWS + PLUGIN_TYPE tls + DEFAULT_IF WIN32 SOURCES ../shared/qtlskey_base_p.h ../shared/qtlskey_base.cpp @@ -21,10 +24,11 @@ qt_internal_add_plugin(QSchannelBackendPlugin qtlskey_schannel.cpp qtlskey_schannel_p.h qx509_schannel.cpp qx509_schannel_p.h LIBRARIES + Qt::NetworkPrivate crypt32 secur32 bcrypt ncrypt - PUBLIC_LIBRARIES - Qt::NetworkPrivate + DEFINES + QT_NO_CAST_FROM_ASCII ) diff --git a/src/plugins/tls/schannel/qtls_schannel.cpp b/src/plugins/tls/schannel/qtls_schannel.cpp index 2ba0651cba..a244a90ebc 100644 --- a/src/plugins/tls/schannel/qtls_schannel.cpp +++ b/src/plugins/tls/schannel/qtls_schannel.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only // #define QSSLSOCKET_DEBUG @@ -62,17 +26,11 @@ #include <security.h> #include <schnlsp.h> -#if NTDDI_VERSION >= NTDDI_WINBLUE && !defined(Q_CC_MINGW) +#if NTDDI_VERSION >= NTDDI_WINBLUE && defined(SECBUFFER_APPLICATION_PROTOCOLS) // ALPN = Application Layer Protocol Negotiation #define SUPPORTS_ALPN 1 #endif -// Redstone 5/1809 has all the API available, but TLS 1.3 is not enabled until a later version of -// Win 10, checked at runtime in supportsTls13() -#if defined(NTDDI_WIN10_RS5) && NTDDI_VERSION >= NTDDI_WIN10_RS5 -#define SUPPORTS_TLS13 1 -#endif - // Not defined in MinGW #ifndef SECBUFFER_ALERT #define SECBUFFER_ALERT 17 @@ -129,6 +87,12 @@ #ifndef SP_PROT_TLS1_3 #define SP_PROT_TLS1_3 (SP_PROT_TLS1_3_CLIENT | SP_PROT_TLS1_3_SERVER) #endif +#ifndef BCRYPT_ECDH_ALGORITHM +#define BCRYPT_ECDH_ALGORITHM L"ECDH" +#endif +#ifndef BCRYPT_ECDSA_ALGORITHM +#define BCRYPT_ECDSA_ALGORITHM L"ECDSA" +#endif /* @future!: @@ -150,10 +114,6 @@ - Check if SEC_I_INCOMPLETE_CREDENTIALS is still returned for both "missing certificate" and "missing PSK" when calling InitializeSecurityContext in "performHandshake". - Medium priority: - - Setting cipher-suites (or ALG_ID) - - People have survived without it in WinRT - Low priority: - Possibly make RAII wrappers for SecBuffer (which I commonly create QScopeGuards for) @@ -161,43 +121,349 @@ QT_BEGIN_NAMESPACE -Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.schannel"); +using namespace Qt::StringLiterals; + +Q_LOGGING_CATEGORY(lcTlsBackendSchannel, "qt.tlsbackend.schannel"); // Defined in qsslsocket_qt.cpp. QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); +namespace { +bool supportsTls13(); +} + namespace QTlsPrivate { +QList<QSslCipher> defaultCiphers(); + +struct SchannelCipherInfo { + const char *openSslCipherSuite; + const char *schannelCipherSuite; + const char *keyExchangeMethod; + const char *authenticationMethod; + const char *encryptionMethod; + int encryptionBits; + const char *hashMethod; + QList<QSsl::SslProtocol> protocols; +}; + +// The list of supported ciphers according to +// https://learn.microsoft.com/en-us/windows/win32/secauthn/tls-cipher-suites-in-windows-server-2022 +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED +std::array<SchannelCipherInfo, 44> schannelCipherInfo = {{ + {"TLS_AES_256_GCM_SHA384", "TLS_AES_256_GCM_SHA384", "", "", "AES", 256, "SHA384", {QSsl::TlsV1_3}}, + {"TLS_AES_128_GCM_SHA256", "TLS_AES_128_GCM_SHA256", "", "", "AES", 128, "SHA256", {QSsl::TlsV1_3}}, + {"ECDHE-ECDSA-AES256-GCM-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384", "ECDH", "ECDSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"ECDHE-ECDSA-AES128-GCM-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256", "ECDH", "ECDSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"ECDHE-RSA-AES256-GCM-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "ECDH", "RSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"ECDHE-RSA-AES128-GCM-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", "ECDH", "RSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"DHE-RSA-AES256-GCM-SHA384", "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "DH", "RSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"DHE-RSA-AES128-GCM-SHA256", "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "DH", "RSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"ECDHE-ECDSA-AES256-SHA384", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "ECDH", "ECDSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"ECDHE-ECDSA-AES128-SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "ECDH", "ECDSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"ECDHE-RSA-AES256-SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", "ECDH", "RSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"ECDHE-RSA-AES128-SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "ECDH", "RSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"ECDHE-ECDSA-AES256-SHA", "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "ECDH", "ECDSA", "AES", 256, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"ECDHE-ECDSA-AES128-SHA", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "ECDH", "ECDSA", "AES", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"ECDHE-RSA-AES256-SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", "ECDH", "RSA", "AES", 256, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"ECDHE-RSA-AES128-SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "ECDH", "RSA", "AES", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"AES256-GCM-SHA384", "TLS_RSA_WITH_AES_256_GCM_SHA384", "RSA", "RSA", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"AES128-GCM-SHA256", "TLS_RSA_WITH_AES_128_GCM_SHA256", "RSA", "RSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"AES256-SHA256", "TLS_RSA_WITH_AES_256_CBC_SHA256", "RSA", "RSA", "AES", 256, "SHA256", {QSsl::TlsV1_2}}, + {"AES128-SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", "RSA", "RSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"AES256-SHA", "TLS_RSA_WITH_AES_256_CBC_SHA", "RSA", "RSA", "AES", 256, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"AES128-SHA", "TLS_RSA_WITH_AES_128_CBC_SHA", "RSA", "RSA", "AES", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"DES-CBC3-SHA", "TLS_RSA_WITH_3DES_EDE_CBC_SHA", "RSA", "RSA", "3DES", 168, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"NULL-SHA256", "TLS_RSA_WITH_NULL_SHA256", "RSA", "RSA", "", 0, "SHA256", {QSsl::TlsV1_2}}, + {"NULL-SHA", "TLS_RSA_WITH_NULL_SHA", "RSA", "RSA", "", 0, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + + // the following cipher suites are not enabled by default in schannel provider + {"TLS_CHACHA20_POLY1305_SHA256", "TLS_CHACHA20_POLY1305_SHA256", "", "", "CHACHA20_POLY1305", 0, "", {QSsl::TlsV1_3}}, + {"DHE-RSA-AES256-SHA", "TLS_DHE_RSA_WITH_AES_256_CBC_SHA", "DH", "RSA", "AES", 256, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"DHE-RSA-AES128-SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "DH", "RSA", "AES", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"DHE-DSS-AES256-SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", "DH", "DSA", "AES", 256, "SHA256", {QSsl::TlsV1_2}}, + {"DHE-DSS-AES128-SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", "DH", "DSA", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"DHE-DSS-AES256-SHA", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA", "DH", "DSA", "AES", 256, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"DHE-DSS-AES128-SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", "DH", "DSA", "AES", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"EDH-DSS-DES-CBC3-SHA", "TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA", "DH", "DSA", "3DES", 168, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"RC4-SHA", "TLS_RSA_WITH_RC4_128_SHA", "RSA", "RSA", "RC4", 128, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"RC4-MD5", "TLS_RSA_WITH_RC4_128_MD5", "RSA", "RSA", "RC4", 128, "MD5", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"DES-CBC-SHA", "TLS_RSA_WITH_DES_CBC_SHA", "RSA", "RSA", "DES", 56, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"EDH-DSS-DES-CBC-SHA", "TLS_DHE_DSS_WITH_DES_CBC_SHA", "DH", "DSA", "DES", 56, "SHA1", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + {"NULL-MD5", "TLS_RSA_WITH_NULL_MD5", "RSA", "RSA", "", 0, "MD5", {QSsl::TlsV1_2, QSsl::TlsV1_1, QSsl::TlsV1_0}}, + + // PSK cipher suites + {"PSK-AES256-GCM-SHA384", "TLS_PSK_WITH_AES_256_GCM_SHA384", "PSK", "", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"PSK-AES128-GCM-SHA256", "TLS_PSK_WITH_AES_128_GCM_SHA256", "PSK", "", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"PSK-AES256-CBC-SHA384", "TLS_PSK_WITH_AES_256_CBC_SHA384", "PSK", "", "AES", 256, "SHA384", {QSsl::TlsV1_2}}, + {"PSK-AES128-CBC-SHA256", "TLS_PSK_WITH_AES_128_CBC_SHA256", "PSK", "", "AES", 128, "SHA256", {QSsl::TlsV1_2}}, + {"PSK-NULL-SHA384", "TLS_PSK_WITH_NULL_SHA384", "PSK", "", "", 0, "SHA384", {QSsl::TlsV1_2}}, + {"PSK-NULL-SHA256", "TLS_PSK_WITH_NULL_SHA256", "PSK", "", "", 0, "SHA256", {QSsl::TlsV1_2}}, +}}; +QT_WARNING_POP + +const SchannelCipherInfo *cipherInfoByOpenSslName(const QString &name) +{ + for (const auto &cipherInfo : schannelCipherInfo) { + if (name == QLatin1StringView(cipherInfo.openSslCipherSuite)) + return &cipherInfo; + } + + return nullptr; +} + +UNICODE_STRING cbcChainingMode = { + sizeof(BCRYPT_CHAIN_MODE_CBC) - 2, + sizeof(BCRYPT_CHAIN_MODE_CBC), + const_cast<PWSTR>(BCRYPT_CHAIN_MODE_CBC) +}; + +UNICODE_STRING gcmChainingMode = { + sizeof(BCRYPT_CHAIN_MODE_GCM) - 2, + sizeof(BCRYPT_CHAIN_MODE_GCM), + const_cast<PWSTR>(BCRYPT_CHAIN_MODE_GCM) +}; + +/** + Determines which algorithms are not used by the requested ciphers to build + up a black list that can be passed to SCH_CREDENTIALS. + */ +QList<CRYPTO_SETTINGS> cryptoSettingsForCiphers(const QList<QSslCipher> &ciphers) +{ + static const QList<QSslCipher> defaultCipherList = defaultCiphers(); + + if (defaultCipherList == ciphers) { + // the ciphers have not been restricted for this session, so no black listing needed + return {}; + } + + QList<const SchannelCipherInfo*> cipherInfo; + + for (const auto &cipher : ciphers) { + if (cipher.isNull()) + continue; + + const auto *info = cipherInfoByOpenSslName(cipher.name()); + if (!cipherInfo.contains(info)) + cipherInfo.append(info); + } + + QList<CRYPTO_SETTINGS> cryptoSettings; + + const auto assignUnicodeString = [](UNICODE_STRING &unicodeString, const wchar_t *characters) { + unicodeString.Length = static_cast<USHORT>(wcslen(characters) * sizeof(WCHAR)); + unicodeString.MaximumLength = unicodeString.Length + sizeof(UNICODE_NULL); + unicodeString.Buffer = const_cast<wchar_t*>(characters); + }; + + // black list of key exchange algorithms + const auto allKeyExchangeAlgorithms = {BCRYPT_RSA_ALGORITHM, + BCRYPT_ECDH_ALGORITHM, + BCRYPT_DH_ALGORITHM}; + + for (const auto &algorithm : allKeyExchangeAlgorithms) { + const auto method = QStringView(algorithm); + + const auto usesMethod = [method](const SchannelCipherInfo *info) { + return QLatin1StringView(info->keyExchangeMethod) == method; + }; + + const bool exclude = std::none_of(cipherInfo.cbegin(), cipherInfo.cend(), usesMethod); + + if (exclude) { + CRYPTO_SETTINGS settings = {}; + settings.eAlgorithmUsage = TlsParametersCngAlgUsageKeyExchange; + assignUnicodeString(settings.strCngAlgId, algorithm); + cryptoSettings.append(settings); + } + } + + // black list of authentication algorithms + const auto allAuthenticationAlgorithms = {BCRYPT_RSA_ALGORITHM, + BCRYPT_DSA_ALGORITHM, + BCRYPT_ECDSA_ALGORITHM, + BCRYPT_DH_ALGORITHM}; + + for (const auto &algorithm : allAuthenticationAlgorithms) { + const auto method = QStringView(algorithm); + + const auto usesMethod = [method](const SchannelCipherInfo *info) { + return QLatin1StringView(info->authenticationMethod) == method; + }; + + const bool exclude = std::none_of(cipherInfo.begin(), cipherInfo.end(), usesMethod); + + if (exclude) { + CRYPTO_SETTINGS settings = {}; + settings.eAlgorithmUsage = TlsParametersCngAlgUsageSignature; + assignUnicodeString(settings.strCngAlgId, algorithm); + cryptoSettings.append(settings); + } + } + + + // black list of encryption algorithms + const auto allEncryptionAlgorithms = {BCRYPT_AES_ALGORITHM, + BCRYPT_RC4_ALGORITHM, + BCRYPT_DES_ALGORITHM, + BCRYPT_3DES_ALGORITHM}; + + for (const auto &algorithm : allEncryptionAlgorithms) { + const auto method = QStringView(algorithm); + + if (method == QLatin1StringView("AES")) { + bool uses128Bit = false; + bool uses256Bit = false; + bool usesGcm = false; + bool usesCbc = false; + for (const auto *info : cipherInfo) { + if (QLatin1StringView(info->encryptionMethod) == method) { + uses128Bit = uses128Bit || (info->encryptionBits == 128); + uses256Bit = uses256Bit || (info->encryptionBits == 256); + usesGcm = usesGcm || + QLatin1StringView(info->schannelCipherSuite).contains("_GCM_"_L1); + usesCbc = usesCbc || + QLatin1StringView(info->schannelCipherSuite).contains("_CBC_"_L1); + } + } + + CRYPTO_SETTINGS settings = {}; + settings.eAlgorithmUsage = TlsParametersCngAlgUsageCipher; + assignUnicodeString(settings.strCngAlgId, algorithm); + + if (usesGcm && !usesCbc) { + settings.cChainingModes = 1; + settings.rgstrChainingModes = &cbcChainingMode; + } else if (!usesGcm && usesCbc) { + settings.cChainingModes = 1; + settings.rgstrChainingModes = &gcmChainingMode; + } + + if (!uses128Bit && uses256Bit) { + settings.dwMinBitLength = 256; + cryptoSettings.append(settings); + } else if (uses128Bit && !uses256Bit) { + settings.dwMaxBitLength = 128; + cryptoSettings.append(settings); + } else if (!uses128Bit && !uses256Bit) { + cryptoSettings.append(settings); + } + } else { + const auto usesMethod = [method](const SchannelCipherInfo *info) { + return QLatin1StringView(info->encryptionMethod) == method; + }; + + const bool exclude = std::none_of(cipherInfo.begin(), cipherInfo.end(), usesMethod); + + if (exclude) { + CRYPTO_SETTINGS settings = {}; + settings.eAlgorithmUsage = TlsParametersCngAlgUsageCipher; + assignUnicodeString(settings.strCngAlgId, algorithm); + cryptoSettings.append(settings); + } + } + } + + // black list of hash algorithms + const auto allHashAlgorithms = {BCRYPT_MD5_ALGORITHM, + BCRYPT_SHA1_ALGORITHM, + BCRYPT_SHA256_ALGORITHM, + BCRYPT_SHA384_ALGORITHM}; + + for (const auto &algorithm : allHashAlgorithms) { + const auto method = QStringView(algorithm); + + const auto usesMethod = [method](const SchannelCipherInfo *info) { + return QLatin1StringView(info->hashMethod) == method; + }; + + const bool exclude = std::none_of(cipherInfo.begin(), cipherInfo.end(), usesMethod); + + if (exclude) { + CRYPTO_SETTINGS settings = {}; + settings.eAlgorithmUsage = TlsParametersCngAlgUsageDigest; + assignUnicodeString(settings.strCngAlgId, algorithm); + cryptoSettings.append(settings); + } + } + + return cryptoSettings; +} + +QList<QSslCipher> ciphersByName(QStringView schannelSuiteName) +{ + QList<QSslCipher> ciphers; + + for (const auto &cipher : schannelCipherInfo) { + if (QLatin1StringView(cipher.schannelCipherSuite) == schannelSuiteName) { + for (const auto &protocol : cipher.protocols) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED + const QString protocolName = ( + protocol == QSsl::TlsV1_0 ? QStringLiteral("TLSv1.0") : + protocol == QSsl::TlsV1_1 ? QStringLiteral("TLSv1.1") : + protocol == QSsl::TlsV1_2 ? QStringLiteral("TLSv1.2") : + protocol == QSsl::TlsV1_3 ? QStringLiteral("TLSv1.3") : + QString()); +QT_WARNING_POP + + ciphers.append(QTlsBackend::createCiphersuite(QLatin1StringView(cipher.openSslCipherSuite), + QLatin1StringView(cipher.keyExchangeMethod), + QLatin1StringView(cipher.encryptionMethod), + QLatin1StringView(cipher.authenticationMethod), + cipher.encryptionBits, + protocol, protocolName)); + } + } + } + + return ciphers; +} + QList<QSslCipher> defaultCiphers() { - // Previously the code was in QSslSocketBackendPrivate. + ULONG contextFunctionsCount = {}; + PCRYPT_CONTEXT_FUNCTIONS contextFunctions = {}; + + const auto status = BCryptEnumContextFunctions(CRYPT_LOCAL, L"SSL", NCRYPT_SCHANNEL_INTERFACE, + &contextFunctionsCount, &contextFunctions); + if (!NT_SUCCESS(status)) { + qCWarning(lcTlsBackendSchannel, "Failed to enumerate ciphers"); + return {}; + } + + const bool supportsV13 = supportsTls13(); + QList<QSslCipher> ciphers; - // @temp (I hope), stolen from qsslsocket_winrt.cpp - const QString protocolStrings[] = { QStringLiteral("TLSv1"), QStringLiteral("TLSv1.1"), - QStringLiteral("TLSv1.2"), QStringLiteral("TLSv1.3") }; - const QSsl::SslProtocol protocols[] = { QSsl::TlsV1_0, QSsl::TlsV1_1, - QSsl::TlsV1_2, QSsl::TlsV1_3 }; - const int size = ARRAYSIZE(protocols); - static_assert(size == ARRAYSIZE(protocolStrings)); - ciphers.reserve(size); - for (int i = 0; i < size; ++i) { - const QSslCipher cipher = QTlsBackend::createCipher(QStringLiteral("Schannel"), - protocols[i], protocolStrings[i]); - ciphers.append(cipher); + for (ULONG index = 0; index < contextFunctions->cFunctions; ++index) { + const auto suiteName = QStringView(contextFunctions->rgpszFunctions[index]); + + const QList<QSslCipher> allCiphers = ciphersByName(suiteName); + + for (const auto &cipher : allCiphers) { + if (!supportsV13 && (cipher.protocol() == QSsl::TlsV1_3)) + continue; + + ciphers.append(cipher); + } } + BCryptFreeBuffer(contextFunctions); + return ciphers; +} +bool containsTls13Cipher(const QList<QSslCipher> &ciphers) +{ + return std::any_of(ciphers.cbegin(), ciphers.cend(), + [](const QSslCipher &cipher) { return cipher.protocol() == QSsl::TlsV1_3; }); } } // namespace QTlsPrivate -namespace { -bool supportsTls13(); -} - bool QSchannelBackend::s_loadedCiphersAndCerts = false; Q_GLOBAL_STATIC(QRecursiveMutex, qt_schannel_mutex) @@ -210,7 +476,7 @@ long QSchannelBackend::tlsLibraryVersionNumber() const QString QSchannelBackend::tlsLibraryVersionString() const { const auto os = QOperatingSystemVersion::current(); - return QLatin1String("Secure Channel, %1 %2.%3.%4") + return "Secure Channel, %1 %2.%3.%4"_L1 .arg(os.name(), QString::number(os.majorVersion()), QString::number(os.minorVersion()), @@ -224,7 +490,7 @@ long QSchannelBackend::tlsLibraryBuildVersionNumber() const QString QSchannelBackend::tlsLibraryBuildVersionString() const { - return QLatin1String("Secure Channel (NTDDI: 0x%1)") + return "Secure Channel (NTDDI: 0x%1)"_L1 .arg(QString::number(NTDDI_VERSION, 16).toUpper()); } @@ -264,10 +530,13 @@ QList<QSsl::SslProtocol> QSchannelBackend::supportedProtocols() const protocols << QSsl::AnyProtocol; protocols << QSsl::SecureProtocols; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::TlsV1_0; protocols << QSsl::TlsV1_0OrLater; protocols << QSsl::TlsV1_1; protocols << QSsl::TlsV1_1OrLater; +QT_WARNING_POP protocols << QSsl::TlsV1_2; protocols << QSsl::TlsV1_2OrLater; @@ -283,8 +552,10 @@ QList<QSsl::SupportedFeature> QSchannelBackend::supportedFeatures() const { QList<QSsl::SupportedFeature> features; +#ifdef SUPPORTS_ALPN features << QSsl::SupportedFeature::ClientSideAlpn; features << QSsl::SupportedFeature::ServerSideAlpn; +#endif return features; } @@ -325,7 +596,11 @@ QList<QSslCertificate> QSchannelBackend::systemCaCertificatesImplementation() // Similar to non-Darwin version found in qtlsbackend_openssl.cpp, // QTlsPrivate::systemCaCertificates function. QList<QSslCertificate> systemCerts; - auto hSystemStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT")); + + auto hSystemStore = QHCertStorePointer( + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT")); + if (hSystemStore) { PCCERT_CONTEXT pc = nullptr; while ((pc = CertFindCertificateInStore(hSystemStore.get(), X509_ASN_ENCODING, 0, @@ -346,6 +621,11 @@ QTlsPrivate::X509DerReaderPtr QSchannelBackend::X509DerReader() const return QTlsPrivate::X509CertificateGeneric::certificatesFromDer; } +QTlsPrivate::X509Pkcs12ReaderPtr QSchannelBackend::X509Pkcs12Reader() const +{ + return QTlsPrivate::X509CertificateSchannel::importPkcs12; +} + namespace { SecBuffer createSecBuffer(void *ptr, unsigned long length, unsigned long bufferType) @@ -410,7 +690,6 @@ QString schannelErrorToString(qint32 status) bool supportsTls13() { -#ifdef SUPPORTS_TLS13 static bool supported = []() { const auto current = QOperatingSystemVersion::current(); // 20221 just happens to be the preview version I run on my laptop where I tested TLS 1.3. @@ -418,10 +697,8 @@ bool supportsTls13() QOperatingSystemVersion(QOperatingSystemVersion::Windows, 10, 0, 20221); return current >= minimum; }(); + return supported; -#else - return false; -#endif } DWORD toSchannelProtocol(QSsl::SslProtocol protocol) @@ -430,9 +707,12 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol) switch (protocol) { case QSsl::UnknownProtocol: return DWORD(-1); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: - case QSsl::DtlsV1_2: case QSsl::DtlsV1_0OrLater: +QT_WARNING_POP + case QSsl::DtlsV1_2: case QSsl::DtlsV1_2OrLater: return DWORD(-1); // Not supported at the moment (@future) case QSsl::AnyProtocol: @@ -440,12 +720,15 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol) if (supportsTls13()) protocols |= SP_PROT_TLS1_3; break; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0: protocols = SP_PROT_TLS1_0; break; case QSsl::TlsV1_1: protocols = SP_PROT_TLS1_1; break; +QT_WARNING_POP case QSsl::TlsV1_2: protocols = SP_PROT_TLS1_2; break; @@ -455,7 +738,8 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol) else protocols = DWORD(-1); break; - case QSsl::SecureProtocols: // TLS v1.0 and later is currently considered secure +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::TlsV1_0OrLater: // For the "OrLater" protocols we fall through from one to the next, adding all of them // in ascending order @@ -464,6 +748,8 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol) case QSsl::TlsV1_1OrLater: protocols |= SP_PROT_TLS1_1; Q_FALLTHROUGH(); +QT_WARNING_POP + case QSsl::SecureProtocols: // TLS v1.2 and later is currently considered secure case QSsl::TlsV1_2OrLater: protocols |= SP_PROT_TLS1_2; Q_FALLTHROUGH(); @@ -477,17 +763,15 @@ DWORD toSchannelProtocol(QSsl::SslProtocol protocol) return protocols; } -#ifdef SUPPORTS_TLS13 // In the new API that descended down upon us we are not asked which protocols we want // but rather which protocols we don't want. So now we have this function to disable // anything that is not enabled. -DWORD toSchannelProtocolNegated(QSsl::SslProtocol protocol) +DWORD negatedSchannelProtocols(DWORD wantedProtocols) { DWORD protocols = SP_PROT_ALL; // all protocols - protocols &= ~toSchannelProtocol(protocol); // minus the one(s) we want + protocols &= ~wantedProtocols; // minus the one(s) we want return protocols; } -#endif /*! \internal @@ -504,8 +788,11 @@ QSsl::SslProtocol toQtSslProtocol(DWORD protocol) return q_protocol; \ } +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED MAP_PROTOCOL(SP_PROT_TLS1_0, QSsl::TlsV1_0) MAP_PROTOCOL(SP_PROT_TLS1_1, QSsl::TlsV1_1) +QT_WARNING_POP MAP_PROTOCOL(SP_PROT_TLS1_2, QSsl::TlsV1_2) MAP_PROTOCOL(SP_PROT_TLS1_3, QSsl::TlsV1_3) #undef MAP_PROTOCOL @@ -522,8 +809,7 @@ bool netscapeWrongCertType(const QList<QSslCertificateExtension> &extensions, bo const auto netscapeIt = std::find_if( extensions.cbegin(), extensions.cend(), [](const QSslCertificateExtension &extension) { - const auto netscapeCertType = QStringLiteral("2.16.840.1.113730.1.1"); - return extension.oid() == netscapeCertType; + return extension.oid() == u"2.16.840.1.113730.1.1"; }); if (netscapeIt != extensions.cend()) { const QByteArray netscapeCertTypeByte = netscapeIt->value().toByteArray(); @@ -551,11 +837,11 @@ bool isCertificateAuthority(const QList<QSslCertificateExtension> &extensions) { auto it = std::find_if(extensions.cbegin(), extensions.cend(), [](const QSslCertificateExtension &extension) { - return extension.name() == QLatin1String("basicConstraints"); + return extension.name() == "basicConstraints"_L1; }); if (it != extensions.cend()) { QVariantMap basicConstraints = it->value().toMap(); - return basicConstraints.value(QLatin1String("ca"), false).toBool(); + return basicConstraints.value("ca"_L1, false).toBool(); } return false; } @@ -570,7 +856,7 @@ bool matchesContextRequirements(DWORD attributes, DWORD requirements, bool isClient) { #ifdef QSSLSOCKET_DEBUG -#define DEBUG_WARN(message) qCWarning(lcTlsBackend, message) +#define DEBUG_WARN(message) qCWarning(lcTlsBackendSchannel, message) #else #define DEBUG_WARN(message) #endif @@ -614,21 +900,16 @@ Required const_reinterpret_cast(Actual *p) } #ifdef SUPPORTS_ALPN -bool supportsAlpn() -{ - return QOperatingSystemVersion::current() >= QOperatingSystemVersion::Windows8_1; -} - QByteArray createAlpnString(const QByteArrayList &nextAllowedProtocols) { QByteArray alpnString; - if (!nextAllowedProtocols.isEmpty() && supportsAlpn()) { + if (!nextAllowedProtocols.isEmpty()) { const QByteArray names = [&nextAllowedProtocols]() { QByteArray protocolString; for (QByteArray proto : nextAllowedProtocols) { if (proto.size() > 255) { - qCWarning(lcTlsBackend) << "TLS ALPN extension" << proto - << "is too long and will be ignored."; + qCWarning(lcTlsBackendSchannel) + << "TLS ALPN extension" << proto << "is too long and will be ignored."; continue; } else if (proto.isEmpty()) { continue; @@ -681,7 +962,8 @@ void retainExtraData(QByteArray &buffer, const SecBuffer &secBuffer) return; #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "We got SECBUFFER_EXTRA, will retain %lu bytes", secBuffer.cbBuffer); + qCDebug(lcTlsBackendSchannel, "We got SECBUFFER_EXTRA, will retain %lu bytes", + secBuffer.cbBuffer); #endif std::move(buffer.end() - secBuffer.cbBuffer, buffer.end(), buffer.begin()); buffer.resize(secBuffer.cbBuffer); @@ -691,13 +973,17 @@ qint64 checkIncompleteData(const SecBuffer &secBuffer) { if (secBuffer.BufferType == SECBUFFER_MISSING) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Need %lu more bytes.", secBuffer.cbBuffer); + qCDebug(lcTlsBackendSchannel, "Need %lu more bytes.", secBuffer.cbBuffer); #endif return secBuffer.cbBuffer; } return 0; } +DWORD defaultCredsFlag() +{ + return qEnvironmentVariableIsSet("QT_SCH_DEFAULT_CREDS") ? 0 : SCH_CRED_NO_DEFAULT_CREDS; +} } // anonymous namespace @@ -737,6 +1023,10 @@ bool TlsCryptographSchannel::sendToken(void *token, unsigned long tokenLength, b Q_ASSERT(d); auto *plainSocket = d->plainTcpSocket(); Q_ASSERT(plainSocket); + if (plainSocket->state() == QAbstractSocket::UnconnectedState || !plainSocket->isValid() + || !plainSocket->isOpen()) { + return false; + } const qint64 written = plainSocket->write(static_cast<const char *>(token), tokenLength); if (written != qint64(tokenLength)) { @@ -799,7 +1089,7 @@ bool TlsCryptographSchannel::acquireCredentialsHandle() Q_ASSERT(schannelState == SchannelState::InitializeHandshake); const bool isClient = d->tlsMode() == QSslSocket::SslClientMode; - const DWORD protocols = toSchannelProtocol(configuration.protocol()); + DWORD protocols = toSchannelProtocol(configuration.protocol()); if (protocols == DWORD(-1)) { setErrorAndEmit(d, QAbstractSocket::SslInvalidUserDataError, QSslSocket::tr("Invalid protocol chosen")); @@ -853,80 +1143,50 @@ bool TlsCryptographSchannel::acquireCredentialsHandle() certsCount = 1; Q_ASSERT(localCertContext); } - void *credentials = nullptr; -#ifdef SUPPORTS_TLS13 + + const QList<QSslCipher> ciphers = configuration.ciphers(); + if (!ciphers.isEmpty() && !containsTls13Cipher(ciphers)) + protocols &= ~SP_PROT_TLS1_3; + + QList<CRYPTO_SETTINGS> cryptoSettings; + if (!ciphers.isEmpty()) + cryptoSettings = cryptoSettingsForCiphers(ciphers); + TLS_PARAMETERS tlsParameters = { 0, nullptr, - toSchannelProtocolNegated(configuration.protocol()), // what protocols to disable + negatedSchannelProtocols(protocols), // what protocols to disable + static_cast<DWORD>(cryptoSettings.size()), + (cryptoSettings.isEmpty() ? nullptr : cryptoSettings.data()), + 0 + }; + + SCH_CREDENTIALS credentials = { + SCH_CREDENTIALS_VERSION, 0, + certsCount, + &localCertContext, nullptr, - 0 + 0, + nullptr, + 0, + SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT | defaultCredsFlag(), + 1, + &tlsParameters }; - if (supportsTls13()) { - SCH_CREDENTIALS *cred = new SCH_CREDENTIALS{ - SCH_CREDENTIALS_VERSION, - 0, - certsCount, - &localCertContext, - nullptr, - 0, - nullptr, - 0, - SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT - | SCH_CRED_NO_DEFAULT_CREDS, - 1, - &tlsParameters - }; - credentials = cred; - } else -#endif // SUPPORTS_TLS13 - { - SCHANNEL_CRED *cred = new SCHANNEL_CRED{ - SCHANNEL_CRED_VERSION, // dwVersion - certsCount, // cCreds - &localCertContext, // paCred (certificate(s) containing a private key for authentication) - nullptr, // hRootStore - - 0, // cMappers (reserved) - nullptr, // aphMappers (reserved) - - 0, // cSupportedAlgs - nullptr, // palgSupportedAlgs (nullptr = system default) - - protocols, // grbitEnabledProtocols - 0, // dwMinimumCipherStrength (0 = system default) - 0, // dwMaximumCipherStrength (0 = system default) - 0, // dwSessionLifespan (0 = schannel default, 10 hours) - SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT - | SCH_CRED_NO_DEFAULT_CREDS, // dwFlags - 0 // dwCredFormat (must be 0) - }; - credentials = cred; - } - Q_ASSERT(credentials != nullptr); TimeStamp expiration{}; auto status = AcquireCredentialsHandle(nullptr, // pszPrincipal (unused) const_cast<wchar_t *>(UNISP_NAME), // pszPackage isClient ? SECPKG_CRED_OUTBOUND : SECPKG_CRED_INBOUND, // fCredentialUse nullptr, // pvLogonID (unused) - credentials, // pAuthData + &credentials, // pAuthData nullptr, // pGetKeyFn (unused) nullptr, // pvGetKeyArgument (unused) &credentialHandle, // phCredential &expiration // ptsExpir ); -#ifdef SUPPORTS_TLS13 - if (supportsTls13()) { - delete static_cast<SCH_CREDENTIALS *>(credentials); - } else -#endif // SUPPORTS_TLS13 - { - delete static_cast<SCHANNEL_CRED *>(credentials); - } - if (status != SEC_E_OK) { setErrorAndEmit(d, QAbstractSocket::SslInternalError, schannelErrorToString(status)); return false; @@ -1131,7 +1391,8 @@ bool TlsCryptographSchannel::performHandshake() auto *plainSocket = d->plainTcpSocket(); Q_ASSERT(plainSocket); - if (plainSocket->state() == QAbstractSocket::UnconnectedState) { + if (plainSocket->state() == QAbstractSocket::UnconnectedState || !plainSocket->isValid() + || !plainSocket->isOpen()) { setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError, QSslSocket::tr("The TLS/SSL connection has been closed")); return false; @@ -1141,8 +1402,9 @@ bool TlsCryptographSchannel::performHandshake() Q_ASSERT(schannelState == SchannelState::PerformHandshake); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Bytes available from socket: %lld", plainSocket->bytesAvailable()); - qCDebug(lcTlsBackend, "intermediateBuffer size: %d", intermediateBuffer.size()); + qCDebug(lcTlsBackendSchannel, "Bytes available from socket: %lld", + plainSocket->bytesAvailable()); + qCDebug(lcTlsBackendSchannel, "intermediateBuffer size: %d", intermediateBuffer.size()); #endif if (missingData > plainSocket->bytesAvailable()) @@ -1299,13 +1561,18 @@ bool TlsCryptographSchannel::verifyHandshake() // Get session cipher info status = QueryContextAttributes(&contextHandle, + SECPKG_ATTR_CIPHER_INFO, + &cipherInfo); + CHECK_STATUS(status); + + status = QueryContextAttributes(&contextHandle, SECPKG_ATTR_CONNECTION_INFO, &connectionInfo); CHECK_STATUS(status); #ifdef SUPPORTS_ALPN const auto allowedProtos = configuration.allowedNextProtocols(); - if (!allowedProtos.isEmpty() && supportsAlpn()) { + if (!allowedProtos.isEmpty()) { SecPkgContext_ApplicationProtocol alpn; status = QueryContextAttributes(&contextHandle, SECPKG_ATTR_APPLICATION_PROTOCOL, @@ -1350,8 +1617,8 @@ bool TlsCryptographSchannel::verifyHandshake() && configuration.peerVerifyMode() != QSslSocket::PeerVerifyMode::QueryPeer)) { if (status != SEC_E_OK) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << "Couldn't retrieve peer certificate, status:" - << schannelErrorToString(status); + qCDebug(lcTlsBackendSchannel) << "Couldn't retrieve peer certificate, status:" + << schannelErrorToString(status); #endif const QSslError error{ QSslError::NoPeerCertificate }; sslErrors += error; @@ -1367,7 +1634,7 @@ bool TlsCryptographSchannel::verifyHandshake() if (!checkSslErrors() || q->state() != QAbstractSocket::ConnectedState) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << __func__ << "was unsuccessful. Paused:" << paused; + qCDebug(lcTlsBackendSchannel) << __func__ << "was unsuccessful. Paused:" << d->isPaused(); #endif // If we're paused then checkSslErrors returned false, but it's not an error return d->isPaused() && q->state() == QAbstractSocket::ConnectedState; @@ -1451,6 +1718,7 @@ void TlsCryptographSchannel::reset() deallocateContext(); freeCredentialsHandle(); // in case we already had one (@future: session resumption requires re-use) + cipherInfo = {}; connectionInfo = {}; streamSizes = {}; @@ -1500,8 +1768,10 @@ void TlsCryptographSchannel::transmit() return; // This function should not have been called // Can happen if called through QSslSocket::abort->QSslSocket::close->QSslSocket::flush->here - if (plainSocket->state() == QAbstractSocket::SocketState::UnconnectedState) + if (plainSocket->state() == QAbstractSocket::UnconnectedState || !plainSocket->isValid() + || !plainSocket->isOpen()) { return; + } if (schannelState != SchannelState::Done) { continueHandshake(); @@ -1550,7 +1820,8 @@ void TlsCryptographSchannel::transmit() fullMessage.resize(inputBuffers[0].cbBuffer + inputBuffers[1].cbBuffer + inputBuffers[2].cbBuffer); const qint64 bytesWritten = plainSocket->write(fullMessage); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Wrote %lld of total %d bytes", bytesWritten, fullMessage.length()); + qCDebug(lcTlsBackendSchannel, "Wrote %lld of total %d bytes", bytesWritten, + fullMessage.length()); #endif if (bytesWritten >= 0) { totalBytesWritten += bytesWritten; @@ -1572,128 +1843,131 @@ void TlsCryptographSchannel::transmit() } } - if (q->isEncrypted()) { // Decrypt data from remote - int totalRead = 0; - bool hadIncompleteData = false; - const auto readBufferMaxSize = d->maxReadBufferSize(); - while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) { - if (missingData > plainSocket->bytesAvailable() - && (!readBufferMaxSize || readBufferMaxSize >= missingData)) { + int totalRead = 0; + bool hadIncompleteData = false; + const auto readBufferMaxSize = d->maxReadBufferSize(); + while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) { + if (missingData > plainSocket->bytesAvailable() + && (!readBufferMaxSize || readBufferMaxSize >= missingData)) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "We're still missing %lld bytes, will check later.", missingData); + qCDebug(lcTlsBackendSchannel, "We're still missing %lld bytes, will check later.", + missingData); #endif - break; - } + break; + } - missingData = 0; - const qint64 bytesRead = readToBuffer(intermediateBuffer, plainSocket); + missingData = 0; + const qint64 bytesRead = readToBuffer(intermediateBuffer, plainSocket); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Read %lld encrypted bytes from the socket", bytesRead); + qCDebug(lcTlsBackendSchannel, "Read %lld encrypted bytes from the socket", bytesRead); #endif - if (intermediateBuffer.length() == 0 || (hadIncompleteData && bytesRead == 0)) { + if (intermediateBuffer.length() == 0 || (hadIncompleteData && bytesRead == 0)) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, (hadIncompleteData ? "No new data received, leaving loop!" - : "Nothing to decrypt, leaving loop!")); + qCDebug(lcTlsBackendSchannel, + hadIncompleteData ? "No new data received, leaving loop!" + : "Nothing to decrypt, leaving loop!"); #endif - break; - } - hadIncompleteData = false; + break; + } + hadIncompleteData = false; #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Total amount of bytes to decrypt: %d", intermediateBuffer.length()); + qCDebug(lcTlsBackendSchannel, "Total amount of bytes to decrypt: %d", + intermediateBuffer.length()); #endif - SecBuffer dataBuffer[4]{ - createSecBuffer(intermediateBuffer, SECBUFFER_DATA), - createSecBuffer(nullptr, 0, SECBUFFER_EMPTY), - createSecBuffer(nullptr, 0, SECBUFFER_EMPTY), - createSecBuffer(nullptr, 0, SECBUFFER_EMPTY) - }; - SecBufferDesc message{ - SECBUFFER_VERSION, - ARRAYSIZE(dataBuffer), - dataBuffer - }; - auto status = DecryptMessage(&contextHandle, &message, 0, nullptr); - if (status == SEC_E_OK || status == SEC_I_RENEGOTIATE || status == SEC_I_CONTEXT_EXPIRED) { - // There can still be 0 output even if it succeeds, this is fine - if (dataBuffer[1].cbBuffer > 0) { - // It is always decrypted in-place. - // But [0] is the STREAM_HEADER, [1] is the DATA and [2] is the STREAM_TRAILER. - // The pointers in all of those still point into 'intermediateBuffer'. - buffer.append(static_cast<char *>(dataBuffer[1].pvBuffer), - dataBuffer[1].cbBuffer); - totalRead += dataBuffer[1].cbBuffer; + SecBuffer dataBuffer[4]{ + createSecBuffer(intermediateBuffer, SECBUFFER_DATA), + createSecBuffer(nullptr, 0, SECBUFFER_EMPTY), + createSecBuffer(nullptr, 0, SECBUFFER_EMPTY), + createSecBuffer(nullptr, 0, SECBUFFER_EMPTY) + }; + SecBufferDesc message{ + SECBUFFER_VERSION, + ARRAYSIZE(dataBuffer), + dataBuffer + }; + auto status = DecryptMessage(&contextHandle, &message, 0, nullptr); + if (status == SEC_E_OK || status == SEC_I_RENEGOTIATE || status == SEC_I_CONTEXT_EXPIRED) { + // There can still be 0 output even if it succeeds, this is fine + if (dataBuffer[1].cbBuffer > 0) { + // It is always decrypted in-place. + // But [0] is the STREAM_HEADER, [1] is the DATA and [2] is the STREAM_TRAILER. + // The pointers in all of those still point into 'intermediateBuffer'. + buffer.append(static_cast<char *>(dataBuffer[1].pvBuffer), + dataBuffer[1].cbBuffer); + totalRead += dataBuffer[1].cbBuffer; #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "Decrypted %lu bytes. New read buffer size: %d", - dataBuffer[1].cbBuffer, buffer.size()); + qCDebug(lcTlsBackendSchannel, "Decrypted %lu bytes. New read buffer size: %d", + dataBuffer[1].cbBuffer, buffer.size()); #endif - } - if (dataBuffer[3].BufferType == SECBUFFER_EXTRA) { - // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel - // dataBuffer[3].cbBuffer indicates the amount of bytes _NOT_ processed, - // the rest need to be stored. - retainExtraData(intermediateBuffer, dataBuffer[3]); - } else { - intermediateBuffer.resize(0); - } } + if (dataBuffer[3].BufferType == SECBUFFER_EXTRA) { + // https://docs.microsoft.com/en-us/windows/desktop/secauthn/extra-buffers-returned-by-schannel + // dataBuffer[3].cbBuffer indicates the amount of bytes _NOT_ processed, + // the rest need to be stored. + retainExtraData(intermediateBuffer, dataBuffer[3]); + } else { + intermediateBuffer.resize(0); + } + } - if (status == SEC_E_INCOMPLETE_MESSAGE) { - missingData = checkIncompleteData(dataBuffer[0]); + if (status == SEC_E_INCOMPLETE_MESSAGE) { + missingData = checkIncompleteData(dataBuffer[0]); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "We didn't have enough data to decrypt anything, will try again!"); + qCDebug(lcTlsBackendSchannel, "We didn't have enough data to decrypt anything, will try again!"); #endif - // We try again, but if we don't get any more data then we leave - hadIncompleteData = true; - } else if (status == SEC_E_INVALID_HANDLE) { - // I don't think this should happen, if it does we're done... - qCWarning(lcTlsBackend, "The internal SSPI handle is invalid!"); - Q_UNREACHABLE(); - } else if (status == SEC_E_INVALID_TOKEN) { - qCWarning(lcTlsBackend, "Got SEC_E_INVALID_TOKEN!"); - Q_UNREACHABLE(); // Happened once due to a bug, but shouldn't generally happen(?) - } else if (status == SEC_E_MESSAGE_ALTERED) { - // The message has been altered, disconnect now. - shutdown = true; // skips sending the shutdown alert - disconnectFromHost(); - setErrorAndEmit(d, QAbstractSocket::SslInternalError, - schannelErrorToString(status)); - break; - } else if (status == SEC_E_OUT_OF_SEQUENCE) { - // @todo: I don't know if this one is actually "fatal".. - // This path might never be hit as it seems this is for connection-oriented connections, - // while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use). - shutdown = true; // skips sending the shutdown alert - disconnectFromHost(); - setErrorAndEmit(d, QAbstractSocket::SslInternalError, - schannelErrorToString(status)); - break; - } else if (status == SEC_I_CONTEXT_EXPIRED) { - // 'remote' has initiated a shutdown - disconnectFromHost(); - setErrorAndEmit(d, QAbstractSocket::RemoteHostClosedError, - schannelErrorToString(status)); - break; - } else if (status == SEC_I_RENEGOTIATE) { - // 'remote' wants to renegotiate + // We try again, but if we don't get any more data then we leave + hadIncompleteData = true; + } else if (status == SEC_E_INVALID_HANDLE) { + // I don't think this should happen, if it does we're done... + qCWarning(lcTlsBackendSchannel, "The internal SSPI handle is invalid!"); + Q_UNREACHABLE(); + } else if (status == SEC_E_INVALID_TOKEN) { + // Supposedly we have an invalid token, it's under-documented what + // this means, so to be safe we disconnect. + shutdown = true; + disconnectFromHost(); + setErrorAndEmit(d, QAbstractSocket::SslInternalError, schannelErrorToString(status)); + break; + } else if (status == SEC_E_MESSAGE_ALTERED) { + // The message has been altered, disconnect now. + shutdown = true; // skips sending the shutdown alert + disconnectFromHost(); + setErrorAndEmit(d, QAbstractSocket::SslInternalError, + schannelErrorToString(status)); + break; + } else if (status == SEC_E_OUT_OF_SEQUENCE) { + // @todo: I don't know if this one is actually "fatal".. + // This path might never be hit as it seems this is for connection-oriented connections, + // while SEC_E_MESSAGE_ALTERED is for stream-oriented ones (what we use). + shutdown = true; // skips sending the shutdown alert + disconnectFromHost(); + setErrorAndEmit(d, QAbstractSocket::SslInternalError, + schannelErrorToString(status)); + break; + } else if (status == SEC_I_CONTEXT_EXPIRED) { + // 'remote' has initiated a shutdown + disconnectFromHost(); + break; + } else if (status == SEC_I_RENEGOTIATE) { + // 'remote' wants to renegotiate #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend, "The peer wants to renegotiate."); + qCDebug(lcTlsBackendSchannel, "The peer wants to renegotiate."); #endif - schannelState = SchannelState::Renegotiate; - renegotiating = true; + schannelState = SchannelState::Renegotiate; + renegotiating = true; - // We need to call 'continueHandshake' or else there's no guarantee it ever gets called - continueHandshake(); - break; - } + // We need to call 'continueHandshake' or else there's no guarantee it ever gets called + continueHandshake(); + break; } + } - if (totalRead) { - if (bool *readyReadEmittedPointer = d->readyReadPointer()) - *readyReadEmittedPointer = true; - emit q->readyRead(); - emit q->channelReadyRead(0); - } + if (totalRead) { + if (bool *readyReadEmittedPointer = d->readyReadPointer()) + *readyReadEmittedPointer = true; + emit q->readyRead(); + emit q->channelReadyRead(0); } } @@ -1713,7 +1987,8 @@ void TlsCryptographSchannel::sendShutdown() if (status != SEC_E_OK) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << "Failed to apply shutdown control token:" << schannelErrorToString(status); + qCDebug(lcTlsBackendSchannel) + << "Failed to apply shutdown control token:" << schannelErrorToString(status); #endif return; } @@ -1771,7 +2046,8 @@ void TlsCryptographSchannel::sendShutdown() } } else { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << "Failed to initialize shutdown:" << schannelErrorToString(status); + qCDebug(lcTlsBackendSchannel) + << "Failed to initialize shutdown:" << schannelErrorToString(status); #endif } } @@ -1786,30 +2062,36 @@ void TlsCryptographSchannel::disconnectFromHost() if (SecIsValidHandle(&contextHandle)) { if (!shutdown) { shutdown = true; - if (plainSocket->state() != QAbstractSocket::UnconnectedState) { - if (q->isEncrypted()) { - // Read as much as possible because this is likely our last chance - qint64 tempMax = d->maxReadBufferSize(); - d->setMaxReadBufferSize(0); - transmit(); - d->setMaxReadBufferSize(tempMax); - sendShutdown(); - } + if (plainSocket->state() != QAbstractSocket::UnconnectedState && q->isEncrypted()) { + sendShutdown(); + transmit(); } } } - if (plainSocket->state() != QAbstractSocket::UnconnectedState) - plainSocket->disconnectFromHost(); + plainSocket->disconnectFromHost(); } void TlsCryptographSchannel::disconnected() { Q_ASSERT(d); + auto *plainSocket = d->plainTcpSocket(); + Q_ASSERT(plainSocket); + d->setEncrypted(false); shutdown = true; - d->setEncrypted(false); - deallocateContext(); - freeCredentialsHandle(); + if (plainSocket->bytesAvailable() > 0 || hasUndecryptedData()) { + // Read as much as possible because this is likely our last chance + qint64 tempMax = d->maxReadBufferSize(); + d->setMaxReadBufferSize(0); // Unlimited + transmit(); + d->setMaxReadBufferSize(tempMax); + // Since there were bytes still available we don't want to deallocate + // our context yet. It will happen later, when the socket is re-used or + // destroyed. + } else { + deallocateContext(); + freeCredentialsHandle(); + } } QSslCipher TlsCryptographSchannel::sessionCipher() const @@ -1817,8 +2099,17 @@ QSslCipher TlsCryptographSchannel::sessionCipher() const Q_ASSERT(q); if (!q->isEncrypted()) - return QSslCipher(); - return QSslCipher(QStringLiteral("Schannel"), sessionProtocol()); + return {}; + + const auto sessionProtocol = toQtSslProtocol(connectionInfo.dwProtocol); + + const auto ciphers = ciphersByName(QStringView(cipherInfo.szCipherSuite)); + for (const auto& cipher : ciphers) { + if (cipher.protocol() == sessionProtocol) + return cipher; + } + + return {}; } QSsl::SslProtocol TlsCryptographSchannel::sessionProtocol() const @@ -1965,7 +2256,7 @@ void TlsCryptographSchannel::initializeCertificateStores() localCertificateStore = createStoreFromCertificateChain(configuration.localCertificateChain(), configuration.privateKey()); if (localCertificateStore == nullptr) - qCWarning(lcTlsBackend, "Failed to load certificate chain!"); + qCWarning(lcTlsBackendSchannel, "Failed to load certificate chain!"); } } @@ -1992,7 +2283,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) nullptr)); if (!tempCertCollection) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend, "Failed to create certificate store collection!"); + qCWarning(lcTlsBackendSchannel, "Failed to create certificate store collection!"); #endif return false; } @@ -2002,15 +2293,20 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) // the Ca list, not just included during verification. // That being said, it's not trivial to add the root certificates (if and only if they // came from the system root store). And I don't see this mentioned in our documentation. - auto rootStore = QHCertStorePointer(CertOpenSystemStore(0, L"ROOT")); + auto rootStore = QHCertStorePointer( + CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, + CERT_STORE_READONLY_FLAG | CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT")); + if (!rootStore) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend, "Failed to open the system root CA certificate store!"); + qCWarning(lcTlsBackendSchannel, "Failed to open the system root CA certificate store!"); #endif return false; } else if (!CertAddStoreToCollection(tempCertCollection.get(), rootStore.get(), 0, 1)) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend, "Failed to add the system root CA certificate store to the certificate store collection!"); + qCWarning(lcTlsBackendSchannel, + "Failed to add the system root CA certificate store to the certificate store " + "collection!"); #endif return false; } @@ -2018,7 +2314,9 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) if (caCertificateStore) { if (!CertAddStoreToCollection(tempCertCollection.get(), caCertificateStore.get(), 0, 1)) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend, "Failed to add the user's CA certificate store to the certificate store collection!"); + qCWarning(lcTlsBackendSchannel, + "Failed to add the user's CA certificate store to the certificate store " + "collection!"); #endif return false; } @@ -2026,7 +2324,8 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) if (!CertAddStoreToCollection(tempCertCollection.get(), certContext->hCertStore, 0, 0)) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend, "Failed to add certificate's origin store to the certificate store collection!"); + qCWarning(lcTlsBackendSchannel, + "Failed to add certificate's origin store to the certificate store collection!"); #endif return false; } @@ -2111,18 +2410,48 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) verifyDepth = DWORD(q->peerVerifyDepth()); const auto &caCertificates = q->sslConfiguration().caCertificates(); + + if (!rootCertOnDemandLoadingAllowed() + && !(chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_PARTIAL_CHAIN) + && (q->peerVerifyMode() == QSslSocket::VerifyPeer + || (isClient && q->peerVerifyMode() == QSslSocket::AutoVerifyPeer))) { + // When verifying a peer Windows "helpfully" builds a chain that + // may include roots from the system store. But we don't want that if + // the user has set their own CA certificates. + // Since Windows claims this is not a partial chain the root is included + // and we have to check that it is one of our configured CAs. + CERT_CHAIN_ELEMENT *element = chain->rgpElement[chain->cElement - 1]; + QSslCertificate certificate = getCertificateFromChainElement(element); + if (!caCertificates.contains(certificate)) { + auto error = QSslError(QSslError::CertificateUntrusted, certificate); + sslErrors += error; + emit q->peerVerifyError(error); + if (q->state() != QAbstractSocket::ConnectedState) + return false; + } + } + QList<QSslCertificate> peerCertificateChain; for (DWORD i = 0; i < verifyDepth; i++) { CERT_CHAIN_ELEMENT *element = chain->rgpElement[i]; QSslCertificate certificate = getCertificateFromChainElement(element); + if (certificate.isNull()) { + const auto &previousCert = !peerCertificateChain.isEmpty() ? peerCertificateChain.last() + : QSslCertificate(); + auto error = QSslError(QSslError::SslError::UnableToGetIssuerCertificate, previousCert); + sslErrors += error; + emit q->peerVerifyError(error); + if (previousCert.isNull() || q->state() != QAbstractSocket::ConnectedState) + return false; + } const QList<QSslCertificateExtension> extensions = certificate.extensions(); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << "issuer:" << certificate.issuerDisplayName() - << "\nsubject:" << certificate.subjectDisplayName() - << "\nQSslCertificate info:" << certificate - << "\nextended error info:" << element->pwszExtendedErrorInfo - << "\nerror status:" << element->TrustStatus.dwErrorStatus; + qCDebug(lcTlsBackendSchannel) << "issuer:" << certificate.issuerDisplayName() + << "\nsubject:" << certificate.subjectDisplayName() + << "\nQSslCertificate info:" << certificate + << "\nextended error info:" << element->pwszExtendedErrorInfo + << "\nerror status:" << element->TrustStatus.dwErrorStatus; #endif peerCertificateChain.append(certificate); @@ -2216,7 +2545,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) if (element->TrustStatus.dwErrorStatus & CERT_TRUST_INVALID_BASIC_CONSTRAINTS) { auto it = std::find_if(extensions.cbegin(), extensions.cend(), [](const QSslCertificateExtension &extension) { - return extension.name() == QLatin1String("basicConstraints"); + return extension.name() == "basicConstraints"_L1; }); if (it != extensions.cend()) { // @Note: This is actually one of two errors: @@ -2224,7 +2553,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) // or the chain path length has been exceeded." QVariantMap basicConstraints = it->value().toMap(); QSslError error; - if (i > 0 && !basicConstraints.value(QLatin1String("ca"), false).toBool()) + if (i > 0 && !basicConstraints.value("ca"_L1, false).toBool()) error = QSslError(QSslError::InvalidPurpose, certificate); else error = QSslError(QSslError::PathLengthExceeded, certificate); @@ -2262,7 +2591,7 @@ bool TlsCryptographSchannel::verifyCertContext(CERT_CONTEXT *certContext) } if (!peerCertificateChain.isEmpty()) - QTlsBackend::storePeerCertificate(d, peerCertificateChain.first()); + QTlsBackend::storePeerCertificate(d, peerCertificateChain.constFirst()); const auto &configuration = q->sslConfiguration(); // Probably, updated by QTlsBackend::storePeerCertificate etc. // @Note: Somewhat copied from qsslsocket_mac.cpp diff --git a/src/plugins/tls/schannel/qtls_schannel_p.h b/src/plugins/tls/schannel/qtls_schannel_p.h index ca4f8f09cf..fab8777249 100644 --- a/src/plugins/tls/schannel/qtls_schannel_p.h +++ b/src/plugins/tls/schannel/qtls_schannel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2018 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2018 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLS_SCHANNEL_P_H #define QTLS_SCHANNEL_P_H @@ -129,6 +93,7 @@ private: QSslSocket *q = nullptr; QSslSocketPrivate *d = nullptr; + SecPkgContext_CipherInfo cipherInfo = {}; SecPkgContext_ConnectionInfo connectionInfo = {}; SecPkgContext_StreamSizes streamSizes = {}; diff --git a/src/plugins/tls/schannel/qtlsbackend_schannel_p.h b/src/plugins/tls/schannel/qtlsbackend_schannel_p.h index e53cf17f13..7c2d675e79 100644 --- a/src/plugins/tls/schannel/qtlsbackend_schannel_p.h +++ b/src/plugins/tls/schannel/qtlsbackend_schannel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSBACKEND_ST_P_H #define QTLSBACKEND_ST_P_H @@ -93,10 +57,13 @@ private: QTlsPrivate::X509PemReaderPtr X509PemReader() const override; QTlsPrivate::X509DerReaderPtr X509DerReader() const override; + QTlsPrivate::X509Pkcs12ReaderPtr X509Pkcs12Reader() const override; static bool s_loadedCiphersAndCerts; }; +Q_DECLARE_LOGGING_CATEGORY(lcTlsBackendSchannel) + QT_END_NAMESPACE #endif // QTLSBACKEND_ST_P_H diff --git a/src/plugins/tls/schannel/qtlskey_schannel.cpp b/src/plugins/tls/schannel/qtlskey_schannel.cpp index e407da2ed3..eb0a2371ab 100644 --- a/src/plugins/tls/schannel/qtlskey_schannel.cpp +++ b/src/plugins/tls/schannel/qtlskey_schannel.cpp @@ -1,44 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtNetwork/private/qssl_p.h> +#include "qtlsbackend_schannel_p.h" #include "qtlskey_schannel_p.h" #include "../shared/qwincrypt_p.h" @@ -50,6 +15,7 @@ #include <QtCore/qscopeguard.h> #include <QtCore/qbytearray.h> +#include <QtCore/qvarlengtharray.h> QT_BEGIN_NAMESPACE @@ -81,7 +47,7 @@ BCRYPT_ALG_HANDLE getHandle(QSslKeyPrivate::Cipher cipher) 0 // dwFlags ); if (status < 0) { - qCWarning(lcTlsBackend, "Failed to open algorithm handle (%ld)!", status); + qCWarning(lcTlsBackendSchannel, "Failed to open algorithm handle (%ld)!", status); return nullptr; } @@ -102,7 +68,7 @@ BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle, 0 // dwFlags ); if (status < 0) { - qCWarning(lcTlsBackend, "Failed to generate symmetric key (%ld)!", status); + qCWarning(lcTlsBackendSchannel, "Failed to generate symmetric key (%ld)!", status); return nullptr; } @@ -115,7 +81,8 @@ BCRYPT_KEY_HANDLE generateSymmetricKey(BCRYPT_ALG_HANDLE handle, ); if (status < 0) { BCryptDestroyKey(keyHandle); - qCWarning(lcTlsBackend, "Failed to change the symmetric key's chaining mode (%ld)!", status); + qCWarning(lcTlsBackendSchannel, "Failed to change the symmetric key's chaining mode (%ld)!", + status); return nullptr; } return keyHandle; @@ -160,7 +127,8 @@ QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const BCRYPT_BLOCK_PADDING // dwFlags ); if (status < 0) { - qCWarning(lcTlsBackend, "%s failed (%ld)!", encrypt ? "Encrypt" : "Decrypt", status); + qCWarning(lcTlsBackendSchannel, "%s failed (%ld)!", encrypt ? "Encrypt" : "Decrypt", + status); return {}; } } diff --git a/src/plugins/tls/schannel/qtlskey_schannel_p.h b/src/plugins/tls/schannel/qtlskey_schannel_p.h index 53c3b447ce..14d146dfd7 100644 --- a/src/plugins/tls/schannel/qtlskey_schannel_p.h +++ b/src/plugins/tls/schannel/qtlskey_schannel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_SCHANNEL_P_H #define QTLSKEY_SCHANNEL_P_H diff --git a/src/plugins/tls/schannel/qx509_schannel.cpp b/src/plugins/tls/schannel/qx509_schannel.cpp index 01a21c69f5..d9d82dce29 100644 --- a/src/plugins/tls/schannel/qx509_schannel.cpp +++ b/src/plugins/tls/schannel/qx509_schannel.cpp @@ -1,45 +1,11 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +#include "qtlsbackend_schannel_p.h" #include "qtlskey_schannel_p.h" #include "qx509_schannel_p.h" +#include <QtCore/private/qsystemerror_p.h> #include <QtNetwork/private/qsslcertificate_p.h> #include <memory> @@ -75,13 +41,173 @@ QSslCertificate X509CertificateSchannel::QSslCertificate_from_CERT_CONTEXT(const QByteArray derData = QByteArray((const char *)certificateContext->pbCertEncoded, certificateContext->cbCertEncoded); QSslCertificate certificate(derData, QSsl::Der); - - auto *certBackend = QTlsBackend::backend<X509CertificateSchannel>(certificate); - Q_ASSERT(certBackend); - certBackend->certificateContext = CertDuplicateCertificateContext(certificateContext); + if (!certificate.isNull()) { + auto *certBackend = QTlsBackend::backend<X509CertificateSchannel>(certificate); + Q_ASSERT(certBackend); + certBackend->certificateContext = CertDuplicateCertificateContext(certificateContext); + } return certificate; } +bool X509CertificateSchannel::importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, + QList<QSslCertificate> *caCertificates, + const QByteArray &passPhrase) +{ + // These are required + Q_ASSERT(device); + Q_ASSERT(key); + Q_ASSERT(cert); + + QByteArray pkcs12data = device->readAll(); + if (pkcs12data.size() == 0) + return false; + + CRYPT_DATA_BLOB dataBlob; + dataBlob.cbData = pkcs12data.size(); + dataBlob.pbData = reinterpret_cast<BYTE*>(pkcs12data.data()); + + const auto password = QString::fromUtf8(passPhrase); + + const DWORD flags = (CRYPT_EXPORTABLE | PKCS12_NO_PERSIST_KEY | PKCS12_PREFER_CNG_KSP); + + auto certStore = QHCertStorePointer(PFXImportCertStore(&dataBlob, + reinterpret_cast<LPCWSTR>(password.utf16()), + flags)); + + if (!certStore) { + qCWarning(lcTlsBackendSchannel, "Failed to import PFX data: %s", + qPrintable(QSystemError::windowsString())); + return false; + } + + // first extract the certificate with the private key + const auto certContext = QPCCertContextPointer(CertFindCertificateInStore(certStore.get(), + X509_ASN_ENCODING | + PKCS_7_ASN_ENCODING, + 0, + CERT_FIND_HAS_PRIVATE_KEY, + nullptr, nullptr)); + + if (!certContext) { + qCWarning(lcTlsBackendSchannel, "Failed to find certificate in PFX store: %s", + qPrintable(QSystemError::windowsString())); + return false; + } + + *cert = QSslCertificate_from_CERT_CONTEXT(certContext.get()); + + // retrieve the private key for the certificate + NCRYPT_KEY_HANDLE keyHandle = {}; + DWORD keyHandleSize = sizeof(keyHandle); + if (!CertGetCertificateContextProperty(certContext.get(), CERT_NCRYPT_KEY_HANDLE_PROP_ID, + &keyHandle, &keyHandleSize)) { + qCWarning(lcTlsBackendSchannel, "Failed to find private key handle in certificate context: %s", + qPrintable(QSystemError::windowsString())); + return false; + } + + SECURITY_STATUS securityStatus = ERROR_SUCCESS; + + // we need the 'NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG' to make NCryptExportKey succeed + DWORD policy = (NCRYPT_ALLOW_EXPORT_FLAG | NCRYPT_ALLOW_PLAINTEXT_EXPORT_FLAG); + DWORD policySize = sizeof(policy); + + securityStatus = NCryptSetProperty(keyHandle, NCRYPT_EXPORT_POLICY_PROPERTY, + reinterpret_cast<BYTE*>(&policy), policySize, 0); + if (securityStatus != ERROR_SUCCESS) { + qCWarning(lcTlsBackendSchannel, "Failed to update export policy of private key: 0x%x", + static_cast<unsigned int>(securityStatus)); + return false; + } + + DWORD blobSize = {}; + securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB, + nullptr, nullptr, 0, &blobSize, 0); + if (securityStatus != ERROR_SUCCESS) { + qCWarning(lcTlsBackendSchannel, "Failed to retrieve private key size: 0x%x", + static_cast<unsigned int>(securityStatus)); + return false; + } + + std::vector<BYTE> blob(blobSize); + securityStatus = NCryptExportKey(keyHandle, {}, BCRYPT_RSAFULLPRIVATE_BLOB, + nullptr, blob.data(), blobSize, &blobSize, 0); + if (securityStatus != ERROR_SUCCESS) { + qCWarning(lcTlsBackendSchannel, "Failed to retrieve private key from certificate: 0x%x", + static_cast<unsigned int>(securityStatus)); + return false; + } + + DWORD privateKeySize = {}; + + if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, CNG_RSA_PRIVATE_KEY_BLOB, + blob.data(), nullptr, &privateKeySize)) { + qCWarning(lcTlsBackendSchannel, "Failed to encode private key to key info: %s", + qPrintable(QSystemError::windowsString())); + return false; + } + + std::vector<BYTE> privateKeyData(privateKeySize); + + CRYPT_PRIVATE_KEY_INFO privateKeyInfo = {}; + privateKeyInfo.Algorithm.pszObjId = const_cast<PSTR>(szOID_RSA_RSA); + privateKeyInfo.PrivateKey.cbData = privateKeySize; + privateKeyInfo.PrivateKey.pbData = privateKeyData.data(); + + if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + CNG_RSA_PRIVATE_KEY_BLOB, blob.data(), + privateKeyInfo.PrivateKey.pbData, &privateKeyInfo.PrivateKey.cbData)) { + qCWarning(lcTlsBackendSchannel, "Failed to encode private key to key info: %s", + qPrintable(QSystemError::windowsString())); + return false; + } + + + DWORD derSize = {}; + + if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO, + &privateKeyInfo, nullptr, &derSize)) { + qCWarning(lcTlsBackendSchannel, "Failed to encode key info to DER format: %s", + qPrintable(QSystemError::windowsString())); + + return false; + } + + QByteArray derData(derSize, Qt::Uninitialized); + + if (!CryptEncodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, PKCS_PRIVATE_KEY_INFO, + &privateKeyInfo, reinterpret_cast<BYTE*>(derData.data()), &derSize)) { + qCWarning(lcTlsBackendSchannel, "Failed to encode key info to DER format: %s", + qPrintable(QSystemError::windowsString())); + + return false; + } + + *key = QSslKey(derData, QSsl::Rsa, QSsl::Der, QSsl::PrivateKey); + if (key->isNull()) { + qCWarning(lcTlsBackendSchannel, "Failed to parse private key from DER format"); + return false; + } + + // fetch all the remaining certificates as CA certificates + if (caCertificates) { + PCCERT_CONTEXT caCertContext = nullptr; + while ((caCertContext = CertFindCertificateInStore(certStore.get(), + X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + 0, CERT_FIND_ANY, nullptr, caCertContext))) { + if (CertCompareCertificate(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, + certContext->pCertInfo, caCertContext->pCertInfo)) + continue; // ignore the certificate with private key + + auto caCertificate = QSslCertificate_from_CERT_CONTEXT(caCertContext); + + caCertificates->append(caCertificate); + } + } + + return true; +} + } // namespace QTlsPrivate QT_END_NAMESPACE diff --git a/src/plugins/tls/schannel/qx509_schannel_p.h b/src/plugins/tls/schannel/qx509_schannel_p.h index bf39229e96..4625c9584c 100644 --- a/src/plugins/tls/schannel/qx509_schannel_p.h +++ b/src/plugins/tls/schannel/qx509_schannel_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509_SCHANNEL_P_H #define QX509_SCHANNEL_P_H @@ -72,6 +36,10 @@ public: Qt::HANDLE handle() const override; static QSslCertificate QSslCertificate_from_CERT_CONTEXT(const CERT_CONTEXT *certificateContext); + + static bool importPkcs12(QIODevice *device, QSslKey *key, QSslCertificate *cert, + QList<QSslCertificate> *caCertificates, + const QByteArray &passPhrase); private: const CERT_CONTEXT *certificateContext = nullptr; diff --git a/src/plugins/tls/securetransport/CMakeLists.txt b/src/plugins/tls/securetransport/CMakeLists.txt index 6d86191879..bb560229e8 100644 --- a/src/plugins/tls/securetransport/CMakeLists.txt +++ b/src/plugins/tls/securetransport/CMakeLists.txt @@ -1,7 +1,10 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QSecureTransportBackendPlugin - OUTPUT_NAME securetransportbackend + OUTPUT_NAME qsecuretransportbackend CLASS_NAME QSecureTransportBackend - TYPE tls + PLUGIN_TYPE tls DEFAULT_IF APPLE SOURCES ../shared/qsslsocket_mac_shared.cpp @@ -24,10 +27,9 @@ qt_internal_add_plugin(QSecureTransportBackendPlugin qx509_st_p.h qtls_st.cpp qtls_st_p.h - PUBLIC_LIBRARIES + LIBRARIES Qt::NetworkPrivate Qt::CorePrivate - LIBRARIES ${FWCoreFoundation} ${FWSecurity} ) diff --git a/src/plugins/tls/securetransport/qtls_st.cpp b/src/plugins/tls/securetransport/qtls_st.cpp index 306f184f25..48b7f3364f 100644 --- a/src/plugins/tls/securetransport/qtls_st.cpp +++ b/src/plugins/tls/securetransport/qtls_st.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtls_st_p.h" #include "qtlsbackend_st_p.h" @@ -76,6 +40,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + // Defined in qsslsocket_qt.cpp. QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); @@ -109,7 +75,7 @@ EphemeralSecKeychain::EphemeralSecKeychain() { const auto uuid = QUuid::createUuid(); if (uuid.isNull()) { - qCWarning(lcTlsBackend) << "Failed to create a unique keychain name"; + qCWarning(lcSecureTransport) << "Failed to create a unique keychain name"; return; } @@ -117,10 +83,10 @@ EphemeralSecKeychain::EphemeralSecKeychain() Q_ASSERT(uuidAsByteArray.size() > 2); Q_ASSERT(uuidAsByteArray.startsWith('{')); Q_ASSERT(uuidAsByteArray.endsWith('}')); - const auto uuidAsString = QLatin1String(uuidAsByteArray.data(), uuidAsByteArray.size()).mid(1, uuidAsByteArray.size() - 2); + const auto uuidAsString = QLatin1StringView(uuidAsByteArray.data(), uuidAsByteArray.size()).mid(1, uuidAsByteArray.size() - 2); const QString keychainName - = QDir::tempPath() + QDir::separator() + uuidAsString + QLatin1String(".keychain"); + = QDir::tempPath() + QDir::separator() + uuidAsString + ".keychain"_L1; // SecKeychainCreate, pathName parameter: // // "A constant character string representing the POSIX path indicating where @@ -136,14 +102,14 @@ EphemeralSecKeychain::EphemeralSecKeychain() const auto ok = CFStringGetFileSystemRepresentation(cfName, &posixPath[0], CFIndex(posixPath.size())); if (!ok) { - qCWarning(lcTlsBackend) << "Failed to create a unique keychain name from" - << "QDir::tempPath()"; + qCWarning(lcSecureTransport) << "Failed to create a unique keychain name from" + << "QDir::tempPath()"; return; } std::vector<uint8_t> passUtf8(256); if (SecRandomCopyBytes(kSecRandomDefault, passUtf8.size(), &passUtf8[0])) { - qCWarning(lcTlsBackend) << "SecRandomCopyBytes: failed to create a key"; + qCWarning(lcSecureTransport) << "SecRandomCopyBytes: failed to create a key"; return; } @@ -151,7 +117,7 @@ EphemeralSecKeychain::EphemeralSecKeychain() &passUtf8[0], FALSE, nullptr, &keychain); if (status != errSecSuccess || !keychain) { - qCWarning(lcTlsBackend) << "SecKeychainCreate: failed to create a custom keychain"; + qCWarning(lcSecureTransport) << "SecKeychainCreate: failed to create a custom keychain"; if (keychain) { SecKeychainDelete(keychain); CFRelease(keychain); @@ -166,13 +132,13 @@ EphemeralSecKeychain::EphemeralSecKeychain() // == false, set interval to INT_MAX to never lock ... settings.lockInterval = INT_MAX; if (SecKeychainSetSettings(keychain, &settings) != errSecSuccess) - qCWarning(lcTlsBackend) << "SecKeychainSettings: failed to disable lock on sleep"; + qCWarning(lcSecureTransport) << "SecKeychainSettings: failed to disable lock on sleep"; } #ifdef QSSLSOCKET_DEBUG if (keychain) { - qCDebug(lcTlsBackend) << "Custom keychain with name" << keychainName << "was created" - << "successfully"; + qCDebug(lcSecureTransport) << "Custom keychain with name" << keychainName << "was created" + << "successfully"; } #endif } @@ -204,7 +170,7 @@ SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode) // We never use kSSLDatagramType, so it's kSSLStreamType unconditionally. SSLContextRef context = SSLCreateContext(nullptr, side, kSSLStreamType); if (!context) - qCWarning(lcTlsBackend) << "SSLCreateContext failed"; + qCWarning(lcSecureTransport) << "SSLCreateContext failed"; return context; } @@ -280,14 +246,14 @@ OSStatus TlsCryptographSecureTransport::ReadCallback(TlsCryptographSecureTranspo const qint64 bytes = plainSocket->read(data, *dataLength); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "read" << bytes; + qCDebug(lcSecureTransport) << plainSocket << "read" << bytes; #endif if (bytes < 0) { *dataLength = 0; return errSecIO; } - const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess; + const OSStatus err = (size_t(bytes) < *dataLength) ? OSStatus(errSSLWouldBlock) : OSStatus(errSecSuccess); *dataLength = bytes; return err; @@ -306,14 +272,14 @@ OSStatus TlsCryptographSecureTransport::WriteCallback(TlsCryptographSecureTransp const qint64 bytes = plainSocket->write(data, *dataLength); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "write" << bytes; + qCDebug(lcSecureTransport) << plainSocket << "write" << bytes; #endif if (bytes < 0) { *dataLength = 0; return errSecIO; } - const OSStatus err = (size_t(bytes) < *dataLength) ? errSSLWouldBlock : errSecSuccess; + const OSStatus err = (size_t(bytes) < *dataLength) ? OSStatus(errSSLWouldBlock) : OSStatus(errSecSuccess); *dataLength = bytes; return err; @@ -346,45 +312,41 @@ void TlsCryptographSecureTransport::continueHandshake() Q_ASSERT(d); d->setEncrypted(true); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << d->plainTcpSocket() << "connection encrypted"; + qCDebug(lcSecureTransport) << d->plainTcpSocket() << "connection encrypted"; #endif -#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0) // Unlike OpenSSL, Secure Transport does not allow to negotiate protocols via // a callback during handshake. We can only set our list of preferred protocols // (and send it during handshake) and then receive what our peer has sent to us. // And here we can finally try to find a match (if any). const auto &configuration = q->sslConfiguration(); - if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) { - const auto &requestedProtocols = configuration.allowedNextProtocols(); - if (const int requestedCount = requestedProtocols.size()) { - QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone); - QTlsBackend::setNegotiatedProtocol(d, {}); - - QCFType<CFArrayRef> cfArray; - const OSStatus result = SSLCopyALPNProtocols(context, &cfArray); - if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) { - const int size = CFArrayGetCount(cfArray); - QList<QString> peerProtocols(size); - for (int i = 0; i < size; ++i) - peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i)); - - for (int i = 0; i < requestedCount; ++i) { - const auto requestedName = QString::fromLatin1(requestedProtocols[i]); - for (int j = 0; j < size; ++j) { - if (requestedName == peerProtocols[j]) { - QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1()); - QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated); - break; - } - } - if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated) + const auto &requestedProtocols = configuration.allowedNextProtocols(); + if (const int requestedCount = requestedProtocols.size()) { + QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNone); + QTlsBackend::setNegotiatedProtocol(d, {}); + + QCFType<CFArrayRef> cfArray; + const OSStatus result = SSLCopyALPNProtocols(context, &cfArray); + if (result == errSecSuccess && cfArray && CFArrayGetCount(cfArray)) { + const int size = CFArrayGetCount(cfArray); + QList<QString> peerProtocols(size); + for (int i = 0; i < size; ++i) + peerProtocols[i] = QString::fromCFString((CFStringRef)CFArrayGetValueAtIndex(cfArray, i)); + + for (int i = 0; i < requestedCount; ++i) { + const auto requestedName = QString::fromLatin1(requestedProtocols[i]); + for (int j = 0; j < size; ++j) { + if (requestedName == peerProtocols[j]) { + QTlsBackend::setNegotiatedProtocol(d, requestedName.toLatin1()); + QTlsBackend::setAlpnStatus(d, QSslConfiguration::NextProtocolNegotiationNegotiated); break; + } } + if (configuration.nextProtocolNegotiationStatus() == QSslConfiguration::NextProtocolNegotiationNegotiated) + break; } } } -#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE if (!renegotiating) emit q->encrypted(); @@ -398,6 +360,7 @@ void TlsCryptographSecureTransport::continueHandshake() void TlsCryptographSecureTransport::disconnected() { Q_ASSERT(d && d->plainTcpSocket()); + d->setEncrypted(false); if (d->plainTcpSocket()->bytesAvailable() <= 0) destroySslContext(); // If there is still buffered data in the plain socket, don't destroy the ssl context yet. @@ -410,6 +373,7 @@ void TlsCryptographSecureTransport::disconnectFromHost() if (context) { if (!shutdown) { SSLClose(context); + context.reset(nullptr); shutdown = true; } } @@ -433,15 +397,18 @@ QSsl::SslProtocol TlsCryptographSecureTransport::sessionProtocol() const SSLProtocol protocol = kSSLProtocolUnknown; const OSStatus err = SSLGetNegotiatedProtocolVersion(context, &protocol); if (err != errSecSuccess) { - qCWarning(lcTlsBackend) << "SSLGetNegotiatedProtocolVersion failed:" << err; + qCWarning(lcSecureTransport) << "SSLGetNegotiatedProtocolVersion failed:" << err; return QSsl::UnknownProtocol; } switch (protocol) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case kTLSProtocol1: return QSsl::TlsV1_0; case kTLSProtocol11: return QSsl::TlsV1_1; +QT_WARNING_POP case kTLSProtocol12: return QSsl::TlsV1_2; case kTLSProtocol13: @@ -499,7 +466,7 @@ void TlsCryptographSecureTransport::transmit() size_t writtenBytes = 0; const OSStatus err = SSLWrite(context, writeBuffer.readPointer(), nextDataBlockSize, &writtenBytes); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << d->plainTcpSocket() << "SSLWrite returned" << err; + qCDebug(lcSecureTransport) << d->plainTcpSocket() << "SSLWrite returned" << err; #endif if (err != errSecSuccess && err != errSSLWouldBlock) { setErrorAndEmit(d, QAbstractSocket::SslInternalError, @@ -537,7 +504,7 @@ void TlsCryptographSecureTransport::transmit() data.resize(4096); const OSStatus err = SSLRead(context, data.data(), data.size(), &readBytes); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << d->plainTcpSocket() << "SSLRead returned" << err; + qCDebug(lcSecureTransport) << d->plainTcpSocket() << "SSLRead returned" << err; #endif if (err == errSSLClosedGraceful) { shutdown = true; // the other side shut down, make sure we do not send shutdown ourselves @@ -571,80 +538,109 @@ void TlsCryptographSecureTransport::transmit() SSLCipherSuite TlsCryptographSecureTransport::SSLCipherSuite_from_QSslCipher(const QSslCipher &ciph) { - if (ciph.name() == QLatin1String("AES128-SHA")) + if (ciph.name() == "AES128-SHA"_L1) return TLS_RSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("DHE-RSA-AES128-SHA")) + if (ciph.name() == "DHE-RSA-AES128-SHA"_L1) return TLS_DHE_RSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("AES256-SHA")) + if (ciph.name() == "AES256-SHA"_L1) return TLS_RSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("DHE-RSA-AES256-SHA")) + if (ciph.name() == "DHE-RSA-AES256-SHA"_L1) return TLS_DHE_RSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-NULL-SHA")) + if (ciph.name() == "ECDH-ECDSA-NULL-SHA"_L1) return TLS_ECDH_ECDSA_WITH_NULL_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-RC4-SHA")) + if (ciph.name() == "ECDH-ECDSA-RC4-SHA"_L1) return TLS_ECDH_ECDSA_WITH_RC4_128_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-DES-CBC3-SHA")) + if (ciph.name() == "ECDH-ECDSA-DES-CBC3-SHA"_L1) return TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES128-SHA")) + if (ciph.name() == "ECDH-ECDSA-AES128-SHA"_L1) return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES256-SHA")) + if (ciph.name() == "ECDH-ECDSA-AES256-SHA"_L1) return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-RC4-SHA")) + if (ciph.name() == "ECDH-ECDSA-RC4-SHA"_L1) return TLS_ECDHE_ECDSA_WITH_RC4_128_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-DES-CBC3-SHA")) + if (ciph.name() == "ECDH-ECDSA-DES-CBC3-SHA"_L1) return TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES128-SHA")) + if (ciph.name() == "ECDH-ECDSA-AES128-SHA"_L1) return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES256-SHA")) + if (ciph.name() == "ECDH-ECDSA-AES256-SHA"_L1) return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-NULL-SHA")) + if (ciph.name() == "ECDH-RSA-NULL-SHA"_L1) return TLS_ECDH_RSA_WITH_NULL_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-RC4-SHA")) + if (ciph.name() == "ECDH-RSA-RC4-SHA"_L1) return TLS_ECDH_RSA_WITH_RC4_128_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-DES-CBC3-SHA")) + if (ciph.name() == "ECDH-RSA-DES-CBC3-SHA"_L1) return TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-AES128-SHA")) + if (ciph.name() == "ECDH-RSA-AES128-SHA"_L1) return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-AES256-SHA")) + if (ciph.name() == "ECDH-RSA-AES256-SHA"_L1) return TLS_ECDH_RSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-RC4-SHA")) + if (ciph.name() == "ECDH-RSA-RC4-SHA"_L1) return TLS_ECDHE_RSA_WITH_RC4_128_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-DES-CBC3-SHA")) + if (ciph.name() == "ECDH-RSA-DES-CBC3-SHA"_L1) return TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-AES128-SHA")) + if (ciph.name() == "ECDH-RSA-AES128-SHA"_L1) return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA; - if (ciph.name() == QLatin1String("ECDH-RSA-AES256-SHA")) + if (ciph.name() == "ECDH-RSA-AES256-SHA"_L1) return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA; - if (ciph.name() == QLatin1String("DES-CBC3-SHA")) + if (ciph.name() == "DES-CBC3-SHA"_L1) return TLS_RSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("AES128-SHA256")) + if (ciph.name() == "AES128-SHA256"_L1) return TLS_RSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("AES256-SHA256")) + if (ciph.name() == "AES256-SHA256"_L1) return TLS_RSA_WITH_AES_256_CBC_SHA256; - if (ciph.name() == QLatin1String("DHE-RSA-DES-CBC3-SHA")) + if (ciph.name() == "DHE-RSA-DES-CBC3-SHA"_L1) return TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA; - if (ciph.name() == QLatin1String("DHE-RSA-AES128-SHA256")) + if (ciph.name() == "DHE-RSA-AES128-SHA256"_L1) return TLS_DHE_RSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("DHE-RSA-AES256-SHA256")) + if (ciph.name() == "DHE-RSA-AES256-SHA256"_L1) return TLS_DHE_RSA_WITH_AES_256_CBC_SHA256; - if (ciph.name() == QLatin1String("AES256-GCM-SHA384")) + if (ciph.name() == "AES256-GCM-SHA384"_L1) return TLS_RSA_WITH_AES_256_GCM_SHA384; - if (ciph.name() == QLatin1String("ECDHE-ECDSA-AES128-SHA256")) + if (ciph.name() == "ECDHE-ECDSA-AES128-SHA256"_L1) return TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("ECDHE-ECDSA-AES256-SHA384")) + if (ciph.name() == "ECDHE-ECDSA-AES256-SHA384"_L1) return TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES128-SHA256")) + if (ciph.name() == "ECDH-ECDSA-AES128-SHA256"_L1) return TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("ECDH-ECDSA-AES256-SHA384")) + if (ciph.name() == "ECDH-ECDSA-AES256-SHA384"_L1) return TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384; - if (ciph.name() == QLatin1String("ECDHE-RSA-AES128-SHA256")) + if (ciph.name() == "ECDHE-RSA-AES128-SHA256"_L1) return TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("ECDHE-RSA-AES256-SHA384")) + if (ciph.name() == "ECDHE-RSA-AES256-SHA384"_L1) return TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384; - if (ciph.name() == QLatin1String("ECDHE-RSA-AES256-SHA384")) + if (ciph.name() == "ECDHE-RSA-AES256-SHA384"_L1) return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256; - if (ciph.name() == QLatin1String("ECDHE-RSA-AES256-GCM-SHA384")) + if (ciph.name() == "ECDHE-RSA-AES256-GCM-SHA384"_L1) return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384; + if (ciph.name() == "AES128-GCM-SHA256"_L1) + return TLS_AES_128_GCM_SHA256; + if (ciph.name() == "AES256-GCM-SHA384"_L1) + return TLS_AES_256_GCM_SHA384; + if (ciph.name() == "CHACHA20-POLY1305-SHA256"_L1) + return TLS_CHACHA20_POLY1305_SHA256; + if (ciph.name() == "AES128-CCM-SHA256"_L1) + return TLS_AES_128_CCM_SHA256; + if (ciph.name() == "AES128-CCM8-SHA256"_L1) + return TLS_AES_128_CCM_8_SHA256; + if (ciph.name() == "ECDHE-ECDSA-AES128-GCM-SHA256"_L1) + return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; + if (ciph.name() == "ECDHE-ECDSA-AES256-GCM-SHA384"_L1) + return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384; + if (ciph.name() == "ECDH-ECDSA-AES128-GCM-SHA256"_L1) + return TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256; + if (ciph.name() == "ECDH-ECDSA-AES256-GCM-SHA384"_L1) + return TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384; + if (ciph.name() == "ECDHE-RSA-AES128-GCM-SHA256"_L1) + return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; + if (ciph.name() == "ECDH-RSA-AES128-GCM-SHA256"_L1) + return TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256; + if (ciph.name() == "ECDH-RSA-AES256-GCM-SHA384"_L1) + return TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384; + if (ciph.name() == "ECDHE-RSA-CHACHA20-POLY1305-SHA256"_L1) + return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256; + if (ciph.name() == "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256"_L1) + return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256; + return 0; } @@ -695,35 +691,31 @@ bool TlsCryptographSecureTransport::initSslContext() return false; } -#if QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13_4, __IPHONE_11_0, __TVOS_11_0, __WATCHOS_4_0) - if (__builtin_available(macOS 10.13, iOS 11.0, tvOS 11.0, watchOS 4.0, *)) { - const auto protocolNames = configuration.allowedNextProtocols(); - QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks)); - if (cfNames) { - for (const QByteArray &name : protocolNames) { - if (name.size() > 255) { - qCWarning(lcTlsBackend) << "TLS ALPN extension" << name - << "is too long and will be ignored."; - continue; - } else if (name.isEmpty()) { - continue; - } - QCFString cfName(QString::fromLatin1(name).toCFString()); - CFArrayAppendValue(cfNames, cfName); + const auto protocolNames = configuration.allowedNextProtocols(); + QCFType<CFMutableArrayRef> cfNames(CFArrayCreateMutable(nullptr, 0, &kCFTypeArrayCallBacks)); + if (cfNames) { + for (const QByteArray &name : protocolNames) { + if (name.size() > 255) { + qCWarning(lcSecureTransport) << "TLS ALPN extension" << name + << "is too long and will be ignored."; + continue; + } else if (name.isEmpty()) { + continue; } + QCFString cfName(QString::fromLatin1(name).toCFString()); + CFArrayAppendValue(cfNames, cfName); + } - if (CFArrayGetCount(cfNames)) { - // Up to the application layer to check that negotiation - // failed, and handle this non-TLS error, we do not handle - // the result of this call as an error: - if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess) - qCWarning(lcTlsBackend) << "SSLSetALPNProtocols failed - too long protocol names?"; - } - } else { - qCWarning(lcTlsBackend) << "failed to allocate ALPN names array"; + if (CFArrayGetCount(cfNames)) { + // Up to the application layer to check that negotiation + // failed, and handle this non-TLS error, we do not handle + // the result of this call as an error: + if (SSLSetALPNProtocols(context, cfNames) != errSecSuccess) + qCWarning(lcSecureTransport) << "SSLSetALPNProtocols failed - too long protocol names?"; } + } else { + qCWarning(lcSecureTransport) << "failed to allocate ALPN names array"; } -#endif // QT_DARWIN_PLATFORM_SDK_EQUAL_OR_ABOVE if (mode == QSslSocket::SslClientMode) { // enable Server Name Indication (SNI) @@ -775,12 +767,12 @@ bool TlsCryptographSecureTransport::initSslContext() cfCiphers << sslCipher; } if (cfCiphers.size() == 0) { - qCWarning(lcTlsBackend) << "failed to add any of the requested ciphers from the configuration"; + qCWarning(lcSecureTransport) << "failed to add any of the requested ciphers from the configuration"; return false; } OSStatus err = SSLSetEnabledCiphers(context, cfCiphers.data(), cfCiphers.size()); if (err != errSecSuccess) { - qCWarning(lcTlsBackend) << "failed to set the ciphers from the configuration"; + qCWarning(lcSecureTransport) << "failed to set the ciphers from the configuration"; return false; } } @@ -842,8 +834,8 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript OSStatus err = SecPKCS12Import(pkcs12, options, &items); if (err != errSecSuccess) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend) << plainSocket - << QStringLiteral("SecPKCS12Import failed: %1").arg(err); + qCWarning(lcSecureTransport) << plainSocket + << QStringLiteral("SecPKCS12Import failed: %1").arg(err); #endif errorCode = QAbstractSocket::SslInvalidUserDataError; errorDescription = QStringLiteral("SecPKCS12Import failed: %1").arg(err); @@ -852,7 +844,7 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript if (!CFArrayGetCount(items)) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend) << plainSocket << "SecPKCS12Import returned no items"; + qCWarning(lcSecureTransport) << plainSocket << "SecPKCS12Import returned no items"; #endif errorCode = QAbstractSocket::SslInvalidUserDataError; errorDescription = QStringLiteral("SecPKCS12Import returned no items"); @@ -863,7 +855,7 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(import, kSecImportItemIdentity); if (!identity) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend) << plainSocket << "SecPKCS12Import returned no identity"; + qCWarning(lcSecureTransport) << plainSocket << "SecPKCS12Import returned no identity"; #endif errorCode = QAbstractSocket::SslInvalidUserDataError; errorDescription = QStringLiteral("SecPKCS12Import returned no identity"); @@ -888,8 +880,8 @@ bool TlsCryptographSecureTransport::setSessionCertificate(QString &errorDescript err = SSLSetCertificate(context, certs); if (err != errSecSuccess) { #ifdef QSSLSOCKET_DEBUG - qCWarning(lcTlsBackend) - << plainSocket << QStringLiteral("Cannot set certificate and key: %1").arg(err); + qCWarning(lcSecureTransport) << plainSocket + << QStringLiteral("Cannot set certificate and key: %1").arg(err); #endif errorCode = QAbstractSocket::SslInvalidUserDataError; errorDescription = QStringLiteral("Cannot set certificate and key: %1").arg(err); @@ -914,62 +906,68 @@ bool TlsCryptographSecureTransport::setSessionProtocol() switch (configuration.protocol()) { case QSsl::TlsV1_3: case QSsl::TlsV1_3OrLater: - qCWarning(lcTlsBackend) << plainSocket << "SecureTransport does not support TLS 1.3"; + qCWarning(lcSecureTransport) << plainSocket << "SecureTransport does not support TLS 1.3"; return false; default:; } OSStatus err = errSecSuccess; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED if (configuration.protocol() == QSsl::TlsV1_0) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.0"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.0"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); if (err == errSecSuccess) err = SSLSetProtocolVersionMax(context, kTLSProtocol1); } else if (configuration.protocol() == QSsl::TlsV1_1) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.1"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.1"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol11); if (err == errSecSuccess) err = SSLSetProtocolVersionMax(context, kTLSProtocol11); +QT_WARNING_POP } else if (configuration.protocol() == QSsl::TlsV1_2) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.2"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol12); if (err == errSecSuccess) err = SSLSetProtocolVersionMax(context, kTLSProtocol12); } else if (configuration.protocol() == QSsl::AnyProtocol) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : any"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : any"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); } else if (configuration.protocol() == QSsl::SecureProtocols) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.2"; #endif - err = SSLSetProtocolVersionMin(context, kTLSProtocol1); + err = SSLSetProtocolVersionMin(context, kTLSProtocol12); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED } else if (configuration.protocol() == QSsl::TlsV1_0OrLater) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1 - TLSv1.2"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1 - TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol1); } else if (configuration.protocol() == QSsl::TlsV1_1OrLater) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.1 - TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol11); +QT_WARNING_POP } else if (configuration.protocol() == QSsl::TlsV1_2OrLater) { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "requesting : TLSv1.2"; + qCDebug(lcSecureTransport) << plainSocket << "requesting : TLSv1.2"; #endif err = SSLSetProtocolVersionMin(context, kTLSProtocol12); } else { #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "no protocol version found in the configuration"; + qCDebug(lcSecureTransport) << plainSocket << "no protocol version found in the configuration"; #endif return false; } @@ -998,11 +996,14 @@ bool TlsCryptographSecureTransport::verifySessionProtocol() const if (configuration.protocol() == QSsl::AnyProtocol) protocolOk = true; else if (configuration.protocol() == QSsl::SecureProtocols) - protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); + protocolOk = (sessionProtocol() >= QSsl::TlsV1_2); +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED else if (configuration.protocol() == QSsl::TlsV1_0OrLater) protocolOk = (sessionProtocol() >= QSsl::TlsV1_0); else if (configuration.protocol() == QSsl::TlsV1_1OrLater) protocolOk = (sessionProtocol() >= QSsl::TlsV1_1); +QT_WARNING_POP else if (configuration.protocol() == QSsl::TlsV1_2OrLater) protocolOk = (sessionProtocol() >= QSsl::TlsV1_2); else if (configuration.protocol() == QSsl::TlsV1_3OrLater) @@ -1075,7 +1076,7 @@ bool TlsCryptographSecureTransport::verifyPeerTrust() QTlsBackend::storePeerCertificate(d, peerCertificateChain.at(0)); // Check the whole chain for blacklisting (including root, as we check for subjectInfo and issuer): - for (const QSslCertificate &cert : qAsConst(peerCertificateChain)) { + for (const QSslCertificate &cert : std::as_const(peerCertificateChain)) { if (QSslCertificatePrivate::isBlacklisted(cert) && !canIgnoreVerify) { const QSslError error(QSslError::CertificateBlacklisted, cert); errors << error; @@ -1126,8 +1127,6 @@ bool TlsCryptographSecureTransport::verifyPeerTrust() QCFType<CFDataRef> certData = cert.toDer().toCFData(); if (QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(nullptr, certData)) CFArrayAppendValue(certArray, secRef); - else - qCWarning(lcTlsBackend, "Failed to create SecCertificate from QSslCertificate"); } SecTrustSetAnchorCertificates(trust, certArray); @@ -1236,7 +1235,7 @@ bool TlsCryptographSecureTransport::startHandshake() OSStatus err = SSLHandshake(context); #ifdef QSSLSOCKET_DEBUG - qCDebug(lcTlsBackend) << plainSocket << "SSLHandhake returned" << err; + qCDebug(lcSecureTransport) << plainSocket << "SSLHandhake returned" << err; #endif if (err == errSSLWouldBlock) { @@ -1282,7 +1281,7 @@ bool TlsCryptographSecureTransport::startHandshake() // Connection aborted during handshake phase. if (q->state() != QAbstractSocket::ConnectedState) { - qCDebug(lcTlsBackend) << "connection aborted"; + qCDebug(lcSecureTransport) << "connection aborted"; renegotiating = false; return false; } diff --git a/src/plugins/tls/securetransport/qtls_st_p.h b/src/plugins/tls/securetransport/qtls_st_p.h index 3dad24f348..2903ef4815 100644 --- a/src/plugins/tls/securetransport/qtls_st_p.h +++ b/src/plugins/tls/securetransport/qtls_st_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLS_ST_P_H #define QTLS_ST_P_H @@ -63,6 +27,11 @@ #include <QtNetwork/qabstractsocket.h> #include <QtNetwork/private/qsslsocket_p.h> +#warning SecureTransport was deprecated in macOS 10.15 and iOS 13, \ +and is no longer supported. We should be using Network.framework instead. \ +See QTBUG-85231 for more information. +QT_WARNING_DISABLE_DEPRECATED + #include <Security/Security.h> #include <Security/SecureTransport.h> diff --git a/src/plugins/tls/securetransport/qtlsbackend_st.cpp b/src/plugins/tls/securetransport/qtlsbackend_st.cpp index 7fc7692350..54e45d1720 100644 --- a/src/plugins/tls/securetransport/qtlsbackend_st.cpp +++ b/src/plugins/tls/securetransport/qtlsbackend_st.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlsbackend_st_p.h" #include "qtlskey_st_p.h" @@ -47,9 +11,11 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + Q_GLOBAL_STATIC(QRecursiveMutex, qt_securetransport_mutex) -Q_LOGGING_CATEGORY(lcTlsBackend, "qt.tlsbackend.securetransport"); +Q_LOGGING_CATEGORY(lcSecureTransport, "qt.tlsbackend.securetransport"); namespace QTlsPrivate { @@ -64,98 +30,98 @@ QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher) // Sorted as in CipherSuite.h (and groupped by their RFC) // TLS addenda using AES, per RFC 3268 case TLS_RSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("AES128-SHA"); + name = "AES128-SHA"_L1; break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("DHE-RSA-AES128-SHA"); + name = "DHE-RSA-AES128-SHA"_L1; break; case TLS_RSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("AES256-SHA"); + name = "AES256-SHA"_L1; break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("DHE-RSA-AES256-SHA"); + name = "DHE-RSA-AES256-SHA"_L1; break; // ECDSA addenda, RFC 4492 case TLS_ECDH_ECDSA_WITH_NULL_SHA: - name = QLatin1String("ECDH-ECDSA-NULL-SHA"); + name = "ECDH-ECDSA-NULL-SHA"_L1; break; case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: - name = QLatin1String("ECDH-ECDSA-RC4-SHA"); + name = "ECDH-ECDSA-RC4-SHA"_L1; break; case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("ECDH-ECDSA-DES-CBC3-SHA"); + name = "ECDH-ECDSA-DES-CBC3-SHA"_L1; break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("ECDH-ECDSA-AES128-SHA"); + name = "ECDH-ECDSA-AES128-SHA"_L1; break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("ECDH-ECDSA-AES256-SHA"); + name = "ECDH-ECDSA-AES256-SHA"_L1; break; case TLS_ECDHE_ECDSA_WITH_NULL_SHA: - name = QLatin1String("ECDHE-ECDSA-NULL-SHA"); + name = "ECDHE-ECDSA-NULL-SHA"_L1; break; case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: - name = QLatin1String("ECDHE-ECDSA-RC4-SHA"); + name = "ECDHE-ECDSA-RC4-SHA"_L1; break; case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("ECDHE-ECDSA-DES-CBC3-SHA"); + name = "ECDHE-ECDSA-DES-CBC3-SHA"_L1; break; case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("ECDHE-ECDSA-AES128-SHA"); + name = "ECDHE-ECDSA-AES128-SHA"_L1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("ECDHE-ECDSA-AES256-SHA"); + name = "ECDHE-ECDSA-AES256-SHA"_L1; break; case TLS_ECDH_RSA_WITH_NULL_SHA: - name = QLatin1String("ECDH-RSA-NULL-SHA"); + name = "ECDH-RSA-NULL-SHA"_L1; break; case TLS_ECDH_RSA_WITH_RC4_128_SHA: - name = QLatin1String("ECDH-RSA-RC4-SHA"); + name = "ECDH-RSA-RC4-SHA"_L1; break; case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("ECDH-RSA-DES-CBC3-SHA"); + name = "ECDH-RSA-DES-CBC3-SHA"_L1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("ECDH-RSA-AES128-SHA"); + name = "ECDH-RSA-AES128-SHA"_L1; break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("ECDH-RSA-AES256-SHA"); + name = "ECDH-RSA-AES256-SHA"_L1; break; case TLS_ECDHE_RSA_WITH_NULL_SHA: - name = QLatin1String("ECDHE-RSA-NULL-SHA"); + name = "ECDHE-RSA-NULL-SHA"_L1; break; case TLS_ECDHE_RSA_WITH_RC4_128_SHA: - name = QLatin1String("ECDHE-RSA-RC4-SHA"); + name = "ECDHE-RSA-RC4-SHA"_L1; break; case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("ECDHE-RSA-DES-CBC3-SHA"); + name = "ECDHE-RSA-DES-CBC3-SHA"_L1; break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: - name = QLatin1String("ECDHE-RSA-AES128-SHA"); + name = "ECDHE-RSA-AES128-SHA"_L1; break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: - name = QLatin1String("ECDHE-RSA-AES256-SHA"); + name = "ECDHE-RSA-AES256-SHA"_L1; break; // TLS 1.2 addenda, RFC 5246 case TLS_RSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("DES-CBC3-SHA"); + name = "DES-CBC3-SHA"_L1; break; case TLS_RSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("AES128-SHA256"); + name = "AES128-SHA256"_L1; break; case TLS_RSA_WITH_AES_256_CBC_SHA256: - name = QLatin1String("AES256-SHA256"); + name = "AES256-SHA256"_L1; break; case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: - name = QLatin1String("DHE-RSA-DES-CBC3-SHA"); + name = "DHE-RSA-DES-CBC3-SHA"_L1; break; case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("DHE-RSA-AES128-SHA256"); + name = "DHE-RSA-AES128-SHA256"_L1; break; case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: - name = QLatin1String("DHE-RSA-AES256-SHA256"); + name = "DHE-RSA-AES256-SHA256"_L1; break; // Addendum from RFC 4279, TLS PSK @@ -166,7 +132,7 @@ QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher) // Addenda from rfc 5288 AES Galois Counter Mode (CGM) Cipher Suites for TLS case TLS_RSA_WITH_AES_256_GCM_SHA384: - name = QLatin1String("AES256-GCM-SHA384"); + name = "AES256-GCM-SHA384"_L1; break; // RFC 5487 - PSK with SHA-256/384 and AES GCM @@ -174,41 +140,90 @@ QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher) // Addenda from rfc 5289 Elliptic Curve Cipher Suites with HMAC SHA-256/384 case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("ECDHE-ECDSA-AES128-SHA256"); + name = "ECDHE-ECDSA-AES128-SHA256"_L1; break; case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: - name = QLatin1String("ECDHE-ECDSA-AES256-SHA384"); + name = "ECDHE-ECDSA-AES256-SHA384"_L1; break; case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("ECDH-ECDSA-AES128-SHA256"); + name = "ECDH-ECDSA-AES128-SHA256"_L1; break; case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: - name = QLatin1String("ECDH-ECDSA-AES256-SHA384"); + name = "ECDH-ECDSA-AES256-SHA384"_L1; break; case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("ECDHE-RSA-AES128-SHA256"); + name = "ECDHE-RSA-AES128-SHA256"_L1; break; case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: - name = QLatin1String("ECDHE-RSA-AES256-SHA384"); + name = "ECDHE-RSA-AES256-SHA384"_L1; break; case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: - name = QLatin1String("ECDH-RSA-AES128-SHA256"); + name = "ECDH-RSA-AES128-SHA256"_L1; break; case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384: - name = QLatin1String("ECDH-RSA-AES256-SHA384"); + name = "ECDH-RSA-AES256-SHA384"_L1; break; // Addenda from rfc 5289 Elliptic Curve Cipher Suites // with SHA-256/384 and AES Galois Counter Mode (GCM) case TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384: - name = QLatin1String("ECDHE-RSA-AES256-GCM-SHA384"); + name = "ECDHE-RSA-AES256-GCM-SHA384"_L1; break; + // TLS 1.3 standard cipher suites for ChaCha20+Poly1305. + // Note: TLS 1.3 ciphersuites do not specify the key exchange + // algorithm -- they only specify the symmetric ciphers. + case TLS_AES_128_GCM_SHA256: + name = "AES128-GCM-SHA256"_L1; + break; + case TLS_AES_256_GCM_SHA384: + name = "AES256-GCM-SHA384"_L1; + break; + case TLS_CHACHA20_POLY1305_SHA256: + name = "CHACHA20-POLY1305-SHA256"_L1; + break; + case TLS_AES_128_CCM_SHA256: + name = "AES128-CCM-SHA256"_L1; + break; + case TLS_AES_128_CCM_8_SHA256: + name = "AES128-CCM8-SHA256"_L1; + break; + // Addenda from rfc 5289 Elliptic Curve Cipher Suites with + // SHA-256/384 and AES Galois Counter Mode (GCM). + case TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256: + name = "ECDHE-ECDSA-AES128-GCM-SHA256"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384: + name = "ECDHE-ECDSA-AES256-GCM-SHA384"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256: + name = "ECDH-ECDSA-AES128-GCM-SHA256"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384: + name = "ECDH-ECDSA-AES256-GCM-SHA384"_L1; + break; + case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256: + name = "ECDHE-RSA-AES128-GCM-SHA256"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256: + name = "ECDH-RSA-AES128-GCM-SHA256"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384: + name = "ECDH-RSA-AES256-GCM-SHA384"_L1; + break; + // Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for + // Transport Layer Security (TLS). + case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256: + name = "ECDHE-RSA-CHACHA20-POLY1305-SHA256"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256: + name = "ECDHE-ECDSA-CHACHA20-POLY1305-SHA256"_L1; + break; default: return {}; } - return QTlsBackend::createCiphersuite(name, QSsl::TlsV1_2, QLatin1String("TLSv1.2")); + return QTlsBackend::createCiphersuite(name, QSsl::TlsV1_2, "TLSv1.2"_L1); } } // namespace QTlsPrivate @@ -217,7 +232,7 @@ bool QSecureTransportBackend::s_loadedCiphersAndCerts = false; QString QSecureTransportBackend::tlsLibraryVersionString() const { - return QLatin1String("Secure Transport, ") + QSysInfo::prettyProductName(); + return "Secure Transport, "_L1 + QSysInfo::prettyProductName(); } QString QSecureTransportBackend::tlsLibraryBuildVersionString() const @@ -294,10 +309,13 @@ QList<QSsl::SslProtocol> QSecureTransportBackend::supportedProtocols() const protocols << QSsl::AnyProtocol; protocols << QSsl::SecureProtocols; +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED protocols << QSsl::TlsV1_0; protocols << QSsl::TlsV1_0OrLater; protocols << QSsl::TlsV1_1; protocols << QSsl::TlsV1_1OrLater; +QT_WARNING_POP protocols << QSsl::TlsV1_2; protocols << QSsl::TlsV1_2OrLater; @@ -339,3 +357,5 @@ QTlsPrivate::TlsCryptograph *QSecureTransportBackend::createTlsCryptograph() con QT_END_NAMESPACE + +#include "moc_qtlsbackend_st_p.cpp" diff --git a/src/plugins/tls/securetransport/qtlsbackend_st_p.h b/src/plugins/tls/securetransport/qtlsbackend_st_p.h index ebce859db3..968a080cd4 100644 --- a/src/plugins/tls/securetransport/qtlsbackend_st_p.h +++ b/src/plugins/tls/securetransport/qtlsbackend_st_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSBACKEND_ST_P_H #define QTLSBACKEND_ST_P_H @@ -91,6 +55,8 @@ private: static bool s_loadedCiphersAndCerts; }; +Q_DECLARE_LOGGING_CATEGORY(lcSecureTransport) + QT_END_NAMESPACE #endif // QTLSBACKEND_ST_P_H diff --git a/src/plugins/tls/securetransport/qtlskey_st.cpp b/src/plugins/tls/securetransport/qtlskey_st.cpp index 85f86c7bf8..db4187ee03 100644 --- a/src/plugins/tls/securetransport/qtlskey_st.cpp +++ b/src/plugins/tls/securetransport/qtlskey_st.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlskey_st_p.h" diff --git a/src/plugins/tls/securetransport/qtlskey_st_p.h b/src/plugins/tls/securetransport/qtlskey_st_p.h index c9dcc4e3ec..62e1173941 100644 --- a/src/plugins/tls/securetransport/qtlskey_st_p.h +++ b/src/plugins/tls/securetransport/qtlskey_st_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_ST_P_H #define QTLSKEY_ST_P_H diff --git a/src/plugins/tls/securetransport/qx509_st.cpp b/src/plugins/tls/securetransport/qx509_st.cpp index 737b15cef8..3f797a6891 100644 --- a/src/plugins/tls/securetransport/qx509_st.cpp +++ b/src/plugins/tls/securetransport/qx509_st.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlskey_st_p.h" #include "qx509_st_p.h" diff --git a/src/plugins/tls/securetransport/qx509_st_p.h b/src/plugins/tls/securetransport/qx509_st_p.h index 5e5b42e791..bda89231ed 100644 --- a/src/plugins/tls/securetransport/qx509_st_p.h +++ b/src/plugins/tls/securetransport/qx509_st_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509_ST_P_H #define QX509_ST_P_H diff --git a/src/plugins/tls/shared/qasn1element.cpp b/src/plugins/tls/shared/qasn1element.cpp index 3df76c3774..97be46866d 100644 --- a/src/plugins/tls/shared/qasn1element.cpp +++ b/src/plugins/tls/shared/qasn1element.cpp @@ -1,54 +1,22 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qasn1element_p.h" #include <QtCore/qdatastream.h> #include <QtCore/qdatetime.h> +#include <QtCore/qtimezone.h> #include <QtCore/qlist.h> #include <QDebug> +#include <private/qtools_p.h> #include <limits> QT_BEGIN_NAMESPACE +using namespace QtMiscUtils; + typedef QMap<QByteArray, QByteArray> OidNameMap; static OidNameMap createOidMap() { @@ -249,11 +217,6 @@ QDateTime QAsn1Element::toDateTime() const // QDateTime::fromString is lenient and accepts +- signs in front // of the year; but ASN.1 doesn't allow them. - const auto isAsciiDigit = [](char c) - { - return c >= '0' && c <= '9'; - }; - if (!isAsciiDigit(mValue[0])) return result; @@ -261,39 +224,29 @@ QDateTime QAsn1Element::toDateTime() const if (mValue.back() != 'Z') return result; - // In addition, check that we only have digits representing the - // date/time. This should not really be necessary (there's no such - // thing as negative months/days/etc.); it's a workaround for - // QTBUG-84349. - if (!std::all_of(mValue.begin(), mValue.end() - 1, isAsciiDigit)) - return result; - if (mType == UtcTimeType && mValue.size() == 13) { - result = QDateTime::fromString(QString::fromLatin1(mValue), - QStringLiteral("yyMMddHHmmsst")); - if (!result.isValid()) - return result; - - Q_ASSERT(result.timeSpec() == Qt::UTC); - - QDate date = result.date(); - // RFC 2459: // Where YY is greater than or equal to 50, the year shall be // interpreted as 19YY; and // // Where YY is less than 50, the year shall be interpreted as 20YY. // - // QDateTime interprets the 'yy' format as 19yy, so we may need to adjust - // the year (bring it in the [1950, 2049] range). - if (date.year() < 1950) - result.setDate(date.addYears(100)); + // so use 1950 as base year. + constexpr int rfc2459CenturyStart = 1950; + const QLatin1StringView inputView(mValue); + QDate date = QDate::fromString(inputView.first(6), u"yyMMdd", rfc2459CenturyStart); + if (!date.isValid()) + return result; - Q_ASSERT(result.date().year() >= 1950); - Q_ASSERT(result.date().year() <= 2049); + Q_ASSERT(date.year() >= rfc2459CenturyStart); + Q_ASSERT(date.year() < 100 + rfc2459CenturyStart); + + QTime time = QTime::fromString(inputView.sliced(6, 6), u"HHmmss"); + if (!time.isValid()) + return result; + result = QDateTime(date, time, QTimeZone::UTC); } else if (mType == GeneralizedTimeType && mValue.size() == 15) { - result = QDateTime::fromString(QString::fromLatin1(mValue), - QStringLiteral("yyyyMMddHHmmsst")); + result = QDateTime::fromString(QString::fromLatin1(mValue), u"yyyyMMddHHmmsst"); } return result; diff --git a/src/plugins/tls/shared/qasn1element_p.h b/src/plugins/tls/shared/qasn1element_p.h index ac74937802..0de46be009 100644 --- a/src/plugins/tls/shared/qasn1element_p.h +++ b/src/plugins/tls/shared/qasn1element_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QASN1ELEMENT_P_H diff --git a/src/plugins/tls/shared/qdtls_base.cpp b/src/plugins/tls/shared/qdtls_base.cpp index 6a5979eb9e..19131e5497 100644 --- a/src/plugins/tls/shared/qdtls_base.cpp +++ b/src/plugins/tls/shared/qdtls_base.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qdtls_base_p.h" @@ -99,8 +63,11 @@ QDtlsBasePrivate::cookieGeneratorParameters() const bool QDtlsBasePrivate::isDtlsProtocol(QSsl::SslProtocol protocol) { switch (protocol) { +QT_WARNING_PUSH +QT_WARNING_DISABLE_DEPRECATED case QSsl::DtlsV1_0: case QSsl::DtlsV1_0OrLater: +QT_WARNING_POP case QSsl::DtlsV1_2: case QSsl::DtlsV1_2OrLater: return true; diff --git a/src/plugins/tls/shared/qdtls_base_p.h b/src/plugins/tls/shared/qdtls_base_p.h index ca3db50c84..a8faad6a26 100644 --- a/src/plugins/tls/shared/qdtls_base_p.h +++ b/src/plugins/tls/shared/qdtls_base_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QDTLS_BASE_P_H #define QDTLS_BASE_P_H diff --git a/src/plugins/tls/shared/qsslsocket_mac_shared.cpp b/src/plugins/tls/shared/qsslsocket_mac_shared.cpp index b808c9e83b..1257240ee2 100644 --- a/src/plugins/tls/shared/qsslsocket_mac_shared.cpp +++ b/src/plugins/tls/shared/qsslsocket_mac_shared.cpp @@ -1,47 +1,12 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2015 ownCloud Inc -** 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$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// Copyright (C) 2015 ownCloud Inc +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtNetwork/private/qtlsbackend_p.h> #include <QtNetwork/qsslcertificate.h> +#include <QtCore/qloggingcategory.h> #include <QtCore/qglobal.h> #include <QtCore/qdebug.h> @@ -57,7 +22,7 @@ QT_BEGIN_NAMESPACE -Q_DECLARE_LOGGING_CATEGORY(lcTlsBackend) +Q_LOGGING_CATEGORY(lcX509, "qt.mac.shared.x509"); #ifdef Q_OS_MACOS namespace { @@ -107,12 +72,57 @@ bool isCaCertificateTrusted(SecCertificateRef cfCert, int domain) } } } - } else { - qCWarning(lcTlsBackend, "Error receiving trust for a CA certificate"); } + return false; } +bool canDERBeParsed(CFDataRef derData, const QSslCertificate &qtCert) +{ + // We are observing certificates, that while accepted when we copy them + // from the keychain(s), later give us 'Failed to create SslCertificate + // from QSslCertificate'. It's interesting to know at what step the failure + // occurred. Let's check it and skip it below if it's not valid. + + auto checkDer = [](CFDataRef derData, const char *source) + { + Q_ASSERT(source); + Q_ASSERT(derData); + + const auto cfLength = CFDataGetLength(derData); + if (cfLength <= 0) { + qCWarning(lcX509) << source << "returned faulty DER data with invalid length."; + return false; + } + + QCFType<SecCertificateRef> secRef = SecCertificateCreateWithData(nullptr, derData); + if (!secRef) { + qCWarning(lcX509) << source << "returned faulty DER data which cannot be parsed back."; + return false; + } + return true; + }; + + if (!checkDer(derData, "SecCertificateCopyData")) { + qCDebug(lcX509) << "Faulty QSslCertificate is:" << qtCert;// Just in case we managed to parse something. + return false; + } + + // Generic parser failed? + if (qtCert.isNull()) { + qCWarning(lcX509, "QSslCertificate failed to parse DER"); + return false; + } + + const QCFType<CFDataRef> qtDerData = qtCert.toDer().toCFData(); + if (!checkDer(qtDerData, "QSslCertificate")) { + qCWarning(lcX509) << "Faulty QSslCertificate is:" << qtCert; + return false; + } + + return true; +} + } // unnamed namespace #endif // Q_OS_MACOS @@ -133,10 +143,18 @@ QList<QSslCertificate> systemCaCertificates() SecCertificateRef cfCert = (SecCertificateRef)CFArrayGetValueAtIndex(cfCerts, i); QCFType<CFDataRef> derData = SecCertificateCopyData(cfCert); if (isCaCertificateTrusted(cfCert, dom)) { - if (derData == nullptr) { - qCWarning(lcTlsBackend, "Error retrieving a CA certificate from the system store"); + if (derData) { + const auto newCert = QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der); + if (!canDERBeParsed(derData, newCert)) { + // Last attempt to get some information about the certificate: + CFShow(cfCert); + continue; + } + systemCerts << newCert; } else { - systemCerts << QSslCertificate(QByteArray::fromCFData(derData), QSsl::Der); + // "Returns NULL if the data passed in the certificate parameter + // is not a valid certificate object." + qCWarning(lcX509, "SecCertificateCopyData returned invalid DER data (nullptr)."); } } } diff --git a/src/plugins/tls/shared/qsslsocket_qt.cpp b/src/plugins/tls/shared/qsslsocket_qt.cpp index 128459ea19..f55b3e3ded 100644 --- a/src/plugins/tls/shared/qsslsocket_qt.cpp +++ b/src/plugins/tls/shared/qsslsocket_qt.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.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$ -** -****************************************************************************/ +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qasn1element_p.h" @@ -109,15 +73,11 @@ static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QStrin QByteArray A; QByteArray B; B.resize(v); - QCryptographicHash hash(QCryptographicHash::Sha1); for (int i = 0; i < c; ++i) { // hash r iterations QByteArray Ai = D + I; - for (int j = 0; j < r; ++j) { - hash.reset(); - hash.addData(Ai); - Ai = hash.result(); - } + for (int j = 0; j < r; ++j) + Ai = QCryptographicHash::hash(Ai, QCryptographicHash::Sha1); for (int j = 0; j < v; ++j) B[j] = Ai[j % u]; diff --git a/src/plugins/tls/shared/qtlskey_base.cpp b/src/plugins/tls/shared/qtlskey_base.cpp index 13ce063f30..ff541165fe 100644 --- a/src/plugins/tls/shared/qtlskey_base.cpp +++ b/src/plugins/tls/shared/qtlskey_base.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlskey_base_p.h" #include "qasn1element_p.h" diff --git a/src/plugins/tls/shared/qtlskey_base_p.h b/src/plugins/tls/shared/qtlskey_base_p.h index 61bd67119b..ebfa15a2f9 100644 --- a/src/plugins/tls/shared/qtlskey_base_p.h +++ b/src/plugins/tls/shared/qtlskey_base_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_BASE_P_H #define QTLSKEY_BASE_P_H diff --git a/src/plugins/tls/shared/qtlskey_generic.cpp b/src/plugins/tls/shared/qtlskey_generic.cpp index b9eaf3c1f6..4645ef4703 100644 --- a/src/plugins/tls/shared/qtlskey_generic.cpp +++ b/src/plugins/tls/shared/qtlskey_generic.cpp @@ -1,42 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qtlskey_generic_p.h" #include "qasn1element_p.h" @@ -424,9 +388,9 @@ QByteArray deriveAesKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhr hash.addData(data); if (cipher == Cipher::Aes192Cbc) - return key.append(hash.result().constData(), 8); + return key.append(hash.resultView().first(8)); - return key.append(hash.result()); + return key.append(hash.resultView()); } QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, @@ -770,7 +734,7 @@ QByteArray TlsKeyGeneric::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy if (der.contains("Proc-Type:")) { // taken from QHttpNetworkReplyPrivate::parseHeader int i = 0; - while (i < der.count()) { + while (i < der.length()) { int j = der.indexOf(':', i); // field-name if (j == -1) break; @@ -789,7 +753,7 @@ QByteArray TlsKeyGeneric::derFromPem(const QByteArray &pem, QMap<QByteArray, QBy int length = i -(hasCR ? 1: 0) - j; value += der.mid(j, length).trimmed(); j = ++i; - } while (i < der.count() && (der.at(i) == ' ' || der.at(i) == '\t')); + } while (i < der.length() && (der.at(i) == ' ' || der.at(i) == '\t')); if (i == -1) break; // something is wrong diff --git a/src/plugins/tls/shared/qtlskey_generic_p.h b/src/plugins/tls/shared/qtlskey_generic_p.h index beb3d410a6..6344633cc7 100644 --- a/src/plugins/tls/shared/qtlskey_generic_p.h +++ b/src/plugins/tls/shared/qtlskey_generic_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QTLSKEY_GENERIC_P_H #define QTLSKEY_GENERIC_P_H diff --git a/src/plugins/tls/shared/qwincrypt_p.h b/src/plugins/tls/shared/qwincrypt_p.h index 2a7bd1fae2..48ca4247fa 100644 --- a/src/plugins/tls/shared/qwincrypt_p.h +++ b/src/plugins/tls/shared/qwincrypt_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QWINCRYPT_P_H #define QWINCRYPT_P_H @@ -76,6 +40,16 @@ struct QHCertStoreDeleter { // A simple RAII type used by Schannel code and Window CA fetcher class: using QHCertStorePointer = std::unique_ptr<void, QHCertStoreDeleter>; +struct QPCCertContextDeleter { + void operator()(PCCERT_CONTEXT context) const + { + CertFreeCertificateContext(context); + } +}; + +// A simple RAII type used by Schannel code +using QPCCertContextPointer = std::unique_ptr<const CERT_CONTEXT, QPCCertContextDeleter>; + QT_END_NAMESPACE #endif // QWINCRYPT_P_H diff --git a/src/plugins/tls/shared/qx509_base.cpp b/src/plugins/tls/shared/qx509_base.cpp index d7b7b81606..dfa6569fa6 100644 --- a/src/plugins/tls/shared/qx509_base.cpp +++ b/src/plugins/tls/shared/qx509_base.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qx509_base_p.h" diff --git a/src/plugins/tls/shared/qx509_base_p.h b/src/plugins/tls/shared/qx509_base_p.h index b86b573512..0f268880af 100644 --- a/src/plugins/tls/shared/qx509_base_p.h +++ b/src/plugins/tls/shared/qx509_base_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509CERTIFICATE_BASE_P_H #define QX509CERTIFICATE_BASE_P_H diff --git a/src/plugins/tls/shared/qx509_generic.cpp b/src/plugins/tls/shared/qx509_generic.cpp index 9265498c4e..5006db1a72 100644 --- a/src/plugins/tls/shared/qx509_generic.cpp +++ b/src/plugins/tls/shared/qx509_generic.cpp @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include <QtNetwork/private/qsslcertificate_p.h> #include <QtNetwork/private/qssl_p.h> @@ -52,6 +16,8 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + namespace QTlsPrivate { namespace { @@ -79,8 +45,6 @@ bool X509CertificateGeneric::isSelfSigned() const if (null) return false; - qCWarning(lcTlsBackend, "QSslCertificate::isSelfSigned: This function does not check, whether the certificate " - "is actually signed. It just checks whether issuer and subject are identical"); return subjectMatchesIssuer; } @@ -154,7 +118,7 @@ QList<QSslCertificate> X509CertificateGeneric::certificatesFromPem(const QByteAr QByteArray decoded = QByteArray::fromBase64( QByteArray::fromRawData(pem.data() + startPos, endPos - startPos)); - certificates << certificatesFromDer(decoded, 1);; + certificates << certificatesFromDer(decoded, 1); } return certificates; @@ -224,7 +188,7 @@ bool X509CertificateGeneric::parse(const QByteArray &data) if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; - QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); + QByteArray issuerDer = data.mid(dataStream.device()->pos() - elem.value().size(), elem.value().size()); issuerInfoEntries = elem.toInfo(); // validity period @@ -251,7 +215,7 @@ bool X509CertificateGeneric::parse(const QByteArray &data) if (!elem.read(certStream) || elem.type() != QAsn1Element::SequenceType) return false; - QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().length(), elem.value().length()); + QByteArray subjectDer = data.mid(dataStream.device()->pos() - elem.value().size(), elem.value().size()); subjectInfoEntries = elem.toInfo(); subjectMatchesIssuer = issuerDer == subjectDer; @@ -293,11 +257,11 @@ bool X509CertificateGeneric::parse(const QByteArray &data) if (!parseExtension(elem.value(), extension)) return false; - if (extension.oid == QLatin1String("2.5.29.17")) { + if (extension.oid == "2.5.29.17"_L1) { // subjectAltName // Note, parseExtension() returns true for this extensions, - // but considers it to be unsupported and assignes a useless + // but considers it to be unsupported and assigns a useless // value. OpenSSL also treats this extension as unsupported, // but properly creates a map with 'name' and 'value' taken // from the extension. We only support 'email', 'IP' and 'DNS', @@ -321,7 +285,7 @@ bool X509CertificateGeneric::parse(const QByteArray &data) case QAsn1Element::IpAddressType: { QHostAddress ipAddress; QByteArray ipAddrValue = nameElem.value(); - switch (ipAddrValue.length()) { + switch (ipAddrValue.size()) { case 4: // IPv4 ipAddress = QHostAddress(qFromBigEndian(*reinterpret_cast<quint32 *>(ipAddrValue.data()))); break; diff --git a/src/plugins/tls/shared/qx509_generic_p.h b/src/plugins/tls/shared/qx509_generic_p.h index 3e99dcde62..94a4bae7cf 100644 --- a/src/plugins/tls/shared/qx509_generic_p.h +++ b/src/plugins/tls/shared/qx509_generic_p.h @@ -1,41 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** 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$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #ifndef QX509_GENERIC_P_H #define QX509_GENERIC_P_H |