QSslSocket (SecureTransport) add TLS 1.3 ciphersuites

At some point we decided to support a custom set of ciphersuites specified
by QSslConfiguration (which if you ask me was never a good idea). The law
of unforseen consequiences bit us again: since we now give a set of ciphesuites
to QSslConfiguration and set ciphesuites from the configuration a socket has,
we are limited by the ciphersuites we know about at the moment of 'coding'.
Meaning if an SDK was updated and CipherSuite.h later adds more ciphersuites,
we miss them and 'don't support them', while we ... actually do.

This patch tries to add some more ciphersuites introduced in TLS 1.3 (interesting,
SecureTransport does not support TLS 1.3, but TLS 1.3 suites can be used in TLS
1.2 session).

Pick-to: 6.2 6.3 5.15
Task-number: QTBUG-99368
Change-Id: I439b63845c4893e5621cffaf3bcaf62e2b643c74
Reviewed-by: Mårten Nordheim <marten.nordheim@qt.io>
This commit is contained in:
Timur Pocheptsov 2021-12-23 14:17:13 +01:00
parent eabb3fd2f0
commit c30af31f99
4 changed files with 121 additions and 0 deletions

View File

@ -902,6 +902,10 @@ QSslCipher QTlsBackend::createCiphersuite(const QString &suiteName, QSsl::SslPro
ciph.d->encryptionMethod = QLatin1String("AES(256)");
ciph.d->bits = 256;
ciph.d->supportedBits = 256;
} else if (ciph.d->name.contains(QLatin1String("CHACHA20-"))) {
ciph.d->encryptionMethod = QLatin1String("CHACHA20");
ciph.d->bits = 256;
ciph.d->supportedBits = 256;
} else if (ciph.d->name.contains(QLatin1String("NULL-"))) {
ciph.d->encryptionMethod = QLatin1String("NULL");
} else {

View File

@ -649,6 +649,35 @@ SSLCipherSuite TlsCryptographSecureTransport::SSLCipherSuite_from_QSslCipher(con
return TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256;
if (ciph.name() == QLatin1String("ECDHE-RSA-AES256-GCM-SHA384"))
return TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384;
if (ciph.name() == QLatin1String("AES128-GCM-SHA256"))
return TLS_AES_128_GCM_SHA256;
if (ciph.name() == QLatin1String("AES256-GCM-SHA384"))
return TLS_AES_256_GCM_SHA384;
if (ciph.name() == QLatin1String("CHACHA20-POLY1305-SHA256"))
return TLS_CHACHA20_POLY1305_SHA256;
if (ciph.name() == QLatin1String("AES128-CCM-SHA256"))
return TLS_AES_128_CCM_SHA256;
if (ciph.name() == QLatin1String("AES128-CCM8-SHA256"))
return TLS_AES_128_CCM_8_SHA256;
if (ciph.name() == QLatin1String("ECDHE-ECDSA-AES128-GCM-SHA256"))
return TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256;
if (ciph.name() == QLatin1String("ECDHE-ECDSA-AES256-GCM-SHA384"))
return TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384;
if (ciph.name() == QLatin1String("ECDH-ECDSA-AES128-GCM-SHA256"))
return TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256;
if (ciph.name() == QLatin1String("ECDH-ECDSA-AES256-GCM-SHA384"))
return TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384;
if (ciph.name() == QLatin1String("ECDHE-RSA-AES128-GCM-SHA256"))
return TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256;
if (ciph.name() == QLatin1String("ECDH-RSA-AES128-GCM-SHA256"))
return TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256;
if (ciph.name() == QLatin1String("ECDH-RSA-AES256-GCM-SHA384"))
return TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384;
if (ciph.name() == QLatin1String("ECDHE-RSA-CHACHA20-POLY1305-SHA256"))
return TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256;
if (ciph.name() == QLatin1String("ECDHE-ECDSA-CHACHA20-POLY1305-SHA256"))
return TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256;
return 0;
}

View File

@ -204,6 +204,55 @@ QSslCipher QSslCipher_from_SSLCipherSuite(SSLCipherSuite cipher)
name = QLatin1String("ECDHE-RSA-AES256-GCM-SHA384");
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 = QLatin1String("AES128-GCM-SHA256");
break;
case TLS_AES_256_GCM_SHA384:
name = QLatin1String("AES256-GCM-SHA384");
break;
case TLS_CHACHA20_POLY1305_SHA256:
name = QLatin1String("CHACHA20-POLY1305-SHA256");
break;
case TLS_AES_128_CCM_SHA256:
name = QLatin1String("AES128-CCM-SHA256");
break;
case TLS_AES_128_CCM_8_SHA256:
name = QLatin1String("AES128-CCM8-SHA256");
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 = QLatin1String("ECDHE-ECDSA-AES128-GCM-SHA256");
break;
case TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384:
name = QLatin1String("ECDHE-ECDSA-AES256-GCM-SHA384");
break;
case TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256:
name = QLatin1String("ECDH-ECDSA-AES128-GCM-SHA256");
break;
case TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384:
name = QLatin1String("ECDH-ECDSA-AES256-GCM-SHA384");
break;
case TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256:
name = QLatin1String("ECDHE-RSA-AES128-GCM-SHA256");
break;
case TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256:
name = QLatin1String("ECDH-RSA-AES128-GCM-SHA256");
break;
case TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384:
name = QLatin1String("ECDH-RSA-AES256-GCM-SHA384");
break;
// Addenda from rfc 7905 ChaCha20-Poly1305 Cipher Suites for
// Transport Layer Security (TLS).
case TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256:
name = QLatin1String("ECDHE-RSA-CHACHA20-POLY1305-SHA256");
break;
case TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256:
name = QLatin1String("ECDHE-ECDSA-CHACHA20-POLY1305-SHA256");
break;
default:
return {};
}

