Ensure weak ciphers are not part of the default SSL configuration.

Any cipher that is < 128 bits is excluded from the default SSL
configuration. These ciphers are still included in the list
of availableCiphers() and can be used by applications if required.
Calling QSslSocket::setDefaultCiphers(QSslSocket::availableCiphers())
will restore the old behavior.

Note that in doing so I spotted that calling defaultCiphers() before
doing other actions with SSL had an existing bug that I've addressed
as part of the change.

[ChangeLog][Important Behavior Changes] The default set of
ciphers used by QSslSocket has been changed to exclude ciphers that are
using key lengths smaller than 128 bits. These ciphers are still available
and can be enabled by applications if required.

Change-Id: If2241dda67b624e5febf788efa1369f38c6b1dba
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Richard J. Moore 2014-01-17 21:23:20 +00:00 committed by The Qt Project
parent f81de3944d
commit 5c19fad8c1
4 changed files with 24 additions and 7 deletions

View File

@ -663,7 +663,7 @@ int QSslConfiguration::sessionTicketLifeTimeHint() const
\li protocol SecureProtocols (meaning either TLS 1.0 or SSL 3 will be used)
\li the system's default CA certificate list
\li the cipher list equal to the list of the SSL libraries'
supported SSL ciphers
supported SSL ciphers that are 128 bits or more
\endlist
\sa QSslSocket::supportedCiphers(), setDefaultConfiguration()

View File

@ -1953,6 +1953,7 @@ void QSslSocketPrivate::init()
*/
QList<QSslCipher> QSslSocketPrivate::defaultCiphers()
{
QSslSocketPrivate::ensureInitialized();
QMutexLocker locker(&globalData()->mutex);
return globalData()->config->ciphers;
}

View File

@ -596,6 +596,7 @@ void QSslSocketPrivate::resetDefaultCiphers()
SSL *mySsl = q_SSL_new(myCtx);
QList<QSslCipher> ciphers;
QList<QSslCipher> defaultCiphers;
STACK_OF(SSL_CIPHER) *supportedCiphers = q_SSL_get_ciphers(mySsl);
for (int i = 0; i < q_sk_SSL_CIPHER_num(supportedCiphers); ++i) {
@ -603,8 +604,11 @@ void QSslSocketPrivate::resetDefaultCiphers()
if (cipher->valid) {
QSslCipher ciph = QSslSocketBackendPrivate::QSslCipher_from_SSL_CIPHER(cipher);
if (!ciph.isNull()) {
// Unconditionally exclude ADH ciphers since they offer no MITM protection
if (!ciph.name().toLower().startsWith(QLatin1String("adh")))
ciphers << ciph;
if (ciph.usedBits() >= 128)
defaultCiphers << ciph;
}
}
}
@ -614,7 +618,7 @@ void QSslSocketPrivate::resetDefaultCiphers()
q_SSL_free(mySsl);
setDefaultSupportedCiphers(ciphers);
setDefaultCiphers(ciphers);
setDefaultCiphers(defaultCiphers);
}
QList<QSslCertificate> QSslSocketPrivate::systemCaCertificates()

View File

@ -589,13 +589,13 @@ void tst_QSslSocket::ciphers()
return;
QSslSocket socket;
QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
socket.setCiphers(QList<QSslCipher>());
QVERIFY(socket.ciphers().isEmpty());
socket.setCiphers(socket.defaultCiphers());
QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
socket.setCiphers(socket.defaultCiphers());
QCOMPARE(socket.ciphers(), QSslSocket::supportedCiphers());
QCOMPARE(socket.ciphers(), QSslSocket::defaultCiphers());
// Task 164356
socket.setCiphers("ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
@ -678,6 +678,11 @@ void tst_QSslSocket::sessionCipher()
if (!socket->waitForEncrypted(5000))
QSKIP("Skipping flaky test - See QTBUG-29941");
QVERIFY(!socket->sessionCipher().isNull());
qDebug() << "Supported Ciphers:" << QSslSocket::supportedCiphers();
qDebug() << "Default Ciphers:" << QSslSocket::defaultCiphers();
qDebug() << "Session Cipher:" << socket->sessionCipher();
QVERIFY(QSslSocket::supportedCiphers().contains(socket->sessionCipher()));
socket->disconnectFromHost();
QVERIFY(socket->waitForDisconnected());
@ -1386,6 +1391,15 @@ void tst_QSslSocket::defaultCaCertificates()
void tst_QSslSocket::defaultCiphers()
{
if (!QSslSocket::supportsSsl())
return;
QList<QSslCipher> ciphers = QSslSocket::defaultCiphers();
QVERIFY(ciphers.size() > 1);
QSslSocket socket;
QCOMPARE(socket.defaultCiphers(), ciphers);
QCOMPARE(socket.ciphers(), ciphers);
}
void tst_QSslSocket::resetDefaultCiphers()
@ -1410,8 +1424,6 @@ void tst_QSslSocket::supportedCiphers()
QSslSocket socket;
QCOMPARE(socket.supportedCiphers(), ciphers);
QCOMPARE(socket.defaultCiphers(), ciphers);
QCOMPARE(socket.ciphers(), ciphers);
}
void tst_QSslSocket::systemCaCertificates()