summaryrefslogtreecommitdiffstats
path: root/src/network/ssl/qsslkey_qt.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/ssl/qsslkey_qt.cpp')
-rw-r--r--src/network/ssl/qsslkey_qt.cpp50
1 files changed, 49 insertions, 1 deletions
diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp
index 5ebd8ac3bd..43969c3d28 100644
--- a/src/network/ssl/qsslkey_qt.cpp
+++ b/src/network/ssl/qsslkey_qt.cpp
@@ -48,6 +48,8 @@
#include <QtNetwork/qpassworddigestor.h>
+#include <cstring>
+
QT_USE_NAMESPACE
static const quint8 bits_table[256] = {
@@ -124,6 +126,37 @@ static int numberOfBits(const QByteArray &modulus)
return bits;
}
+static QByteArray deriveAesKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, const QByteArray &iv)
+{
+ // This is somewhat simplified and shortened version of what OpenSSL does.
+ // See, for example, EVP_BytesToKey for the "algorithm" itself and elsewhere
+ // in their code for what they pass as arguments to EVP_BytesToKey when
+ // deriving encryption keys (when reading/writing pems files with encrypted
+ // keys).
+
+ Q_ASSERT(iv.size() >= 8);
+
+ QCryptographicHash hash(QCryptographicHash::Md5);
+
+ QByteArray data(passPhrase);
+ data.append(iv.data(), 8); // AKA PKCS5_SALT_LEN in OpenSSL.
+
+ hash.addData(data);
+
+ if (cipher == QSslKeyPrivate::Aes128Cbc)
+ return hash.result();
+
+ QByteArray key(hash.result());
+ hash.reset();
+ hash.addData(key);
+ hash.addData(data);
+
+ if (cipher == QSslKeyPrivate::Aes192Cbc)
+ return key.append(hash.result().constData(), 8);
+
+ return key.append(hash.result());
+}
+
static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &passPhrase, const QByteArray &iv)
{
QByteArray key;
@@ -145,14 +178,19 @@ static QByteArray deriveKey(QSslKeyPrivate::Cipher cipher, const QByteArray &pas
case QSslKeyPrivate::Rc2Cbc:
key = hash.result();
break;
+ case QSslKeyPrivate::Aes128Cbc:
+ case QSslKeyPrivate::Aes192Cbc:
+ case QSslKeyPrivate::Aes256Cbc:
+ return deriveAesKey(cipher, passPhrase, iv);
}
return key;
}
void QSslKeyPrivate::clear(bool deep)
{
- Q_UNUSED(deep);
isNull = true;
+ if (deep)
+ std::memset(derData.data(), 0, derData.size());
derData.clear();
keyLength = -1;
}
@@ -378,6 +416,12 @@ void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhra
cipher = DesEde3Cbc;
} else if (dekInfo.first() == "RC2-CBC") {
cipher = Rc2Cbc;
+ } else if (dekInfo.first() == "AES-128-CBC") {
+ cipher = Aes128Cbc;
+ } else if (dekInfo.first() == "AES-192-CBC") {
+ cipher = Aes192Cbc;
+ } else if (dekInfo.first() == "AES-256-CBC") {
+ cipher = Aes256Cbc;
} else {
clear(deepClear);
return;
@@ -554,6 +598,10 @@ static EncryptionData readPbes2(const QVector<QAsn1Element> &element, const QByt
return {};
break;
} // @todo(?): case (RC5 , AES)
+ case QSslKeyPrivate::Cipher::Aes128Cbc:
+ case QSslKeyPrivate::Cipher::Aes192Cbc:
+ case QSslKeyPrivate::Cipher::Aes256Cbc:
+ Q_UNREACHABLE();
}
if (Q_LIKELY(keyDerivationAlgorithm == PKCS5_PBKDF2_ENCRYPTION_OID)) {