View File

@ -155,6 +155,9 @@ private slots:
void sslErrors_data();
void sslErrors();
void ciphers();
#if QT_CONFIG(securetransport)
void tls13Ciphers();
#endif // QT_CONFIG(securetransport)
void connectToHostEncrypted();
void connectToHostEncryptedWithVerificationPeerName();
void sessionCipher();
@ -1063,6 +1066,42 @@ void tst_QSslSocket::ciphers()
}
}
#if QT_CONFIG(securetransport)
void tst_QSslSocket::tls13Ciphers()
{
// SecureTransport introduced several new ciphers under
// "TLS 1.3 ciphersuites" section. Since Qt 6 we respect
// the ciphers from QSslConfiguration. In case of default
// configuration, these are the same we report and we
// were failing (for historical reasons) to report those
// TLS 1.3 suites when creating default QSslConfiguration.
// Check we now have them.
if (!isTestingSecureTransport)
QSKIP("The feature 'securetransport' was enabled, but active backend is not \"securetransport\"");
QFETCH_GLOBAL(const bool, setProxy);
if (setProxy)
return;
const auto suites = QSslConfiguration::defaultConfiguration().ciphers();
QSslCipher ciph;
// Check the one of reported and previously missed:
for (const auto &suite : suites) {
if (suite.encryptionMethod() == QStringLiteral("CHACHA20")) {
// There are several ciphesuites using CHACHA20, the first one
// is sufficient for the purpose of this test:
ciph = suite;
break;
}
}
QVERIFY(!ciph.isNull());
QCOMPARE(ciph.encryptionMethod(), QStringLiteral("CHACHA20"));
QCOMPARE(ciph.supportedBits(), 256);
QCOMPARE(ciph.usedBits(), 256);
}
#endif // QT_CONFIG(securetransport)
void tst_QSslSocket::connectToHostEncrypted()
{
if (!QSslSocket::supportsSsl())