diff options
Diffstat (limited to 'src/plugins/tls/securetransport/qtlsbackend_st.cpp')
-rw-r--r-- | src/plugins/tls/securetransport/qtlsbackend_st.cpp | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/src/plugins/tls/securetransport/qtlsbackend_st.cpp b/src/plugins/tls/securetransport/qtlsbackend_st.cpp new file mode 100644 index 0000000000..54e45d1720 --- /dev/null +++ b/src/plugins/tls/securetransport/qtlsbackend_st.cpp @@ -0,0 +1,361 @@ +// 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" +#include "qx509_st_p.h" +#include "qtls_st_p.h" + +#include <QtCore/qsysinfo.h> +#include <QtCore/qmutex.h> + +QT_BEGIN_NAMESPACE + +using namespace Qt::StringLiterals; + +Q_GLOBAL_STATIC(QRecursiveMutex, qt_securetransport_mutex) + +Q_LOGGING_CATEGORY(lcSecureTransport, "qt.tlsbackend.securetransport"); + +namespace QTlsPrivate { + +QList<QSslCertificate> systemCaCertificates(); // defined in qsslsocket_mac_shared.cpp + +SSLContextRef qt_createSecureTransportContext(QSslSocket::SslMode mode); + +QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher) +{ + QString name; + switch (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 = "AES128-SHA"_L1; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA: + name = "DHE-RSA-AES128-SHA"_L1; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA: + name = "AES256-SHA"_L1; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA: + name = "DHE-RSA-AES256-SHA"_L1; + break; + + // ECDSA addenda, RFC 4492 + case TLS_ECDH_ECDSA_WITH_NULL_SHA: + name = "ECDH-ECDSA-NULL-SHA"_L1; + break; + case TLS_ECDH_ECDSA_WITH_RC4_128_SHA: + name = "ECDH-ECDSA-RC4-SHA"_L1; + break; + case TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA: + name = "ECDH-ECDSA-DES-CBC3-SHA"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA: + name = "ECDH-ECDSA-AES128-SHA"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA: + name = "ECDH-ECDSA-AES256-SHA"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_NULL_SHA: + name = "ECDHE-ECDSA-NULL-SHA"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_RC4_128_SHA: + name = "ECDHE-ECDSA-RC4-SHA"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA: + name = "ECDHE-ECDSA-DES-CBC3-SHA"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA: + name = "ECDHE-ECDSA-AES128-SHA"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA: + name = "ECDHE-ECDSA-AES256-SHA"_L1; + break; + case TLS_ECDH_RSA_WITH_NULL_SHA: + name = "ECDH-RSA-NULL-SHA"_L1; + break; + case TLS_ECDH_RSA_WITH_RC4_128_SHA: + name = "ECDH-RSA-RC4-SHA"_L1; + break; + case TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA: + name = "ECDH-RSA-DES-CBC3-SHA"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA: + name = "ECDH-RSA-AES128-SHA"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_SHA: + name = "ECDH-RSA-AES256-SHA"_L1; + break; + case TLS_ECDHE_RSA_WITH_NULL_SHA: + name = "ECDHE-RSA-NULL-SHA"_L1; + break; + case TLS_ECDHE_RSA_WITH_RC4_128_SHA: + name = "ECDHE-RSA-RC4-SHA"_L1; + break; + case TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA: + name = "ECDHE-RSA-DES-CBC3-SHA"_L1; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA: + name = "ECDHE-RSA-AES128-SHA"_L1; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA: + name = "ECDHE-RSA-AES256-SHA"_L1; + break; + + // TLS 1.2 addenda, RFC 5246 + case TLS_RSA_WITH_3DES_EDE_CBC_SHA: + name = "DES-CBC3-SHA"_L1; + break; + case TLS_RSA_WITH_AES_128_CBC_SHA256: + name = "AES128-SHA256"_L1; + break; + case TLS_RSA_WITH_AES_256_CBC_SHA256: + name = "AES256-SHA256"_L1; + break; + case TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA: + name = "DHE-RSA-DES-CBC3-SHA"_L1; + break; + case TLS_DHE_RSA_WITH_AES_128_CBC_SHA256: + name = "DHE-RSA-AES128-SHA256"_L1; + break; + case TLS_DHE_RSA_WITH_AES_256_CBC_SHA256: + name = "DHE-RSA-AES256-SHA256"_L1; + break; + + // Addendum from RFC 4279, TLS PSK + // all missing atm. + + // RFC 4785 - Pre-Shared Key (PSK) Ciphersuites with NULL Encryption + // all missing atm. + + // Addenda from rfc 5288 AES Galois Counter Mode (CGM) Cipher Suites for TLS + case TLS_RSA_WITH_AES_256_GCM_SHA384: + name = "AES256-GCM-SHA384"_L1; + break; + + // RFC 5487 - PSK with SHA-256/384 and AES GCM + // all missing atm. + + // Addenda from rfc 5289 Elliptic Curve Cipher Suites with HMAC SHA-256/384 + case TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256: + name = "ECDHE-ECDSA-AES128-SHA256"_L1; + break; + case TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384: + name = "ECDHE-ECDSA-AES256-SHA384"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256: + name = "ECDH-ECDSA-AES128-SHA256"_L1; + break; + case TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384: + name = "ECDH-ECDSA-AES256-SHA384"_L1; + break; + case TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256: + name = "ECDHE-RSA-AES128-SHA256"_L1; + break; + case TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384: + name = "ECDHE-RSA-AES256-SHA384"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256: + name = "ECDH-RSA-AES128-SHA256"_L1; + break; + case TLS_ECDH_RSA_WITH_AES_256_CBC_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 = "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, "TLSv1.2"_L1); +} + +} // namespace QTlsPrivate + +bool QSecureTransportBackend::s_loadedCiphersAndCerts = false; + +QString QSecureTransportBackend::tlsLibraryVersionString() const +{ + return "Secure Transport, "_L1 + QSysInfo::prettyProductName(); +} + +QString QSecureTransportBackend::tlsLibraryBuildVersionString() const +{ + return tlsLibraryVersionString(); +} + +void QSecureTransportBackend::ensureInitialized() const +{ + const QMutexLocker locker(qt_securetransport_mutex()); + if (s_loadedCiphersAndCerts) + return; + + // We have to set it before setDefaultSupportedCiphers, + // since this function can trigger static (global)'s initialization + // and as a result - recursive ensureInitialized call + // from QSslCertificatePrivate's ctor. + s_loadedCiphersAndCerts = true; + + const QTlsPrivate::QSecureTransportContext context(QTlsPrivate::qt_createSecureTransportContext(QSslSocket::SslClientMode)); + if (context) { + QList<QSslCipher> ciphers; + QList<QSslCipher> defaultCiphers; + + size_t numCiphers = 0; + // Fails only if any of parameters is null. + SSLGetNumberSupportedCiphers(context, &numCiphers); + QList<SSLCipherSuite> cfCiphers(numCiphers); + // Fails only if any of parameter is null or number of ciphers is wrong. + SSLGetSupportedCiphers(context, cfCiphers.data(), &numCiphers); + + for (size_t i = 0; i < size_t(cfCiphers.size()); ++i) { + const QSslCipher ciph(QTlsPrivate::QSslCipher_from_SSLCipherSuite(cfCiphers.at(i))); + if (!ciph.isNull()) { + ciphers << ciph; + if (ciph.usedBits() >= 128) + defaultCiphers << ciph; + } + } + + setDefaultSupportedCiphers(ciphers); + setDefaultCiphers(defaultCiphers); + + if (!QSslSocketPrivate::rootCertOnDemandLoadingSupported()) + setDefaultCaCertificates(systemCaCertificates()); + } else { + s_loadedCiphersAndCerts = false; + } +} + +QString QSecureTransportBackend::backendName() const +{ + return builtinBackendNames[nameIndexSecureTransport]; +} + +QTlsPrivate::TlsKey *QSecureTransportBackend::createKey() const +{ + return new QTlsPrivate::TlsKeySecureTransport; +} + +QTlsPrivate::X509Certificate *QSecureTransportBackend::createCertificate() const +{ + return new QTlsPrivate::X509CertificateSecureTransport; +} + +QList<QSslCertificate> QSecureTransportBackend::systemCaCertificates() const +{ + return QTlsPrivate::systemCaCertificates(); +} + +QList<QSsl::SslProtocol> QSecureTransportBackend::supportedProtocols() const +{ + QList<QSsl::SslProtocol> protocols; + + 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; + + return protocols; +} + +QList<QSsl::SupportedFeature> QSecureTransportBackend::supportedFeatures() const +{ + QList<QSsl::SupportedFeature> features; + features << QSsl::SupportedFeature::ClientSideAlpn; + + return features; +} + +QList<QSsl::ImplementedClass> QSecureTransportBackend::implementedClasses() const +{ + QList<QSsl::ImplementedClass> classes; + classes << QSsl::ImplementedClass::Socket; + classes << QSsl::ImplementedClass::Certificate; + classes << QSsl::ImplementedClass::Key; + + return classes; +} + +QTlsPrivate::X509PemReaderPtr QSecureTransportBackend::X509PemReader() const +{ + return QTlsPrivate::X509CertificateGeneric::certificatesFromPem; +} + +QTlsPrivate::X509DerReaderPtr QSecureTransportBackend::X509DerReader() const +{ + return QTlsPrivate::X509CertificateGeneric::certificatesFromDer; +} + +QTlsPrivate::TlsCryptograph *QSecureTransportBackend::createTlsCryptograph() const +{ + return new QTlsPrivate::TlsCryptographSecureTransport; +} + +QT_END_NAMESPACE + + +#include "moc_qtlsbackend_st_p.cpp" |