This functionality is controlled by a feature flag so that clients
supporting EC keys won't try to set an EC key on a core that
doesn't. As with the previous EC patch, this requires Qt 5.5 to
work but uses the QT_VERSION macro to remain compileable with Qt4.
This patch also fixes the QSsl::KeyAlgorithm indices to be correct
for both Qt4 and Qt5. In Qt4, RSA was 0 and DSA was 1, but in Qt5
0 became Opaque, 1 because RSA, and two became DSA. EC is 3 and
wasn't added until 5.5. The new macro handles all three versions
correctly. (See https://doc.qt.io/qt-5/qssl.html#KeyAlgorithm-enum
and https://doc.qt.io/archives/qt-4.8/qssl.html#KeyAlgorithm-enum.)
Thanks to @justJanne for pointing out this discrepancy.
Closes GH-347.
void ClientCertManager::setSslKey(const QByteArray &encoded)
{
QSslKey key(encoded, QSsl::Rsa);
void ClientCertManager::setSslKey(const QByteArray &encoded)
{
QSslKey key(encoded, QSsl::Rsa);
+#if QT_VERSION >= 0x050500
+ if (key.isNull() && Client::isCoreFeatureEnabled(Quassel::Feature::EcdsaCertfpKeys))
+ key = QSslKey(encoded, QSsl::Ec);
+#endif
if (key.isNull())
key = QSslKey(encoded, QSsl::Dsa);
_certIdentity->setSslKey(key);
if (key.isNull())
key = QSslKey(encoded, QSsl::Dsa);
_certIdentity->setSslKey(key);
SenderPrefixes, ///< Show prefixes for senders in backlog
RemoteDisconnect, ///< Allow this peer to be remotely disconnected
ExtendedFeatures, ///< Extended features
SenderPrefixes, ///< Show prefixes for senders in backlog
RemoteDisconnect, ///< Allow this peer to be remotely disconnected
ExtendedFeatures, ///< Extended features
+#if QT_VERSION >= 0x050500
+ EcdsaCertfpKeys, ///< ECDSA keys for CertFP in identities
+#endif
void CoreIdentity::setSslKey(const QByteArray &encoded)
{
QSslKey key(encoded, QSsl::Rsa);
void CoreIdentity::setSslKey(const QByteArray &encoded)
{
QSslKey key(encoded, QSsl::Rsa);
+#if QT_VERSION >= 0x050500
+ if (key.isNull())
+ key = QSslKey(encoded, QSsl::Ec);
+#endif
if (key.isNull())
key = QSslKey(encoded, QSsl::Dsa);
setSslKey(key);
if (key.isNull())
key = QSslKey(encoded, QSsl::Dsa);
setSslKey(key);
keyFile.close();
for (int i = 0; i < 2; i++) {
keyFile.close();
for (int i = 0; i < 2; i++) {
+#if QT_VERSION >= 0x050500
+ // On Qt5.5+, support QSsl::KeyAlgorithm::Rsa (1), QSsl::KeyAlgorithm::Dsa (2), and QSsl::KeyAlgorithm::Ec (3)
+ for (int j = 1; j < 4; j++) {
+#elif QT_VERSION >= 0x050000
+ // On Qt5.0-Qt5.4, support QSsl::KeyAlgorithm::Rsa (1) and QSsl::KeyAlgorithm::Dsa (2) (Ec wasn't added until 5.5)
+ for (int j = 1; j < 3; j++) {
+#else
+ // On Qt4, support QSsl::KeyAlgorithm::Rsa (0) and QSsl::KeyAlgorithm::Dsa (1) (Qt4 uses different indices for the values)
for (int j = 0; j < 2; j++) {
for (int j = 0; j < 2; j++) {
key = QSslKey(keyRaw, (QSsl::KeyAlgorithm)j, (QSsl::EncodingFormat)i);
if (!key.isNull())
goto returnKey;
key = QSslKey(keyRaw, (QSsl::KeyAlgorithm)j, (QSsl::EncodingFormat)i);
if (!key.isNull())
goto returnKey;
}
QMessageBox::information(this, tr("Failed to read key"), tr("Failed to read the key file. It is either incompatible or invalid. Note that the key file must not have a passphrase."));
returnKey:
}
QMessageBox::information(this, tr("Failed to read key"), tr("Failed to read the key file. It is either incompatible or invalid. Note that the key file must not have a passphrase."));
returnKey:
+#if QT_VERSION >= 0x050500
+ if(!key.isNull() && key.algorithm() == QSsl::KeyAlgorithm::Ec && !Client::isCoreFeatureEnabled(Quassel::Feature::EcdsaCertfpKeys)) {
+ QMessageBox::information(this, tr("Core does not support ECDSA keys"), tr("You loaded an ECDSA key, but the core does not support ECDSA keys. Please contact the core administrator."));
+ key.clear();
+ }
+#endif
case QSsl::Rsa:
ui.keyTypeLabel->setText(tr("RSA"));
break;
case QSsl::Rsa:
ui.keyTypeLabel->setText(tr("RSA"));
break;
+#if QT_VERSION >= 0x050500
+ case QSsl::Ec:
+ ui.keyTypeLabel->setText(tr("ECDSA"));
+ break;
+#endif
case QSsl::Dsa:
ui.keyTypeLabel->setText(tr("DSA"));
break;
default:
case QSsl::Dsa:
ui.keyTypeLabel->setText(tr("DSA"));
break;
default:
- ui.keyTypeLabel->setText(tr("No Key loaded"));
+ ui.keyTypeLabel->setText(tr("Invalid key or no key loaded"));
}
ui.clearOrLoadKeyButton->setText(tr("Clear"));
}
}
ui.clearOrLoadKeyButton->setText(tr("Clear"));
}