summaryrefslogtreecommitdiffstats
path: root/src/network/ssl
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl')
-rw-r--r--src/network/ssl/qdtls.h2
-rw-r--r--src/network/ssl/qocspresponse.cpp2
-rw-r--r--src/network/ssl/qocspresponse.h2
-rw-r--r--src/network/ssl/qpassworddigestor.cpp100
-rw-r--r--src/network/ssl/qssl.cpp2
-rw-r--r--src/network/ssl/qssl.h13
-rw-r--r--src/network/ssl/qsslcertificate.cpp74
-rw-r--r--src/network/ssl/qsslcertificate.h2
-rw-r--r--src/network/ssl/qsslcertificate_p.h4
-rw-r--r--src/network/ssl/qsslconfiguration.cpp41
-rw-r--r--src/network/ssl/qsslconfiguration.h2
-rw-r--r--src/network/ssl/qssldiffiehellmanparameters.cpp16
-rw-r--r--src/network/ssl/qsslellipticcurve.cpp2
-rw-r--r--src/network/ssl/qsslkey.h2
-rw-r--r--src/network/ssl/qsslpresharedkeyauthenticator.h1
-rw-r--r--src/network/ssl/qsslserver.cpp151
-rw-r--r--src/network/ssl/qsslserver.h3
-rw-r--r--src/network/ssl/qsslserver_p.h34
-rw-r--r--src/network/ssl/qsslsocket.cpp42
-rw-r--r--src/network/ssl/qsslsocket.h2
-rw-r--r--src/network/ssl/qtlsbackend.cpp36
-rw-r--r--src/network/ssl/qtlsbackend_p.h18
22 files changed, 433 insertions, 118 deletions
diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h
index 903ba5b4e1..dd24aa219a 100644
--- a/src/network/ssl/qdtls.h
+++ b/src/network/ssl/qdtls.h
@@ -15,7 +15,7 @@
Q_MOC_INCLUDE(<QtNetwork/QSslPreSharedKeyAuthenticator>)
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
QT_REQUIRE_CONFIG(dtls);
#endif
diff --git a/src/network/ssl/qocspresponse.cpp b/src/network/ssl/qocspresponse.cpp
index 9911988aff..74e2c814fd 100644
--- a/src/network/ssl/qocspresponse.cpp
+++ b/src/network/ssl/qocspresponse.cpp
@@ -201,8 +201,6 @@ bool QOcspResponse::isEqual(const QOcspResponse &other) const
}
/*!
- \fn size_t qHash(const QOcspResponse &response, size_t seed)
-
Returns the hash value for the \a response, using \a seed to seed the calculation.
\since 5.13
diff --git a/src/network/ssl/qocspresponse.h b/src/network/ssl/qocspresponse.h
index d208edab7a..68251a1547 100644
--- a/src/network/ssl/qocspresponse.h
+++ b/src/network/ssl/qocspresponse.h
@@ -11,7 +11,7 @@
#include <QtCore/qmetatype.h>
#include <QtCore/qobject.h>
-#ifndef Q_CLANG_QDOC
+#ifndef Q_QDOC
QT_REQUIRE_CONFIG(ssl);
#endif
diff --git a/src/network/ssl/qpassworddigestor.cpp b/src/network/ssl/qpassworddigestor.cpp
index a6c6e7666c..94de14abd4 100644
--- a/src/network/ssl/qpassworddigestor.cpp
+++ b/src/network/ssl/qpassworddigestor.cpp
@@ -6,9 +6,20 @@
#include <QtCore/QDebug>
#include <QtCore/QMessageAuthenticationCode>
#include <QtCore/QtEndian>
+#include <QtCore/QList>
+
+#include "qtcore-config_p.h"
#include <limits>
+#if QT_CONFIG(opensslv30) && QT_CONFIG(openssl_linked)
+#define USING_OPENSSL30
+#include <openssl/core_names.h>
+#include <openssl/kdf.h>
+#include <openssl/params.h>
+#include <openssl/provider.h>
+#endif
+
QT_BEGIN_NAMESPACE
namespace QPasswordDigestor {
@@ -86,6 +97,85 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf1(QCryptographicHash::Algorithm algori
return key.left(dkLen);
}
+#ifdef USING_OPENSSL30
+// Copied from QCryptographicHashPrivate
+static constexpr const char * methodToName(QCryptographicHash::Algorithm method) noexcept
+{
+ switch (method) {
+#define CASE(Enum, Name) \
+ case QCryptographicHash:: Enum : \
+ return Name \
+ /*end*/
+ CASE(Sha1, "SHA1");
+ CASE(Md4, "MD4");
+ CASE(Md5, "MD5");
+ CASE(Sha224, "SHA224");
+ CASE(Sha256, "SHA256");
+ CASE(Sha384, "SHA384");
+ CASE(Sha512, "SHA512");
+ CASE(RealSha3_224, "SHA3-224");
+ CASE(RealSha3_256, "SHA3-256");
+ CASE(RealSha3_384, "SHA3-384");
+ CASE(RealSha3_512, "SHA3-512");
+ CASE(Keccak_224, "SHA3-224");
+ CASE(Keccak_256, "SHA3-256");
+ CASE(Keccak_384, "SHA3-384");
+ CASE(Keccak_512, "SHA3-512");
+ CASE(Blake2b_512, "BLAKE2B512");
+ CASE(Blake2s_256, "BLAKE2S256");
+#undef CASE
+ default: return nullptr;
+ }
+}
+
+static QByteArray opensslDeriveKeyPbkdf2(QCryptographicHash::Algorithm algorithm,
+ const QByteArray &data, const QByteArray &salt,
+ uint64_t iterations, quint64 dkLen)
+{
+ EVP_KDF *kdf = EVP_KDF_fetch(nullptr, "PBKDF2", nullptr);
+
+ if (!kdf)
+ return QByteArray();
+
+ auto cleanUpKdf = qScopeGuard([kdf] {
+ EVP_KDF_free(kdf);
+ });
+
+ EVP_KDF_CTX *ctx = EVP_KDF_CTX_new(kdf);
+
+ if (!ctx)
+ return QByteArray();
+
+ auto cleanUpCtx = qScopeGuard([ctx] {
+ EVP_KDF_CTX_free(ctx);
+ });
+
+ // Do not enable SP800-132 compliance check, otherwise we will require:
+ // - the iteration count is at least 1000
+ // - the salt length is at least 128 bits
+ // - the derived key length is at least 112 bits
+ // This would be a different behavior from the original implementation.
+ int checkDisabled = 1;
+ QList<OSSL_PARAM> params;
+ params.append(OSSL_PARAM_construct_utf8_string(OSSL_KDF_PARAM_DIGEST, const_cast<char*>(methodToName(algorithm)), 0));
+ params.append(OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_SALT, const_cast<char*>(salt.data()), salt.size()));
+ params.append(OSSL_PARAM_construct_octet_string(OSSL_KDF_PARAM_PASSWORD, const_cast<char*>(data.data()), data.size()));
+ params.append(OSSL_PARAM_construct_uint64(OSSL_KDF_PARAM_ITER, &iterations));
+ params.append(OSSL_PARAM_construct_int(OSSL_KDF_PARAM_PKCS5, &checkDisabled));
+ params.append(OSSL_PARAM_construct_end());
+
+ if (EVP_KDF_CTX_set_params(ctx, params.data()) <= 0)
+ return QByteArray();
+
+ QByteArray derived(dkLen, '\0');
+
+ if (!EVP_KDF_derive(ctx, reinterpret_cast<unsigned char*>(derived.data()), derived.size(), nullptr))
+ return QByteArray();
+
+ return derived;
+}
+#endif
+
/*!
\since 5.12
@@ -107,8 +197,6 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algori
const QByteArray &data, const QByteArray &salt,
int iterations, quint64 dkLen)
{
- // https://tools.ietf.org/html/rfc8018#section-5.2
-
// The RFC recommends checking that 'dkLen' is not greater than '(2^32 - 1) * hLen'
int hashLen = QCryptographicHash::hashLength(algorithm);
const quint64 maxLen = quint64(std::numeric_limits<quint32>::max() - 1) * hashLen;
@@ -122,11 +210,17 @@ Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algori
if (iterations < 1 || dkLen < 1)
return QByteArray();
+#ifdef USING_OPENSSL30
+ if (methodToName(algorithm))
+ return opensslDeriveKeyPbkdf2(algorithm, data, salt, iterations, dkLen);
+#endif
+
+ // https://tools.ietf.org/html/rfc8018#section-5.2
QByteArray key;
quint32 currentIteration = 1;
QMessageAuthenticationCode hmac(algorithm, data);
QByteArray index(4, Qt::Uninitialized);
- while (quint64(key.length()) < dkLen) {
+ while (quint64(key.size()) < dkLen) {
hmac.addData(salt);
qToBigEndian(currentIteration, index.data());
diff --git a/src/network/ssl/qssl.cpp b/src/network/ssl/qssl.cpp
index 7525df8c87..dfd3745d3e 100644
--- a/src/network/ssl/qssl.cpp
+++ b/src/network/ssl/qssl.cpp
@@ -256,3 +256,5 @@ Q_LOGGING_CATEGORY(lcSsl, "qt.network.ssl");
*/
QT_END_NAMESPACE
+
+#include "moc_qssl.cpp"
diff --git a/src/network/ssl/qssl.h b/src/network/ssl/qssl.h
index 3d01168172..e52b8c6361 100644
--- a/src/network/ssl/qssl.h
+++ b/src/network/ssl/qssl.h
@@ -10,21 +10,26 @@
#endif
#include <QtNetwork/qtnetworkglobal.h>
+#include <QtCore/qobjectdefs.h>
#include <QtCore/QFlags>
QT_BEGIN_NAMESPACE
namespace QSsl {
+ Q_NAMESPACE_EXPORT(Q_NETWORK_EXPORT)
+
enum KeyType {
PrivateKey,
PublicKey
};
+ Q_ENUM_NS(KeyType)
enum EncodingFormat {
Pem,
Der
};
+ Q_ENUM_NS(EncodingFormat)
enum KeyAlgorithm {
Opaque,
@@ -33,12 +38,14 @@ namespace QSsl {
Ec,
Dh,
};
+ Q_ENUM_NS(KeyAlgorithm)
enum AlternativeNameEntryType {
EmailEntry,
DnsEntry,
IpAddressEntry
};
+ Q_ENUM_NS(AlternativeNameEntryType)
enum SslProtocol {
TlsV1_0 QT_DEPRECATED_VERSION_X_6_3("Use TlsV1_2OrLater instead."),
@@ -61,6 +68,7 @@ namespace QSsl {
UnknownProtocol = -1
};
+ Q_ENUM_NS(SslProtocol)
enum SslOption {
SslOptionDisableEmptyFragments = 0x01,
@@ -72,6 +80,7 @@ namespace QSsl {
SslOptionDisableSessionPersistence = 0x40,
SslOptionDisableServerCipherPreference = 0x80
};
+ Q_ENUM_NS(SslOption)
Q_DECLARE_FLAGS(SslOptions, SslOption)
enum class AlertLevel {
@@ -79,6 +88,7 @@ namespace QSsl {
Fatal,
Unknown
};
+ Q_ENUM_NS(AlertLevel)
enum class AlertType {
CloseNotify,
@@ -116,6 +126,7 @@ namespace QSsl {
NoApplicationProtocol = 120,
UnknownAlertMessage = 255
};
+ Q_ENUM_NS(AlertType)
enum class ImplementedClass
{
@@ -127,6 +138,7 @@ namespace QSsl {
Dtls,
DtlsCookie
};
+ Q_ENUM_NS(ImplementedClass)
enum class SupportedFeature
{
@@ -138,6 +150,7 @@ namespace QSsl {
SessionTicket,
Alerts
};
+ Q_ENUM_NS(SupportedFeature)
}
Q_DECLARE_OPERATORS_FOR_FLAGS(QSsl::SslOptions)
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 39745427eb..9878c603b6 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -110,7 +110,7 @@
#endif
#include <QtCore/qdir.h>
-#include <QtCore/qdiriterator.h>
+#include <QtCore/qdirlisting.h>
#include <QtCore/qfile.h>
QT_BEGIN_NAMESPACE
@@ -186,7 +186,7 @@ QSslCertificate::QSslCertificate(const QByteArray &data, QSsl::EncodingFormat fo
return;
}
- QList<QSslCertificate> certs = X509Reader(data, 1);
+ const QList<QSslCertificate> certs = X509Reader(data, 1);
if (!certs.isEmpty())
d = certs.first().d;
}
@@ -624,7 +624,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
QString sourcePath = QDir::fromNativeSeparators(path);
// Find the path without the filename
- QString pathPrefix = sourcePath.left(sourcePath.lastIndexOf(u'/'));
+ QStringView pathPrefix = QStringView(sourcePath).left(sourcePath.lastIndexOf(u'/'));
// Check if the path contains any special chars
int pos = -1;
@@ -647,7 +647,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
if (lastIndexOfSlash != -1)
pathPrefix = pathPrefix.left(lastIndexOfSlash);
else
- pathPrefix.clear();
+ pathPrefix = {};
} else {
// Check if the path is a file.
if (QFileInfo(sourcePath).isFile()) {
@@ -664,10 +664,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
// Special case - if the prefix ends up being nothing, use "." instead.
int startIndex = 0;
if (pathPrefix.isEmpty()) {
- pathPrefix = "."_L1;
+ pathPrefix = u".";
startIndex = 2;
}
+ const QString pathPrefixString = pathPrefix.toString();
+
// The path can be a file or directory.
QList<QSslCertificate> certs;
@@ -678,9 +680,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
QRegularExpression pattern(QRegularExpression::anchoredPattern(sourcePath));
#endif
- QDirIterator it(pathPrefix, QDir::Files, QDirIterator::FollowSymlinks | QDirIterator::Subdirectories);
- while (it.hasNext()) {
- QString filePath = startIndex == 0 ? it.next() : it.next().mid(startIndex);
+ using F = QDirListing::IteratorFlag;
+ constexpr auto iterFlags = F::FollowSymlinks | F::Recursive;
+ for (const auto &dirEntry : QDirListing(pathPrefixString, QDir::Files, iterFlags)) {
+ QString filePath = dirEntry.filePath();
+ if (startIndex > 0)
+ filePath.remove(0, startIndex);
#if QT_CONFIG(regularexpression)
if (!pattern.match(filePath).hasMatch())
@@ -878,7 +883,7 @@ static const char *const certificate_blacklist[] = {
bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
{
for (int a = 0; certificate_blacklist[a] != nullptr; a++) {
- QString blacklistedCommonName = QString::fromUtf8(certificate_blacklist[(a+1)]);
+ auto blacklistedCommonName = QAnyStringView(QUtf8StringView(certificate_blacklist[(a+1)]));
if (certificate.serialNumber() == certificate_blacklist[a++] &&
(certificate.subjectInfo(QSslCertificate::CommonName).contains(blacklistedCommonName) ||
certificate.issuerInfo(QSslCertificate::CommonName).contains(blacklistedCommonName)))
@@ -889,19 +894,18 @@ bool QSslCertificatePrivate::isBlacklisted(const QSslCertificate &certificate)
QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectInfo info)
{
- QByteArray str;
switch (info) {
- case QSslCertificate::Organization: str = QByteArray("O"); break;
- case QSslCertificate::CommonName: str = QByteArray("CN"); break;
- case QSslCertificate::LocalityName: str = QByteArray("L"); break;
- case QSslCertificate::OrganizationalUnitName: str = QByteArray("OU"); break;
- case QSslCertificate::CountryName: str = QByteArray("C"); break;
- case QSslCertificate::StateOrProvinceName: str = QByteArray("ST"); break;
- case QSslCertificate::DistinguishedNameQualifier: str = QByteArray("dnQualifier"); break;
- case QSslCertificate::SerialNumber: str = QByteArray("serialNumber"); break;
- case QSslCertificate::EmailAddress: str = QByteArray("emailAddress"); break;
+ case QSslCertificate::Organization: return "O"_ba;
+ case QSslCertificate::CommonName: return "CN"_ba;
+ case QSslCertificate::LocalityName: return"L"_ba;
+ case QSslCertificate::OrganizationalUnitName: return "OU"_ba;
+ case QSslCertificate::CountryName: return "C"_ba;
+ case QSslCertificate::StateOrProvinceName: return "ST"_ba;
+ case QSslCertificate::DistinguishedNameQualifier: return "dnQualifier"_ba;
+ case QSslCertificate::SerialNumber: return "serialNumber"_ba;
+ case QSslCertificate::EmailAddress: return "emailAddress"_ba;
}
- return str;
+ return QByteArray();
}
/*!
@@ -918,13 +922,13 @@ QString QSslCertificate::issuerDisplayName() const
QStringList names;
names = issuerInfo(QSslCertificate::CommonName);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
names = issuerInfo(QSslCertificate::Organization);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
names = issuerInfo(QSslCertificate::OrganizationalUnitName);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
return QString();
}
@@ -943,20 +947,18 @@ QString QSslCertificate::subjectDisplayName() const
QStringList names;
names = subjectInfo(QSslCertificate::CommonName);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
names = subjectInfo(QSslCertificate::Organization);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
names = subjectInfo(QSslCertificate::OrganizationalUnitName);
if (!names.isEmpty())
- return names.first();
+ return names.constFirst();
return QString();
}
/*!
- \fn size_t qHash(const QSslCertificate &key, size_t seed)
-
Returns the hash value for the \a key, using \a seed to seed the calculation.
\since 5.4
\relates QHash
@@ -976,15 +978,15 @@ QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
QDebugStateSaver saver(debug);
debug.resetFormat().nospace();
debug << "QSslCertificate("
- << certificate.version()
- << ", " << certificate.serialNumber()
- << ", " << certificate.digest().toBase64()
- << ", " << certificate.issuerDisplayName()
- << ", " << certificate.subjectDisplayName()
- << ", " << certificate.subjectAlternativeNames()
+ << "Version=" << certificate.version()
+ << ", SerialNumber=" << certificate.serialNumber()
+ << ", Digest=" << certificate.digest().toBase64()
+ << ", Issuer=" << certificate.issuerDisplayName()
+ << ", Subject=" << certificate.subjectDisplayName()
+ << ", AlternativeSubjectNames=" << certificate.subjectAlternativeNames()
#if QT_CONFIG(datestring)
- << ", " << certificate.effectiveDate()
- << ", " << certificate.expiryDate()
+ << ", EffectiveDate=" << certificate.effectiveDate()
+ << ", ExpiryDate=" << certificate.expiryDate()
#endif
<< ')';
return debug;
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index 5807c8d2c7..cdf11b28b0 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -14,8 +14,8 @@
#include <QtCore/qbytearray.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qdatetime.h>
-#include <QtCore/qsharedpointer.h>
#include <QtCore/qmap.h>
+#include <QtCore/qshareddata.h>
#include <QtNetwork/qssl.h>
QT_BEGIN_NAMESPACE
diff --git a/src/network/ssl/qsslcertificate_p.h b/src/network/ssl/qsslcertificate_p.h
index 02cf002460..ca59abae82 100644
--- a/src/network/ssl/qsslcertificate_p.h
+++ b/src/network/ssl/qsslcertificate_p.h
@@ -35,8 +35,8 @@ public:
~QSslCertificatePrivate();
QList<QSslCertificateExtension> extensions() const;
- Q_NETWORK_PRIVATE_EXPORT static bool isBlacklisted(const QSslCertificate &certificate);
- Q_NETWORK_PRIVATE_EXPORT static QByteArray subjectInfoToString(QSslCertificate::SubjectInfo info);
+ Q_NETWORK_EXPORT static bool isBlacklisted(const QSslCertificate &certificate);
+ Q_NETWORK_EXPORT static QByteArray subjectInfoToString(QSslCertificate::SubjectInfo info);
QAtomicInt ref;
std::unique_ptr<QTlsPrivate::X509Certificate> backend;
diff --git a/src/network/ssl/qsslconfiguration.cpp b/src/network/ssl/qsslconfiguration.cpp
index 80377f3426..fd308d7037 100644
--- a/src/network/ssl/qsslconfiguration.cpp
+++ b/src/network/ssl/qsslconfiguration.cpp
@@ -105,6 +105,12 @@ const char QSslConfiguration::NextProtocolHttp1_1[] = "http/1.1";
*/
/*!
+ \variable QSslConfiguration::ALPNProtocolHTTP2
+ \brief The value used for negotiating HTTP 2 during the Application-Layer
+ Protocol Negotiation.
+*/
+
+/*!
Constructs an empty SSL configuration. This configuration contains
no valid settings and the state will be empty. isNull() will
return true after this constructor is called.
@@ -218,15 +224,15 @@ bool QSslConfiguration::isNull() const
d->peerVerifyMode == QSslSocket::AutoVerifyPeer &&
d->peerVerifyDepth == 0 &&
d->allowRootCertOnDemandLoading == true &&
- d->caCertificates.count() == 0 &&
- d->ciphers.count() == 0 &&
+ d->caCertificates.size() == 0 &&
+ d->ciphers.size() == 0 &&
d->ellipticCurves.isEmpty() &&
d->ephemeralServerKey.isNull() &&
d->dhParams == QSslDiffieHellmanParameters::defaultParameters() &&
d->localCertificateChain.isEmpty() &&
d->privateKey.isNull() &&
d->peerCertificate.isNull() &&
- d->peerCertificateChain.count() == 0 &&
+ d->peerCertificateChain.size() == 0 &&
d->backendConfig.isEmpty() &&
d->sslOptions == QSslConfigurationPrivate::defaultSslOptions &&
d->sslSession.isNull() &&
@@ -550,8 +556,6 @@ void QSslConfiguration::setPrivateKey(const QSslKey &key)
ciphers. You can revert to using the entire set by calling
setCiphers() with the list returned by supportedCiphers().
- \note This is not currently supported in the Schannel backend.
-
\sa setCiphers(), supportedCiphers()
*/
QList<QSslCipher> QSslConfiguration::ciphers() const
@@ -567,8 +571,6 @@ QList<QSslCipher> QSslConfiguration::ciphers() const
Restricting the cipher suite must be done before the handshake
phase, where the session cipher is chosen.
- \note This is not currently supported in the Schannel backend.
-
\sa ciphers(), supportedCiphers()
*/
void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers)
@@ -581,16 +583,14 @@ void QSslConfiguration::setCiphers(const QList<QSslCipher> &ciphers)
Sets the cryptographic cipher suite for this configuration to \a ciphers,
which is a colon-separated list of cipher suite names. The ciphers are listed
- in order of preference, starting with the most preferred cipher. For example:
-
- \snippet code/src_network_ssl_qsslconfiguration.cpp 1
-
+ in order of preference, starting with the most preferred cipher.
Each cipher name in \a ciphers must be the name of a cipher in the
list returned by supportedCiphers(). Restricting the cipher suite
must be done before the handshake phase, where the session cipher
is chosen.
- \note This is not currently supported in the Schannel backend.
+ \note With the Schannel backend the order of the ciphers is ignored and Schannel
+ picks the most secure one during the handshake.
\sa ciphers()
*/
@@ -922,7 +922,11 @@ void QSslConfiguration::setPreSharedKeyIdentityHint(const QByteArray &hint)
Retrieves the current set of Diffie-Hellman parameters.
If no Diffie-Hellman parameters have been set, the QSslConfiguration object
- defaults to using the 1024-bit MODP group from RFC 2409.
+ defaults to using the 2048-bit MODP group from RFC 3526.
+
+ \note The default parameters may change in future Qt versions.
+ Please check the documentation of the \e{exact Qt version} that you
+ are using in order to know what defaults that version uses.
*/
QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const
{
@@ -936,7 +940,14 @@ QSslDiffieHellmanParameters QSslConfiguration::diffieHellmanParameters() const
a server to \a dhparams.
If no Diffie-Hellman parameters have been set, the QSslConfiguration object
- defaults to using the 1024-bit MODP group from RFC 2409.
+ defaults to using the 2048-bit MODP group from RFC 3526.
+
+ Since 6.7 you can provide an empty Diffie-Hellman parameter to use auto selection
+ (see SSL_CTX_set_dh_auto of openssl) if the tls backend supports it.
+
+ \note The default parameters may change in future Qt versions.
+ Please check the documentation of the \e{exact Qt version} that you
+ are using in order to know what defaults that version uses.
*/
void QSslConfiguration::setDiffieHellmanParameters(const QSslDiffieHellmanParameters &dhparams)
{
@@ -1098,7 +1109,7 @@ void QSslConfiguration::setDefaultConfiguration(const QSslConfiguration &configu
QSslConfigurationPrivate::setDefaultConfiguration(configuration);
}
-#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(dtls) || defined(Q_QDOC)
/*!
This function returns true if DTLS cookie verification was enabled on a
diff --git a/src/network/ssl/qsslconfiguration.h b/src/network/ssl/qsslconfiguration.h
index 85c287bb2f..dd2dd2a97c 100644
--- a/src/network/ssl/qsslconfiguration.h
+++ b/src/network/ssl/qsslconfiguration.h
@@ -125,7 +125,7 @@ public:
static QSslConfiguration defaultConfiguration();
static void setDefaultConfiguration(const QSslConfiguration &configuration);
-#if QT_CONFIG(dtls) || defined(Q_CLANG_QDOC)
+#if QT_CONFIG(dtls) || defined(Q_QDOC)
bool dtlsCookieVerificationEnabled() const;
void setDtlsCookieVerificationEnabled(bool enable);
diff --git a/src/network/ssl/qssldiffiehellmanparameters.cpp b/src/network/ssl/qssldiffiehellmanparameters.cpp
index 04add93116..7da14f3536 100644
--- a/src/network/ssl/qssldiffiehellmanparameters.cpp
+++ b/src/network/ssl/qssldiffiehellmanparameters.cpp
@@ -33,17 +33,18 @@
QT_BEGIN_NAMESPACE
-// The 1024-bit MODP group from RFC 2459 (Second Oakley Group)
+// The 2048-bit MODP group from RFC 3526
Q_AUTOTEST_EXPORT const char *qssl_dhparams_default_base64 =
- "MIGHAoGBAP//////////yQ/aoiFowjTExmKLgNwc0SkCTgiKZ8x0Agu+pjsTmyJR"
- "Sgh5jjQE3e+VGbPNOkMbMCsKbfJfFDdP4TVtbVHCReSFtXZiXn7G9ExC6aY37WsL"
- "/1y29Aa37e44a/taiZ+lrp8kEXxLH+ZJKGZR7OZTgf//////////AgEC";
+ "MIIBCAKCAQEA///////////JD9qiIWjCNMTGYouA3BzRKQJOCIpnzHQCC76mOxObIlFKCHmO"
+ "NATd75UZs806QxswKwpt8l8UN0/hNW1tUcJF5IW1dmJefsb0TELppjftawv/XLb0Brft7jhr"
+ "+1qJn6WunyQRfEsf5kkoZlHs5Fs9wgB8uKFjvwWY2kg2HFXTmmkWP6j9JM9fg2VdI9yjrZYc"
+ "YvNWIIVSu57VKQdwlpZtZww1Tkq8mATxdGwIyhghfDKQXkYuNs474553LBgOhgObJ4Oi7Aei"
+ "j7XFXfBvTFLJ3ivL9pVYFxg5lUl86pVq5RXSJhiY+gUQFXKOWoqsqmj//////////wIBAg==";
/*!
Returns the default QSslDiffieHellmanParameters used by QSslSocket.
- This is currently the 1024-bit MODP group from RFC 2459, also
- known as the Second Oakley Group.
+ This is currently the 2048-bit MODP group from RFC 3526.
*/
QSslDiffieHellmanParameters QSslDiffieHellmanParameters::defaultParameters()
{
@@ -241,8 +242,7 @@ QString QSslDiffieHellmanParameters::errorString() const noexcept
return QCoreApplication::translate("QSslDiffieHellmanParameter", "The given Diffie-Hellman parameters are deemed unsafe");
}
- Q_UNREACHABLE();
- return QString();
+ Q_UNREACHABLE_RETURN(QString());
}
/*!
diff --git a/src/network/ssl/qsslellipticcurve.cpp b/src/network/ssl/qsslellipticcurve.cpp
index 959bf1de33..77aa66f3cc 100644
--- a/src/network/ssl/qsslellipticcurve.cpp
+++ b/src/network/ssl/qsslellipticcurve.cpp
@@ -160,7 +160,7 @@ bool QSslEllipticCurve::isTlsNamedCurve() const noexcept
*/
/*!
- \fn size_t qHash(QSslEllipticCurve curve, size_t seed)
+ \fn size_t qHash(QSslEllipticCurve curve, size_t seed = 0)
\since 5.5
\relates QHash
diff --git a/src/network/ssl/qsslkey.h b/src/network/ssl/qsslkey.h
index db14c89c98..decfc4b5a1 100644
--- a/src/network/ssl/qsslkey.h
+++ b/src/network/ssl/qsslkey.h
@@ -8,7 +8,7 @@
#include <QtNetwork/qtnetworkglobal.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qbytearray.h>
-#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <QtNetwork/qssl.h>
QT_BEGIN_NAMESPACE
diff --git a/src/network/ssl/qsslpresharedkeyauthenticator.h b/src/network/ssl/qsslpresharedkeyauthenticator.h
index 98cfad19ed..a3912406d3 100644
--- a/src/network/ssl/qsslpresharedkeyauthenticator.h
+++ b/src/network/ssl/qsslpresharedkeyauthenticator.h
@@ -16,6 +16,7 @@ QT_BEGIN_NAMESPACE
class QSslPreSharedKeyAuthenticatorPrivate;
class QSslPreSharedKeyAuthenticator
{
+ Q_GADGET_EXPORT(Q_NETWORK_EXPORT)
public:
Q_NETWORK_EXPORT QSslPreSharedKeyAuthenticator();
Q_NETWORK_EXPORT ~QSslPreSharedKeyAuthenticator();
diff --git a/src/network/ssl/qsslserver.cpp b/src/network/ssl/qsslserver.cpp
index 727d647784..40a6a6f526 100644
--- a/src/network/ssl/qsslserver.cpp
+++ b/src/network/ssl/qsslserver.cpp
@@ -16,7 +16,7 @@
Transport Layer Security (TLS).
To configure the secure handshake settings, use the applicable setter
- functions on a QSslConfiguration object, and then use it as a argument
+ functions on a QSslConfiguration object, and then use it as an argument
to the setSslConfiguration() function. All following incoming
connections handled will use these settings.
@@ -32,7 +32,7 @@
nextPendingConnection() function to fetch the next incoming connection and
take it out of the pending connection queue. The QSslSocket is a child of
the QSslServer and will be deleted when the QSslServer is deleted. It is
- still a good a good idea to destroy the object explicitly when you are done
+ still a good idea to destroy the object explicitly when you are done
with it, to avoid wasting memory.
\sa QTcpServer, QSslConfiguration, QSslSocket
@@ -171,6 +171,13 @@
QSslConfiguration::setHandshakeMustInterruptOnError()
*/
+/*!
+ \fn void QSslServer::startedEncryptionHandshake(QSslSocket *socket)
+
+ This signal is emitted when the client, connected to \a socket,
+ initiates the TLS handshake.
+*/
+
#include "qsslserver.h"
#include "qsslserver_p.h"
@@ -228,6 +235,42 @@ QSslConfiguration QSslServer::sslConfiguration() const
}
/*!
+ Sets the \a timeout to use for all incoming handshakes, in milliseconds.
+
+ This is relevant in the scenario where a client, whether malicious or
+ accidental, connects to the server but makes no attempt at communicating or
+ initiating a handshake. QSslServer will then automatically end the
+ connection after \a timeout milliseconds have elapsed.
+
+ By default the timeout is 5000 milliseconds (5 seconds).
+
+ \note The underlying TLS framework may have their own timeout logic now or
+ in the future, this function does not affect that.
+
+ \note The \a timeout passed to this function will only apply to \e{new}
+ connections. If a client is already connected it will use the timeout which
+ was set when it connected.
+
+ \sa handshakeTimeout()
+*/
+void QSslServer::setHandshakeTimeout(int timeout)
+{
+ Q_D(QSslServer);
+ d->handshakeTimeout = timeout;
+}
+
+/*!
+ Returns the currently configured handshake timeout.
+
+ \sa setHandshakeTimeout()
+*/
+int QSslServer::handshakeTimeout() const
+{
+ const Q_D(QSslServer);
+ return d->handshakeTimeout;
+}
+
+/*!
Called when a new connection is established.
Converts \a socket to a QSslSocket.
@@ -241,47 +284,129 @@ void QSslServer::incomingConnection(qintptr socket)
pSslSocket->setSslConfiguration(sslConfiguration());
if (Q_LIKELY(pSslSocket->setSocketDescriptor(socket))) {
- connect(pSslSocket, &QSslSocket::peerVerifyError,
+ connect(pSslSocket, &QSslSocket::peerVerifyError, this,
[this, pSslSocket](const QSslError &error) {
Q_EMIT peerVerifyError(pSslSocket, error);
});
- connect(pSslSocket, &QSslSocket::sslErrors,
+ connect(pSslSocket, &QSslSocket::sslErrors, this,
[this, pSslSocket](const QList<QSslError> &errors) {
Q_EMIT sslErrors(pSslSocket, errors);
});
- connect(pSslSocket, &QAbstractSocket::errorOccurred,
+ connect(pSslSocket, &QAbstractSocket::errorOccurred, this,
[this, pSslSocket](QAbstractSocket::SocketError error) {
Q_EMIT errorOccurred(pSslSocket, error);
if (!pSslSocket->isEncrypted())
pSslSocket->deleteLater();
});
- connect(pSslSocket, &QSslSocket::encrypted, [this, pSslSocket]() {
- pSslSocket->disconnect();
+ connect(pSslSocket, &QSslSocket::encrypted, this, [this, pSslSocket]() {
+ Q_D(QSslServer);
+ d->removeSocketData(quintptr(pSslSocket));
+ pSslSocket->disconnect(this);
addPendingConnection(pSslSocket);
});
- connect(pSslSocket, &QSslSocket::preSharedKeyAuthenticationRequired,
+ connect(pSslSocket, &QSslSocket::preSharedKeyAuthenticationRequired, this,
[this, pSslSocket](QSslPreSharedKeyAuthenticator *authenticator) {
Q_EMIT preSharedKeyAuthenticationRequired(pSslSocket, authenticator);
});
- connect(pSslSocket, &QSslSocket::alertSent,
+ connect(pSslSocket, &QSslSocket::alertSent, this,
[this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type,
const QString &description) {
Q_EMIT alertSent(pSslSocket, level, type, description);
});
- connect(pSslSocket, &QSslSocket::alertReceived,
+ connect(pSslSocket, &QSslSocket::alertReceived, this,
[this, pSslSocket](QSsl::AlertLevel level, QSsl::AlertType type,
const QString &description) {
Q_EMIT alertReceived(pSslSocket, level, type, description);
});
- connect(pSslSocket, &QSslSocket::handshakeInterruptedOnError,
+ connect(pSslSocket, &QSslSocket::handshakeInterruptedOnError, this,
[this, pSslSocket](const QSslError &error) {
Q_EMIT handshakeInterruptedOnError(pSslSocket, error);
});
- Q_EMIT startedEncryptionHandshake(pSslSocket);
+ d_func()->initializeHandshakeProcess(pSslSocket);
+ }
+}
+
+void QSslServerPrivate::initializeHandshakeProcess(QSslSocket *socket)
+{
+ Q_Q(QSslServer);
+ QMetaObject::Connection readyRead = QObject::connect(
+ socket, &QSslSocket::readyRead, q, [this]() { checkClientHelloAndContinue(); });
+
+ QMetaObject::Connection destroyed =
+ QObject::connect(socket, &QSslSocket::destroyed, q, [this](QObject *obj) {
+ // This cast is not safe to use since the socket is inside the
+ // QObject dtor, but we only use the pointer value!
+ removeSocketData(quintptr(obj));
+ });
+ auto it = socketData.emplace(quintptr(socket), readyRead, destroyed, std::make_shared<QTimer>());
+ it->timeoutTimer->setSingleShot(true);
+ it->timeoutTimer->callOnTimeout(q, [this, socket]() { handleHandshakeTimedOut(socket); });
+ it->timeoutTimer->setInterval(handshakeTimeout);
+ it->timeoutTimer->start();
+}
+
+// This function may be called while in the socket's QObject dtor, __never__ use
+// the socket for anything other than a lookup!
+void QSslServerPrivate::removeSocketData(quintptr socket)
+{
+ auto it = socketData.find(socket);
+ if (it != socketData.end()) {
+ it->disconnectSignals();
+ socketData.erase(it);
+ }
+}
+
+int QSslServerPrivate::totalPendingConnections() const
+{
+ // max pending connections is int, so this cannot exceed that
+ return QTcpServerPrivate::totalPendingConnections() + int(socketData.size());
+}
+
+void QSslServerPrivate::checkClientHelloAndContinue()
+{
+ Q_Q(QSslServer);
+ QSslSocket *socket = qobject_cast<QSslSocket *>(q->sender());
+ if (Q_UNLIKELY(!socket) || socket->bytesAvailable() <= 0)
+ return;
+
+ char byte = '\0';
+ if (socket->peek(&byte, 1) != 1) {
+ socket->deleteLater();
+ return;
+ }
+
+ auto it = socketData.find(quintptr(socket));
+ const bool foundData = it != socketData.end();
+ if (foundData && it->readyReadConnection)
+ QObject::disconnect(std::exchange(it->readyReadConnection, {}));
- pSslSocket->startServerEncryption();
+ constexpr char CLIENT_HELLO = 0x16;
+ if (byte != CLIENT_HELLO) {
+ socket->disconnectFromHost();
+ socket->deleteLater();
+ return;
}
+
+ // Be nice and restart the timeout timer since some progress was made
+ if (foundData)
+ it->timeoutTimer->start();
+
+ socket->startServerEncryption();
+ Q_EMIT q->startedEncryptionHandshake(socket);
+}
+
+void QSslServerPrivate::handleHandshakeTimedOut(QSslSocket *socket)
+{
+ Q_Q(QSslServer);
+ removeSocketData(quintptr(socket));
+ socket->disconnectFromHost();
+ Q_EMIT q->errorOccurred(socket, QAbstractSocket::SocketTimeoutError);
+ socket->deleteLater();
+ if (!socketEngine->isReadNotificationEnabled() && totalPendingConnections() < maxConnections)
+ q->resumeAccepting();
}
QT_END_NAMESPACE
+
+#include "moc_qsslserver.cpp"
diff --git a/src/network/ssl/qsslserver.h b/src/network/ssl/qsslserver.h
index d2f3abc456..aaa0f43c35 100644
--- a/src/network/ssl/qsslserver.h
+++ b/src/network/ssl/qsslserver.h
@@ -33,6 +33,9 @@ public:
void setSslConfiguration(const QSslConfiguration &sslConfiguration);
QSslConfiguration sslConfiguration() const;
+ void setHandshakeTimeout(int timeout);
+ int handshakeTimeout() const;
+
Q_SIGNALS:
void sslErrors(QSslSocket *socket, const QList<QSslError> &errors);
void peerVerifyError(QSslSocket *socket, const QSslError &error);
diff --git a/src/network/ssl/qsslserver_p.h b/src/network/ssl/qsslserver_p.h
index b4b6490ed4..1b90d35d48 100644
--- a/src/network/ssl/qsslserver_p.h
+++ b/src/network/ssl/qsslserver_p.h
@@ -16,19 +16,53 @@
// We mean it.
//
+#include <QtNetwork/private/qtnetworkglobal_p.h>
+
+#include <QtCore/qhash.h>
+#include <QtCore/qtimer.h>
+
#include <QtNetwork/QSslConfiguration>
#include <QtNetwork/private/qtcpserver_p.h>
+#include <utility>
QT_BEGIN_NAMESPACE
class Q_NETWORK_EXPORT QSslServerPrivate : public QTcpServerPrivate
{
+ static constexpr int DefaultHandshakeTimeout = 5'000; // 5 seconds
public:
Q_DECLARE_PUBLIC(QSslServer)
QSslServerPrivate();
+ void checkClientHelloAndContinue();
+ void initializeHandshakeProcess(QSslSocket *socket);
+ void removeSocketData(quintptr socket);
+ void handleHandshakeTimedOut(QSslSocket *socket);
+ int totalPendingConnections() const override;
+
+ struct SocketData {
+ QMetaObject::Connection readyReadConnection;
+ QMetaObject::Connection destroyedConnection;
+ std::shared_ptr<QTimer> timeoutTimer; // shared_ptr because QHash demands copying
+
+ SocketData(QMetaObject::Connection readyRead, QMetaObject::Connection destroyed,
+ std::shared_ptr<QTimer> &&timer)
+ : readyReadConnection(readyRead),
+ destroyedConnection(destroyed),
+ timeoutTimer(std::move(timer))
+ {
+ }
+
+ void disconnectSignals()
+ {
+ QObject::disconnect(std::exchange(readyReadConnection, {}));
+ QObject::disconnect(std::exchange(destroyedConnection, {}));
+ }
+ };
+ QHash<quintptr, SocketData> socketData;
QSslConfiguration sslConfiguration;
+ int handshakeTimeout = DefaultHandshakeTimeout;
};
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index cd76517c25..395394d432 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -97,8 +97,7 @@
\list
\li The socket's cryptographic cipher suite can be customized before
- the handshake phase with QSslConfiguration::setCiphers()
- and QSslConfiguration::setDefaultCiphers().
+ the handshake phase with QSslConfiguration::setCiphers().
\li The socket's local certificate and private key can be customized
before the handshake phase with setLocalCertificate() and
setPrivateKey().
@@ -365,6 +364,12 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
+#ifdef Q_OS_VXWORKS
+constexpr auto isVxworks = true;
+#else
+constexpr auto isVxworks = false;
+#endif
+
class QSslSocketGlobalData
{
public:
@@ -1539,7 +1544,12 @@ QList<QString> QSslSocket::availableBackends()
from the list of available backends.
\note When selecting a default backend implicitly, QSslSocket prefers
- the OpenSSL backend if available.
+ the OpenSSL backend if available. If it's not available, the Schannel backend
+ is implicitly selected on Windows, and Secure Transport on Darwin platforms.
+ Failing these, if a custom TLS backend is found, it is used.
+ If no other backend is found, the "certificate only" backend is selected.
+ For more information about TLS plugins, please see
+ \l {Enabling and Disabling SSL Support when Building Qt from Source}.
\sa setActiveBackend(), availableBackends()
*/
@@ -1973,6 +1983,10 @@ QSslSocketPrivate::QSslSocketPrivate()
, flushTriggered(false)
{
QSslConfigurationPrivate::deepCopyDefaultConfiguration(&configuration);
+ // If the global configuration doesn't allow root certificates to be loaded
+ // on demand then we have to disable it for this socket as well.
+ if (!configuration.allowRootCertOnDemandLoading)
+ allowRootCertOnDemandLoading = false;
const auto *tlsBackend = tlsBackendInUse();
if (!tlsBackend) {
@@ -2281,6 +2295,7 @@ void QSslConfigurationPrivate::deepCopyDefaultConfiguration(QSslConfigurationPri
ptr->sessionProtocol = global->sessionProtocol;
ptr->ciphers = global->ciphers;
ptr->caCertificates = global->caCertificates;
+ ptr->allowRootCertOnDemandLoading = global->allowRootCertOnDemandLoading;
ptr->protocol = global->protocol;
ptr->peerVerifyMode = global->peerVerifyMode;
ptr->peerVerifyDepth = global->peerVerifyDepth;
@@ -2661,7 +2676,7 @@ bool QSslSocketPrivate::verifyErrorsHaveBeenIgnored()
// was called)
const auto &sslErrors = backend->tlsErrors();
doEmitSslError = false;
- for (int a = 0; a < sslErrors.count(); a++) {
+ for (int a = 0; a < sslErrors.size(); a++) {
if (!ignoreErrorsList.contains(sslErrors.at(a))) {
doEmitSslError = true;
break;
@@ -2799,11 +2814,11 @@ QByteArray QSslSocketPrivate::peek(qint64 maxSize)
QByteArray ret;
ret.reserve(maxSize);
ret.resize(buffer.peek(ret.data(), maxSize, transactionPos));
- if (ret.length() == maxSize)
+ if (ret.size() == maxSize)
return ret;
//peek at data in the plain socket
if (plainSocket)
- return ret + plainSocket->peek(maxSize - ret.length());
+ return ret + plainSocket->peek(maxSize - ret.size());
return QByteArray();
} else {
@@ -2955,7 +2970,13 @@ QList<QByteArray> QSslSocketPrivate::unixRootCertDirectories()
ba("/opt/openssl/certs/"), // HP-UX
ba("/etc/ssl/"), // OpenBSD
};
- return QList<QByteArray>::fromReadOnlyData(dirs);
+ QList<QByteArray> result = QList<QByteArray>::fromReadOnlyData(dirs);
+ if constexpr (isVxworks) {
+ static QByteArray vxworksCertsDir = qgetenv("VXWORKS_CERTS_DIR");
+ if (!vxworksCertsDir.isEmpty())
+ result.push_back(vxworksCertsDir);
+ }
+ return result;
}
/*!
@@ -3031,7 +3052,7 @@ bool QSslSocketPrivate::isMatchingHostname(const QString &cn, const QString &hos
qsizetype secondCnDot = cn.indexOf(u'.', firstCnDot+1);
// Check at least 3 components
- if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.length()))
+ if ((-1 == secondCnDot) || (secondCnDot+1 >= cn.size()))
return false;
// Check * is last character of 1st component (ie. there's a following .)
@@ -3086,10 +3107,11 @@ QTlsBackend *QSslSocketPrivate::tlsBackendInUse()
tlsBackend = QTlsBackend::findBackend(activeBackendName);
if (tlsBackend) {
- QObject::connect(tlsBackend, &QObject::destroyed, [] {
+ QObject::connect(tlsBackend, &QObject::destroyed, tlsBackend, [] {
const QMutexLocker locker(&backendMutex);
tlsBackend = nullptr;
- });
+ },
+ Qt::DirectConnection);
}
return tlsBackend;
}
diff --git a/src/network/ssl/qsslsocket.h b/src/network/ssl/qsslsocket.h
index 3174a68953..3ed1bc45cc 100644
--- a/src/network/ssl/qsslsocket.h
+++ b/src/network/ssl/qsslsocket.h
@@ -35,6 +35,7 @@ public:
SslClientMode,
SslServerMode
};
+ Q_ENUM(SslMode)
enum PeerVerifyMode {
VerifyNone,
@@ -42,6 +43,7 @@ public:
VerifyPeer,
AutoVerifyPeer
};
+ Q_ENUM(PeerVerifyMode)
explicit QSslSocket(QObject *parent = nullptr);
~QSslSocket();
diff --git a/src/network/ssl/qtlsbackend.cpp b/src/network/ssl/qtlsbackend.cpp
index bc5b492d0f..761ab33fbe 100644
--- a/src/network/ssl/qtlsbackend.cpp
+++ b/src/network/ssl/qtlsbackend.cpp
@@ -27,7 +27,7 @@ QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
-Q_APPLICATION_STATIC(QFactoryLoader, loader, QTlsBackend_iid,
+Q_APPLICATION_STATIC(QFactoryLoader, qtlsbLoader, QTlsBackend_iid,
QStringLiteral("/tls"))
namespace {
@@ -54,7 +54,7 @@ public:
bool tryPopulateCollection()
{
- if (!loader())
+ if (!qtlsbLoader())
return false;
Q_CONSTINIT static QBasicMutex mutex;
@@ -63,10 +63,10 @@ public:
return true;
#if QT_CONFIG(library)
- loader->update();
+ qtlsbLoader->update();
#endif
int index = 0;
- while (loader->instance(index))
+ while (qtlsbLoader->instance(index))
++index;
return true;
@@ -889,20 +889,28 @@ QSslCipher QTlsBackend::createCiphersuite(const QString &suiteName, QSsl::SslPro
/*!
\internal
- Auxiliary function. Creates a new QSslCipher from \a name (which is an implementation-specific
- string), \a protocol and \a protocolString, e.g.:
+ Auxiliary function. Creates a new QSslCipher from \a name, \a keyExchangeMethod, \a encryptionMethod,
+ \a authenticationMethod, \a bits, \a protocol version and \a protocolString.
+ For example:
\code
- createCipher(QStringLiteral("schannel"), QSsl::TlsV1_2, "TLSv1.2"_L1);
+ createCiphersuite("ECDHE-RSA-AES256-GCM-SHA256"_L1, "ECDH"_L1, "AES"_L1, "RSA"_L1, 256,
+ QSsl::TlsV1_2, "TLSv1.2"_L1);
\endcode
*/
-QSslCipher QTlsBackend::createCipher(const QString &name, QSsl::SslProtocol protocol,
- const QString &protocolString)
+QSslCipher QTlsBackend::createCiphersuite(const QString &name, const QString &keyExchangeMethod,
+ const QString &encryptionMethod,
+ const QString &authenticationMethod,
+ int bits, QSsl::SslProtocol protocol,
+ const QString &protocolString)
{
- // Note the name 'createCipher' (not 'ciphersuite'): we don't provide
- // information about Kx, Au, bits/supported etc.
QSslCipher cipher;
cipher.d->isNull = false;
cipher.d->name = name;
+ cipher.d->bits = bits;
+ cipher.d->supportedBits = bits;
+ cipher.d->keyExchangeMethod = keyExchangeMethod;
+ cipher.d->encryptionMethod = encryptionMethod;
+ cipher.d->authenticationMethod = authenticationMethod;
cipher.d->protocol = protocol;
cipher.d->protocolString = protocolString;
return cipher;
@@ -1382,8 +1390,7 @@ QByteArray TlsKey::pemHeader() const
else if (algorithm() == QSsl::Dh)
return QByteArrayLiteral("-----BEGIN PRIVATE KEY-----");
- Q_UNREACHABLE();
- return {};
+ Q_UNREACHABLE_RETURN({});
}
/*!
@@ -1404,8 +1411,7 @@ QByteArray TlsKey::pemFooter() const
else if (algorithm() == QSsl::Dh)
return QByteArrayLiteral("-----END PRIVATE KEY-----");
- Q_UNREACHABLE();
- return {};
+ Q_UNREACHABLE_RETURN({});
}
/*!
diff --git a/src/network/ssl/qtlsbackend_p.h b/src/network/ssl/qtlsbackend_p.h
index c69e641854..090531014b 100644
--- a/src/network/ssl/qtlsbackend_p.h
+++ b/src/network/ssl/qtlsbackend_p.h
@@ -31,7 +31,6 @@
#include <QtNetwork/qssl.h>
#include <QtCore/qloggingcategory.h>
-#include <QtCore/qsharedpointer.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qobject.h>
#include <QtCore/qglobal.h>
@@ -58,7 +57,7 @@ class QSslKey;
namespace QTlsPrivate {
-class Q_NETWORK_PRIVATE_EXPORT TlsKey {
+class Q_NETWORK_EXPORT TlsKey {
public:
virtual ~TlsKey();
@@ -95,7 +94,7 @@ public:
QByteArray pemFooter() const;
};
-class Q_NETWORK_PRIVATE_EXPORT X509Certificate
+class Q_NETWORK_EXPORT X509Certificate
{
public:
virtual ~X509Certificate();
@@ -152,7 +151,7 @@ using X509Pkcs12ReaderPtr = bool (*)(QIODevice *device, QSslKey *key, QSslCertif
#if QT_CONFIG(ssl)
// TLS over TCP. Handshake, encryption/decryption.
-class Q_NETWORK_PRIVATE_EXPORT TlsCryptograph : public QObject
+class Q_NETWORK_EXPORT TlsCryptograph : public QObject
{
public:
virtual ~TlsCryptograph();
@@ -188,7 +187,7 @@ class TlsCryptograph;
#if QT_CONFIG(dtls)
-class Q_NETWORK_PRIVATE_EXPORT DtlsBase
+class Q_NETWORK_EXPORT DtlsBase
{
public:
virtual ~DtlsBase();
@@ -218,7 +217,7 @@ public:
};
// TLS over UDP. Handshake, encryption/decryption.
-class Q_NETWORK_PRIVATE_EXPORT DtlsCryptograph : virtual public DtlsBase
+class Q_NETWORK_EXPORT DtlsCryptograph : virtual public DtlsBase
{
public:
@@ -347,8 +346,11 @@ public:
static QSslCipher createCiphersuite(const QString &description, int bits, int supportedBits);
static QSslCipher createCiphersuite(const QString &suiteName, QSsl::SslProtocol protocol,
const QString &protocolString);
- static QSslCipher createCipher(const QString &name, QSsl::SslProtocol protocol,
- const QString &protocolString);
+ static QSslCipher createCiphersuite(const QString &name, const QString &keyExchangeMethod,
+ const QString &encryptionMethod,
+ const QString &authenticationMethod,
+ int bits, QSsl::SslProtocol protocol,
+ const QString &protocolString);
// Those statics are implemented using QSslSocketPrivate (which is not exported,
// unlike QTlsBackend).