8#include <QtNetwork/private/qsslkey_p.h>
10#include <QtNetwork/qpassworddigestor.h>
12#include <QtCore/QMessageAuthenticationCode>
13#include <QtCore/qcryptographichash.h>
14#include <QtCore/qrandom.h>
16#include <QtCore/qdatastream.h>
17#include <QtCore/qbytearray.h>
18#include <QtCore/qdebug.h>
19#include <QtCore/qmap.h>
34const quint8 bits_table[256] = {
35 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,
36 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
37 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
38 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
39 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
40 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
41 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
42 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
43 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
44 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
45 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
46 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
47 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
48 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
49 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
50 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
110 EncryptionData() =
default;
113 : initialized(
true), cipher(cipher),
key(
key), iv(iv)
116 bool initialized =
false;
152 {QSslKeyPrivate::Cipher::DesCbc, 8},
153 {QSslKeyPrivate::Cipher::DesEde3Cbc, 24},
155 {QSslKeyPrivate::Cipher::Rc2Cbc, 4}
160 if (keyDerivationContainer.
size() != 2
166 const QByteArray keyDerivationAlgorithm = keyDerivationContainer[0].toObjectId();
167 const auto keyDerivationParams = keyDerivationContainer[1].
toList();
169 const auto encryptionAlgorithmContainer = element[1].
toList();
170 if (encryptionAlgorithmContainer.size() != 2
175 auto iterator = oidCipherMap.constFind(encryptionAlgorithmContainer[0].toObjectId());
176 if (iterator == oidCipherMap.cend()) {
178 <<
"QSslKey: Unsupported encryption cipher OID:" << encryptionAlgorithmContainer[0].toObjectId()
179 <<
"\nFile a bug report to Qt (include the line above).";
187 case QSslKeyPrivate::Cipher::DesCbc:
188 case QSslKeyPrivate::Cipher::DesEde3Cbc:
199 iv = encryptionAlgorithmContainer[1].value();
204 case QSslKeyPrivate::Cipher::Rc2Cbc: {
213 const auto rc2ParametersContainer = encryptionAlgorithmContainer[1].toList();
214 if ((rc2ParametersContainer.size() != 1 && rc2ParametersContainer.size() != 2)
218 iv = rc2ParametersContainer.
back().value();
223 case QSslKeyPrivate::Cipher::Aes128Cbc:
224 case QSslKeyPrivate::Cipher::Aes192Cbc:
225 case QSslKeyPrivate::Cipher::Aes256Cbc:
233 salt = keyDerivationParams[0].value();
245 int iterationCount = keyDerivationParams[1].toInteger();
249 if (keyDerivationParams.size() > vectorPos
251 keyLength = keyDerivationParams[vectorPos].toInteger(
nullptr);
254 keyLength = cipherKeyLengthMap[cipher];
259 if (keyDerivationParams.size() > vectorPos
261 const auto hashAlgorithmContainer = keyDerivationParams[vectorPos].toList();
262 hashAlgorithm = pbes2OidHashFunctionMap[hashAlgorithmContainer.front().toObjectId()];
266 Q_ASSERT(keyDerivationParams.size() == vectorPos);
271 <<
"QSslKey: Unsupported key derivation algorithm OID:" << keyDerivationAlgorithm
272 <<
"\nFile a bugreport to Qt (include the line above).";
275 return {cipher,
key, iv};
280#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
311 if (element.
size() != 2
317 if (salt.
size() != 8)
320 int iterationCount = element[1].toInteger();
321 if (iterationCount < 0)
325 auto iterator = pbes1OidHashFunctionMap.constFind(encryptionScheme);
326 if (iterator == pbes1OidHashFunctionMap.cend()) {
332 if (
key.size() != 16)
341 return {cipher,
key, iv};
346 const int length = oidLengthMap->value(oid);
353 for (
int i = 0;
i < modulus.
size(); ++
i) {
357 bits += bits_table[
b];
383 return hash.result();
391 return key.append(
hash.resultView().first(8));
393 return key.append(
hash.resultView());
401 hash.addData(passPhrase);
411 hash.addData(passPhrase);
421 return deriveAesKey(cipher, passPhrase, iv);
453 qWarning() <<
"QSslKey: Found RSA key when asked to use" << getName(that->
algorithm())
454 <<
"\nLoading will fail.";
466 qWarning() <<
"QSslKey: Found EC key when asked to use" << getName(that->
algorithm())
467 <<
"\nLoading will fail.";
474 keyLength = curveBits(pkcs8Info[1].toObjectId());
478 qWarning() <<
"QSslKey: Found DSA when asked to use" << getName(that->
algorithm())
479 <<
"\nLoading will fail.";
486 const auto dsaInfo = pkcs8Info[1].toList();
489 keyLength = numberOfBits(dsaInfo[0].
value());
493 qWarning() <<
"QSslKey: Found DH when asked to use" << getName(that->
algorithm())
494 <<
"\nLoading will fail.";
501 const auto dhInfo = pkcs8Info[1].toList();
504 keyLength = numberOfBits(dhInfo[0].
value());
507 qWarning() <<
"QSslKey: Unsupported PKCS#8 key algorithm:" <<
value
508 <<
"\nFile a bugreport to Qt (include the line above).";
528 QByteArray decryptedDer = decryptPkcs8(der, passPhrase);
539 const auto infoItems = elem.
toList();
552 keyLength = numberOfBits(elem.
value());
559 const auto params = infoItems[1].toList();
569 const auto params = infoItems[1].toList();
578 keyLength = curveBits(infoItems[1].toObjectId());
593 if (versionHex !=
"00" && versionHex !=
"01")
595 int pkcs8KeyLength = extractPkcs8KeyLength(
items,
this);
596 if (pkcs8KeyLength == -1)
599 keyLength = pkcs8KeyLength;
601 if (versionHex !=
"00")
607 if (versionHex !=
"00")
613 if (versionHex !=
"00")
619 if (versionHex !=
"01")
634 derData = decryptedDer;
647 if (headers.
value(
"Proc-Type") ==
"4,ENCRYPTED") {
649 if (dekInfo.
size() != 2) {
655 if (dekInfo.
first() ==
"DES-CBC") {
657 }
else if (dekInfo.
first() ==
"DES-EDE3-CBC") {
659 }
else if (dekInfo.
first() ==
"RC2-CBC") {
661 }
else if (dekInfo.
first() ==
"AES-128-CBC") {
663 }
else if (dekInfo.
first() ==
"AES-192-CBC") {
665 }
else if (dekInfo.
first() ==
"AES-256-CBC") {
694 headers.
insert(
"Proc-Type",
"4,ENCRYPTED");
695 headers.
insert(
"DEK-Info",
"DES-EDE3-CBC," + iv.
toHex());
716 if (headerIndex == -1 || footerIndex == -1) {
722 if (headerIndex == -1 || footerIndex == -1) {
729 if (headerIndex == -1 || footerIndex == -1)
749 if (!
value.isEmpty())
752 bool hasCR = (
i && der[
i-1] ==
'\r');
756 }
while (
i < der.
length() && (der.
at(
i) ==
' ' || der.
at(
i) ==
'\t'));
778 std::memset(derData.
data(), 0, derData.
size());
804 const auto encryptionSchemeContainer =
items[0].
toList();
806 if (encryptionSchemeContainer.size() != 2
812 const QByteArray encryptionScheme = encryptionSchemeContainer[0].toObjectId();
813 const auto schemeParameterContainer = encryptionSchemeContainer[1].toList();
815 if (schemeParameterContainer.size() != 2
823 data = readPbes2(schemeParameterContainer, passPhrase);
824 }
else if (pbes1OidHashFunctionMap.contains(encryptionScheme)) {
825 data = readPbes1(schemeParameterContainer, encryptionScheme, passPhrase);
831 <<
"QSslKey: Unsupported encryption scheme OID:" << encryptionScheme
832 <<
"\nFile a bugreport to Qt (include the line above).";
836 if (!
data.initialized) {
844 return decryptedKeyElement.value();
bool read(QDataStream &data)
QByteArray toObjectId() const
QList< QAsn1Element > toList() const
QByteArray trimmed() const &
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
static QByteArray fromHex(const QByteArray &hexEncoded)
Returns a decoded copy of the hex encoded array hexEncoded.
qsizetype indexOf(char c, qsizetype from=0) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
qsizetype length() const noexcept
Same as size().
void truncate(qsizetype pos)
Truncates the byte array at index position pos.
static QByteArray fromBase64(const QByteArray &base64, Base64Options options=Base64Encoding)
QByteArray right(qsizetype len) const
Returns a byte array that contains the last len bytes of this byte array.
bool startsWith(QByteArrayView bv) const
char at(qsizetype i) const
Returns the byte at index position i in the byte array.
bool contains(char c) const
This is an overloaded member function, provided for convenience. It differs from the above function o...
bool isEmpty() const noexcept
Returns true if the byte array has size 0; otherwise returns false.
void clear()
Clears the contents of the byte array and makes it null.
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
QByteArray mid(qsizetype index, qsizetype len=-1) const
Returns a byte array containing len bytes from this byte array, starting at position pos.
static QByteArray fromRawData(const char *data, qsizetype size)
Constructs a QByteArray that uses the first size bytes of the data array.
\inmodule QtCore\reentrant
qsizetype size() const noexcept
bool isEmpty() const noexcept
QList< T > toList() const noexcept
T value(qsizetype i) const
iterator insert(const Key &key, const T &value)
T value(const Key &key, const T &defaultValue=T()) const
static Q_DECL_CONST_FUNCTION QRandomGenerator * system()
\threadsafe
quint64 generate64()
Generates a 64-bit random quantity and returns it.
qsizetype size() const
Returns the number of characters in this string.
qsizetype length() const
Returns the number of characters in this string.
KeyType type() const override
QByteArray pemFromDer(const QByteArray &der, const QMap< QByteArray, QByteArray > &headers) const override
KeyAlgorithm algorithm() const override
static QByteArray pkcs8Footer(bool encrypted)
static QByteArray pkcs8Header(bool encrypted)
KeyAlgorithm keyAlgorithm
QByteArray derFromPem(const QByteArray &pem, QMap< QByteArray, QByteArray > *headers) const override
QByteArray toPem(const QByteArray &passPhrase) const override
void decodePem(KeyType type, KeyAlgorithm algorithm, const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) override
void fromHandle(Qt::HANDLE opaque, KeyType expectedType) override
Qt::HANDLE handle() const override
void clear(bool deep) override
void decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der, const QByteArray &passPhrase, bool deepClear) override
TlsKey is an abstract class, that allows a TLS plugin to provide an underlying implementation for the...
virtual void decodeDer(KeyType type, KeyAlgorithm algorithm, const QByteArray &der, const QByteArray &passPhrase, bool deepClear)=0
virtual QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) const =0
virtual KeyType type() const =0
QByteArray pemHeader() const
QByteArray pemFooter() const
virtual KeyAlgorithm algorithm() const =0
virtual QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &passPhrase, const QByteArray &iv) const =0
QHash< int, QWidget * > hash
[35multi]
Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf1(QCryptographicHash::Algorithm algorithm, const QByteArray &data, const QByteArray &salt, int iterations, quint64 dkLen)
Q_NETWORK_EXPORT QByteArray deriveKeyPbkdf2(QCryptographicHash::Algorithm algorithm, const QByteArray &data, const QByteArray &salt, int iterations, quint64 dkLen)
KeyType
Describes the two types of keys QSslKey supports.
KeyAlgorithm
Describes the different key algorithms supported by QSslKey.
Combined button and popup list for selecting options.
Namespace containing onternal types that TLS backends implement.
static OidNameMap createOidMap()
#define PKCS5_MD5_DES_CBC_OID
#define EC_ENCRYPTION_OID
#define RC2_CBC_ENCRYPTION_OID
#define PKCS5_PBES2_ENCRYPTION_OID
#define HMAC_WITH_SHA512_256
#define DSA_ENCRYPTION_OID
#define RSA_ENCRYPTION_OID
#define PKCS5_PBKDF2_ENCRYPTION_OID
#define DH_ENCRYPTION_OID
#define PKCS5_SHA1_RC2_CBC_OID
#define DES_CBC_ENCRYPTION_OID
#define DES_EDE3_CBC_ENCRYPTION_OID
#define PKCS5_MD5_RC2_CBC_OID
#define HMAC_WITH_SHA512_224
#define PKCS5_SHA1_DES_CBC_OID
#define QByteArrayLiteral(str)
static QString header(const QString &name)
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define Q_GLOBAL_STATIC_WITH_ARGS(TYPE, NAME, ARGS)
GLboolean GLboolean GLboolean b
GLuint64 GLenum void * handle
GLenum GLuint GLenum GLsizei length
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLenum GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const void * bits
#define Q_UNIMPLEMENTED()
unsigned long long quint64