diff options
author | Jeremy Lainé <jeremy.laine@m4x.org> | 2014-08-30 16:39:29 +0200 |
---|---|---|
committer | Jeremy Lainé <jeremy.laine@m4x.org> | 2014-08-30 17:36:23 +0200 |
commit | 5c3a499c9ffbf2d4872dd6a6916b3a3a9a7d9cdd (patch) | |
tree | 9ea3da5c7856f1ae48b192e3f4999a8e775bc7b3 /src/network | |
parent | 2fd0afc1f87edf28295caeaeb8a830d888a3e81b (diff) |
ssl: disable (broken) i/o on DER encoded keys
QSslKey currently has methods which supposedly allow decoding and
encoding private keys as DER protected by a passphrase. This is
broken by design as explained in QTBUG-41038, as storing the encrypted
DER data alone makes no sense: such a file lacks the necessary
information about the encryption algorithm and initialization vector.
This change:
- explicitly stops using the passphrase when decoding DER in the
constructor. The behavior is unchanged, it is not possible to
read the encrypted DER alone.
- refuses to honor the passphrase to DER encode a private key. The toDer
method now outputs an empty QByteArray instead of garbage.
Task-number: QTBUG-41038
Change-Id: I4281050cf1104f12d154db201a173633bfe22bd9
Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/ssl/qsslcertificate_qt.cpp | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslkey_openssl.cpp | 5 | ||||
-rw-r--r-- | src/network/ssl/qsslkey_p.cpp | 35 | ||||
-rw-r--r-- | src/network/ssl/qsslkey_p.h | 3 | ||||
-rw-r--r-- | src/network/ssl/qsslkey_qt.cpp | 15 |
5 files changed, 31 insertions, 29 deletions
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp index 26c9c5e64e..391ee6f7f9 100644 --- a/src/network/ssl/qsslcertificate_qt.cpp +++ b/src/network/ssl/qsslcertificate_qt.cpp @@ -143,7 +143,7 @@ QSslKey QSslCertificate::publicKey() const key.d->type = QSsl::PublicKey; if (d->publicKeyAlgorithm != QSsl::Opaque) { key.d->algorithm = d->publicKeyAlgorithm; - key.d->decodeDer(d->publicKeyDerData, QByteArray()); + key.d->decodeDer(d->publicKeyDerData); } return key; } diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 14559d6618..7e78ac0fee 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -109,10 +109,9 @@ bool QSslKeyPrivate::fromEVP_PKEY(EVP_PKEY *pkey) return false; } -void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhrase, - bool deepClear) +void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) { - decodePem(pemFromDer(der), passPhrase, deepClear); + decodePem(pemFromDer(der), QByteArray(), deepClear); } void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase, diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index 40e9231177..2b0dab9933 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -175,8 +175,10 @@ QByteArray QSslKeyPrivate::derFromPem(const QByteArray &pem) const /*! Constructs a QSslKey by decoding the string in the byte array \a encoded using a specified \a algorithm and \a encoding format. - If the encoded key is encrypted, \a passPhrase is used to decrypt - it. \a type specifies whether the key is public or private. + \a type specifies whether the key is public or private. + + If the key is encoded as PEM and encrypted, \a passPhrase is used + to decrypt it. After construction, use isNull() to check if \a encoded contained a valid key. @@ -188,7 +190,7 @@ QSslKey::QSslKey(const QByteArray &encoded, QSsl::KeyAlgorithm algorithm, d->type = type; d->algorithm = algorithm; if (encoding == QSsl::Der) - d->decodeDer(encoded, passPhrase); + d->decodeDer(encoded); else d->decodePem(encoded, passPhrase); } @@ -196,8 +198,10 @@ QSslKey::QSslKey(const QByteArray &encoded, QSsl::KeyAlgorithm algorithm, /*! Constructs a QSslKey by reading and decoding data from a \a device using a specified \a algorithm and \a encoding format. - If the encoded key is encrypted, \a passPhrase is used to decrypt - it. \a type specifies whether the key is public or private. + \a type specifies whether the key is public or private. + + If the key is encoded as PEM and encrypted, \a passPhrase is used + to decrypt it. After construction, use isNull() to check if \a device provided a valid key. @@ -211,9 +215,10 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding encoded = device->readAll(); d->type = type; d->algorithm = algorithm; - d->decodePem((encoding == QSsl::Der) ? - d->pemFromDer(encoded) : encoded, - passPhrase); + if (encoding == QSsl::Der) + d->decodeDer(encoded); + else + d->decodePem(encoded, passPhrase); } /*! @@ -317,23 +322,23 @@ QSsl::KeyAlgorithm QSslKey::algorithm() const } /*! - Returns the key in DER encoding. The result is encrypted with - \a passPhrase if the key is a private key and \a passPhrase is - non-empty. + Returns the key in DER encoding. + + The \a passPhrase argument should be omitted as DER cannot be + encrypted. It will be removed in a future version of Qt. */ -// ### autotest failure for non-empty passPhrase and private key QByteArray QSslKey::toDer(const QByteArray &passPhrase) const { if (d->isNull || d->algorithm == QSsl::Opaque) return QByteArray(); -#ifndef QT_NO_OPENSSL - return d->derFromPem(toPem(passPhrase)); -#else // Encrypted DER is nonsense, see QTBUG-41038. if (d->type == QSsl::PrivateKey && !passPhrase.isEmpty()) return QByteArray(); +#ifndef QT_NO_OPENSSL + return d->derFromPem(toPem(passPhrase)); +#else return d->derData; #endif } diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h index 64a157ba09..9c1476038a 100644 --- a/src/network/ssl/qsslkey_p.h +++ b/src/network/ssl/qsslkey_p.h @@ -86,8 +86,7 @@ public: #ifndef QT_NO_OPENSSL bool fromEVP_PKEY(EVP_PKEY *pkey); #endif - void decodeDer(const QByteArray &der, const QByteArray &passPhrase, - bool deepClear = true); + void decodeDer(const QByteArray &der, bool deepClear = true); void decodePem(const QByteArray &pem, const QByteArray &passPhrase, bool deepClear = true); QByteArray pemHeader() const; diff --git a/src/network/ssl/qsslkey_qt.cpp b/src/network/ssl/qsslkey_qt.cpp index 1e60476601..feeb7d6f87 100644 --- a/src/network/ssl/qsslkey_qt.cpp +++ b/src/network/ssl/qsslkey_qt.cpp @@ -86,19 +86,13 @@ void QSslKeyPrivate::clear(bool deep) keyLength = -1; } -void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhrase, - bool deepClear) +void QSslKeyPrivate::decodeDer(const QByteArray &der, bool deepClear) { clear(deepClear); if (der.isEmpty()) return; - if (type == QSsl::PrivateKey && !passPhrase.isEmpty()) { - Q_UNIMPLEMENTED(); - return; - } - QAsn1Element elem; if (!elem.read(der) || elem.type() != QAsn1Element::SequenceType) return; @@ -161,7 +155,12 @@ void QSslKeyPrivate::decodeDer(const QByteArray &der, const QByteArray &passPhra void QSslKeyPrivate::decodePem(const QByteArray &pem, const QByteArray &passPhrase, bool deepClear) { - decodeDer(derFromPem(pem), passPhrase, deepClear); + if (type == QSsl::PrivateKey && !passPhrase.isEmpty()) { + Q_UNIMPLEMENTED(); + return; + } + + decodeDer(derFromPem(pem), deepClear); } int QSslKeyPrivate::length() const |