diff options
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/access/qnetworkcookiejar.cpp | 21 | ||||
-rw-r--r-- | src/network/kernel/qauthenticator.cpp | 15 | ||||
-rw-r--r-- | src/network/kernel/qauthenticator_p.h | 2 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.cpp | 29 | ||||
-rw-r--r-- | src/network/kernel/qhostinfo.h | 7 | ||||
-rw-r--r-- | src/network/ssl/qdtls.h | 2 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_mac.cpp | 263 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_p.h | 5 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_qt.cpp | 309 | ||||
-rw-r--r-- | src/network/ssl/ssl.pri | 1 |
10 files changed, 341 insertions, 313 deletions
diff --git a/src/network/access/qnetworkcookiejar.cpp b/src/network/access/qnetworkcookiejar.cpp index 072a7f249d..af5b126953 100644 --- a/src/network/access/qnetworkcookiejar.cpp +++ b/src/network/access/qnetworkcookiejar.cpp @@ -45,6 +45,14 @@ #include "QtCore/qdatetime.h" #if QT_CONFIG(topleveldomain) #include "private/qtldurl_p.h" +#else +QT_BEGIN_NAMESPACE +static bool qIsEffectiveTLD(QString domain) +{ + // provide minimal checking by not accepting cookies on real TLDs + return !domain.contains(QLatin1Char('.')); +} +QT_END_NAMESPACE #endif QT_BEGIN_NAMESPACE @@ -356,19 +364,12 @@ bool QNetworkCookieJar::validateCookie(const QNetworkCookie &cookie, const QUrl // https://tools.ietf.org/html/rfc6265#section-5.3 step 5 if (host == domain) return true; -#if QT_CONFIG(topleveldomain) // the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2 // redundant; the "leading dot" rule has been relaxed anyway, see QNetworkCookie::normalize() // we remove the leading dot for this check if it's present - if (qIsEffectiveTLD(domain)) - return false; // not accepted -#else - // provide minimal checking by not accepting cookies on real TLDs - if (!domain.contains(QLatin1Char('.'))) - return false; -#endif - - return true; + // Normally defined in qtldurl_p.h, but uses fall-back in this file when topleveldomain isn't + // configured: + return !qIsEffectiveTLD(domain); } QT_END_NAMESPACE diff --git a/src/network/kernel/qauthenticator.cpp b/src/network/kernel/qauthenticator.cpp index 34db5b4b31..47ce9ab0c6 100644 --- a/src/network/kernel/qauthenticator.cpp +++ b/src/network/kernel/qauthenticator.cpp @@ -465,27 +465,12 @@ QByteArray QAuthenticatorPrivate::calculateResponse(const QByteArray &requestMet methodString = ""; phase = Done; break; - case QAuthenticatorPrivate::Plain: - response = '\0' + user.toUtf8() + '\0' + password.toUtf8(); - phase = Done; - break; case QAuthenticatorPrivate::Basic: methodString = "Basic "; response = user.toLatin1() + ':' + password.toLatin1(); response = response.toBase64(); phase = Done; break; - case QAuthenticatorPrivate::Login: - if (challenge.contains("VXNlciBOYW1lAA==")) { - response = user.toUtf8().toBase64(); - phase = Phase2; - } else if (challenge.contains("UGFzc3dvcmQA")) { - response = password.toUtf8().toBase64(); - phase = Done; - } - break; - case QAuthenticatorPrivate::CramMd5: - break; case QAuthenticatorPrivate::DigestMd5: methodString = "Digest "; response = digestMd5Response(challenge, requestMethod, path); diff --git a/src/network/kernel/qauthenticator_p.h b/src/network/kernel/qauthenticator_p.h index 8a1ee0ebe6..265cb7afe2 100644 --- a/src/network/kernel/qauthenticator_p.h +++ b/src/network/kernel/qauthenticator_p.h @@ -68,7 +68,7 @@ class QNtlmWindowsHandles; class Q_AUTOTEST_EXPORT QAuthenticatorPrivate { public: - enum Method { None, Basic, Plain, Login, Ntlm, CramMd5, DigestMd5 }; + enum Method { None, Basic, Ntlm, DigestMd5 }; QAuthenticatorPrivate(); ~QAuthenticatorPrivate(); diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 0973d0dd52..1c7a8da06d 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -300,25 +300,6 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, */ /*! - \fn template<typename PointerToMemberFunction> int QHostInfo::lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function) - - \since 5.9 - - \overload - - Looks up the IP address(es) associated with host name \a name, and - returns an ID for the lookup. When the result of the lookup is - ready, the slot or signal \a function in \a receiver is called with - a QHostInfo argument. The QHostInfo object can then be inspected - to get the results of the lookup. - - \note There is no guarantee on the order the signals will be emitted - if you start multiple requests with lookupHost(). - - \sa abortHostLookup(), addresses(), error(), fromName() -*/ - -/*! \fn template<typename Functor> int QHostInfo::lookupHost(const QString &name, Functor functor) \since 5.9 @@ -354,6 +335,16 @@ int QHostInfo::lookupHost(const QString &name, QObject *receiver, thread of \a context. The context's thread must have a running Qt event loop. + Here is an alternative signature for the function: + \code + lookupHost(const QString &name, const QObject *receiver, PointerToMemberFunction function) + \endcode + + In this case, when the result of the lookup is ready, the slot or + signal \c{function} in \c{receiver} is called with a QHostInfo + argument. The QHostInfo object can then be inspected to get the + results of the lookup. + \note There is no guarantee on the order the signals will be emitted if you start multiple requests with lookupHost(). diff --git a/src/network/kernel/qhostinfo.h b/src/network/kernel/qhostinfo.h index 75917a02a3..49871ad470 100644 --- a/src/network/kernel/qhostinfo.h +++ b/src/network/kernel/qhostinfo.h @@ -91,13 +91,10 @@ public: static QString localDomainName(); #ifdef Q_CLANG_QDOC - template<typename PointerToMemberFunction> - static int QHostInfo::lookupHost(const QString &name, const QObject *receiver, - PointerToMemberFunction function); template<typename Functor> - static int QHostInfo::lookupHost(const QString &name, Functor functor); + static int lookupHost(const QString &name, Functor functor); template<typename Functor> - static int QHostInfo::lookupHost(const QString &name, const QObject *context, Functor functor); + static int lookupHost(const QString &name, const QObject *context, Functor functor); #else // lookupHost to a QObject slot template <typename Func> diff --git a/src/network/ssl/qdtls.h b/src/network/ssl/qdtls.h index 8505b00d5e..d057eadf19 100644 --- a/src/network/ssl/qdtls.h +++ b/src/network/ssl/qdtls.h @@ -48,7 +48,9 @@ #include <QtCore/qcryptographichash.h> #include <QtCore/qobject.h> +#ifndef Q_CLANG_QDOC QT_REQUIRE_CONFIG(dtls); +#endif QT_BEGIN_NAMESPACE diff --git a/src/network/ssl/qsslsocket_mac.cpp b/src/network/ssl/qsslsocket_mac.cpp index 9166e0ac29..aa4fb4fe8e 100644 --- a/src/network/ssl/qsslsocket_mac.cpp +++ b/src/network/ssl/qsslsocket_mac.cpp @@ -993,9 +993,6 @@ void QSslSocketBackendPrivate::destroySslContext() context.reset(nullptr); } -static QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); - - bool QSslSocketBackendPrivate::setSessionCertificate(QString &errorDescription, QAbstractSocket::SocketError &errorCode) { Q_ASSERT_X(context, Q_FUNC_INFO, "invalid SSL context (null)"); @@ -1499,264 +1496,4 @@ bool QSslSocketBackendPrivate::startHandshake() } } -/* - PKCS12 helpers. -*/ - -static QAsn1Element wrap(quint8 type, const QAsn1Element &child) -{ - QByteArray value; - QDataStream stream(&value, QIODevice::WriteOnly); - child.write(stream); - return QAsn1Element(type, value); -} - -static QAsn1Element _q_PKCS7_data(const QByteArray &data) -{ - QVector<QAsn1Element> items; - items << QAsn1Element::fromObjectId("1.2.840.113549.1.7.1"); - items << wrap(QAsn1Element::Context0Type, - QAsn1Element(QAsn1Element::OctetStringType, data)); - return QAsn1Element::fromVector(items); -} - -/*! - PKCS #12 key derivation. - - Some test vectors: - http://www.drh-consultancy.demon.co.uk/test.txt -*/ -static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r) -{ - const int u = 20; - const int v = 64; - - // password formatting - QByteArray passUnicode(passPhrase.size() * 2 + 2, '\0'); - char *p = passUnicode.data(); - for (int i = 0; i < passPhrase.size(); ++i) { - quint16 ch = passPhrase[i].unicode(); - *(p++) = (ch & 0xff00) >> 8; - *(p++) = (ch & 0xff); - } - - // prepare I - QByteArray D(64, id); - QByteArray S, P; - const int sSize = v * ((salt.size() + v - 1) / v); - S.resize(sSize); - for (int i = 0; i < sSize; ++i) { - S[i] = salt[i % salt.size()]; - } - const int pSize = v * ((passUnicode.size() + v - 1) / v); - P.resize(pSize); - for (int i = 0; i < pSize; ++i) { - P[i] = passUnicode[i % passUnicode.size()]; - } - QByteArray I = S + P; - - // apply hashing - const int c = (n + u - 1) / u; - QByteArray A; - QByteArray B; - B.resize(v); - QCryptographicHash hash(QCryptographicHash::Sha1); - for (int i = 0; i < c; ++i) { - // hash r iterations - QByteArray Ai = D + I; - for (int j = 0; j < r; ++j) { - hash.reset(); - hash.addData(Ai); - Ai = hash.result(); - } - - for (int j = 0; j < v; ++j) { - B[j] = Ai[j % u]; - } - - // modify I as Ij = (Ij + B + 1) modulo 2^v - for (int p = 0; p < I.size(); p += v) { - quint8 carry = 1; - for (int j = v - 1; j >= 0; --j) { - quint16 v = quint8(I[p+j]) + quint8(B[j]) + carry; - I[p+j] = v & 0xff; - carry = (v & 0xff00) >> 8; - } - } - A += Ai; - } - return A.left(n); -} - -static QByteArray _q_PKCS12_salt() -{ - QByteArray salt; - salt.resize(8); - for (int i = 0; i < salt.size(); ++i) { - salt[i] = (qrand() & 0xff); - } - return salt; -} - -static QByteArray _q_PKCS12_certBag(const QSslCertificate &cert) -{ - QVector<QAsn1Element> items; - items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.3"); - - // certificate - QVector<QAsn1Element> certItems; - certItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.22.1"); - certItems << wrap(QAsn1Element::Context0Type, - QAsn1Element(QAsn1Element::OctetStringType, cert.toDer())); - items << wrap(QAsn1Element::Context0Type, - QAsn1Element::fromVector(certItems)); - - // local key id - const QByteArray localKeyId = cert.digest(QCryptographicHash::Sha1); - QVector<QAsn1Element> idItems; - idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21"); - idItems << wrap(QAsn1Element::SetType, - QAsn1Element(QAsn1Element::OctetStringType, localKeyId)); - items << wrap(QAsn1Element::SetType, QAsn1Element::fromVector(idItems)); - - // dump - QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items)); - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - root.write(stream); - return ba; -} - -static QAsn1Element _q_PKCS12_key(const QSslKey &key) -{ - Q_ASSERT(key.algorithm() == QSsl::Rsa || key.algorithm() == QSsl::Dsa); - - QVector<QAsn1Element> keyItems; - keyItems << QAsn1Element::fromInteger(0); - QVector<QAsn1Element> algoItems; - if (key.algorithm() == QSsl::Rsa) - algoItems << QAsn1Element::fromObjectId(RSA_ENCRYPTION_OID); - else if (key.algorithm() == QSsl::Dsa) - algoItems << QAsn1Element::fromObjectId(DSA_ENCRYPTION_OID); - algoItems << QAsn1Element(QAsn1Element::NullType); - keyItems << QAsn1Element::fromVector(algoItems); - keyItems << QAsn1Element(QAsn1Element::OctetStringType, key.toDer()); - return QAsn1Element::fromVector(keyItems); -} - -static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId) -{ - const int iterations = 2048; - QByteArray salt = _q_PKCS12_salt(); - QByteArray cKey = _q_PKCS12_keygen(1, salt, passPhrase, 24, iterations); - QByteArray cIv = _q_PKCS12_keygen(2, salt, passPhrase, 8, iterations); - - // prepare and encrypt data - QByteArray plain; - QDataStream plainStream(&plain, QIODevice::WriteOnly); - _q_PKCS12_key(key).write(plainStream); - QByteArray crypted = QSslKeyPrivate::encrypt(QSslKeyPrivate::DesEde3Cbc, - plain, cKey, cIv); - - QVector<QAsn1Element> items; - items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.2"); - - // key - QVector<QAsn1Element> keyItems; - QVector<QAsn1Element> algoItems; - algoItems << QAsn1Element::fromObjectId("1.2.840.113549.1.12.1.3"); - QVector<QAsn1Element> paramItems; - paramItems << QAsn1Element(QAsn1Element::OctetStringType, salt); - paramItems << QAsn1Element::fromInteger(iterations); - algoItems << QAsn1Element::fromVector(paramItems); - keyItems << QAsn1Element::fromVector(algoItems); - keyItems << QAsn1Element(QAsn1Element::OctetStringType, crypted); - items << wrap(QAsn1Element::Context0Type, - QAsn1Element::fromVector(keyItems)); - - // local key id - QVector<QAsn1Element> idItems; - idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21"); - idItems << wrap(QAsn1Element::SetType, - QAsn1Element(QAsn1Element::OctetStringType, localKeyId)); - items << wrap(QAsn1Element::SetType, - QAsn1Element::fromVector(idItems)); - - // dump - QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items)); - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - root.write(stream); - return ba; -} - -static QByteArray _q_PKCS12_bag(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase) -{ - QVector<QAsn1Element> items; - - // certs - for (int i = 0; i < certs.size(); ++i) - items << _q_PKCS7_data(_q_PKCS12_certBag(certs[i])); - - // key - const QByteArray localKeyId = certs.first().digest(QCryptographicHash::Sha1); - items << _q_PKCS7_data(_q_PKCS12_shroudedKeyBag(key, passPhrase, localKeyId)); - - // dump - QAsn1Element root = QAsn1Element::fromVector(items); - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - root.write(stream); - return ba; -} - -static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase) -{ - const int iterations = 2048; - - // salt generation - QByteArray macSalt = _q_PKCS12_salt(); - QByteArray key = _q_PKCS12_keygen(3, macSalt, passPhrase, 20, iterations); - - // HMAC calculation - QMessageAuthenticationCode hmac(QCryptographicHash::Sha1, key); - hmac.addData(data); - - QVector<QAsn1Element> algoItems; - algoItems << QAsn1Element::fromObjectId("1.3.14.3.2.26"); - algoItems << QAsn1Element(QAsn1Element::NullType); - - QVector<QAsn1Element> digestItems; - digestItems << QAsn1Element::fromVector(algoItems); - digestItems << QAsn1Element(QAsn1Element::OctetStringType, hmac.result()); - - QVector<QAsn1Element> macItems; - macItems << QAsn1Element::fromVector(digestItems); - macItems << QAsn1Element(QAsn1Element::OctetStringType, macSalt); - macItems << QAsn1Element::fromInteger(iterations); - return QAsn1Element::fromVector(macItems); -} - -QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase) -{ - QVector<QAsn1Element> items; - - // version - items << QAsn1Element::fromInteger(3); - - // auth safe - const QByteArray data = _q_PKCS12_bag(certs, key, passPhrase); - items << _q_PKCS7_data(data); - - // HMAC - items << _q_PKCS12_mac(data, passPhrase); - - // dump - QAsn1Element root = QAsn1Element::fromVector(items); - QByteArray ba; - QDataStream stream(&ba, QIODevice::WriteOnly); - root.write(stream); - return ba; -} - QT_END_NAMESPACE diff --git a/src/network/ssl/qsslsocket_p.h b/src/network/ssl/qsslsocket_p.h index 6f34c6c888..c27496ec02 100644 --- a/src/network/ssl/qsslsocket_p.h +++ b/src/network/ssl/qsslsocket_p.h @@ -222,6 +222,11 @@ protected: bool flushTriggered; }; +#if QT_CONFIG(securetransport) +// Implemented in qsslsocket_qt.cpp +QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase); +#endif + QT_END_NAMESPACE #endif diff --git a/src/network/ssl/qsslsocket_qt.cpp b/src/network/ssl/qsslsocket_qt.cpp new file mode 100644 index 0000000000..2c78f0f4e7 --- /dev/null +++ b/src/network/ssl/qsslsocket_qt.cpp @@ -0,0 +1,309 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Jeremy Lainé <jeremy.laine@m4x.org> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtNetwork module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include <QtCore/qbytearray.h> +#include <QtCore/qdatastream.h> +#include <QtCore/qmessageauthenticationcode.h> + +#include "qsslsocket_p.h" +#include "qasn1element_p.h" +#include "qsslkey_p.h" + +QT_BEGIN_NAMESPACE + +/* + PKCS12 helpers. +*/ + +static QAsn1Element wrap(quint8 type, const QAsn1Element &child) +{ + QByteArray value; + QDataStream stream(&value, QIODevice::WriteOnly); + child.write(stream); + return QAsn1Element(type, value); +} + +static QAsn1Element _q_PKCS7_data(const QByteArray &data) +{ + QVector<QAsn1Element> items; + items << QAsn1Element::fromObjectId("1.2.840.113549.1.7.1"); + items << wrap(QAsn1Element::Context0Type, + QAsn1Element(QAsn1Element::OctetStringType, data)); + return QAsn1Element::fromVector(items); +} + +/*! + PKCS #12 key derivation. + + Some test vectors: + http://www.drh-consultancy.demon.co.uk/test.txt +*/ +static QByteArray _q_PKCS12_keygen(char id, const QByteArray &salt, const QString &passPhrase, int n, int r) +{ + const int u = 20; + const int v = 64; + + // password formatting + QByteArray passUnicode(passPhrase.size() * 2 + 2, '\0'); + char *p = passUnicode.data(); + for (int i = 0; i < passPhrase.size(); ++i) { + quint16 ch = passPhrase[i].unicode(); + *(p++) = (ch & 0xff00) >> 8; + *(p++) = (ch & 0xff); + } + + // prepare I + QByteArray D(64, id); + QByteArray S, P; + const int sSize = v * ((salt.size() + v - 1) / v); + S.resize(sSize); + for (int i = 0; i < sSize; ++i) { + S[i] = salt[i % salt.size()]; + } + const int pSize = v * ((passUnicode.size() + v - 1) / v); + P.resize(pSize); + for (int i = 0; i < pSize; ++i) { + P[i] = passUnicode[i % passUnicode.size()]; + } + QByteArray I = S + P; + + // apply hashing + const int c = (n + u - 1) / u; + QByteArray A; + QByteArray B; + B.resize(v); + QCryptographicHash hash(QCryptographicHash::Sha1); + for (int i = 0; i < c; ++i) { + // hash r iterations + QByteArray Ai = D + I; + for (int j = 0; j < r; ++j) { + hash.reset(); + hash.addData(Ai); + Ai = hash.result(); + } + + for (int j = 0; j < v; ++j) { + B[j] = Ai[j % u]; + } + + // modify I as Ij = (Ij + B + 1) modulo 2^v + for (int p = 0; p < I.size(); p += v) { + quint8 carry = 1; + for (int j = v - 1; j >= 0; --j) { + quint16 v = quint8(I[p+j]) + quint8(B[j]) + carry; + I[p+j] = v & 0xff; + carry = (v & 0xff00) >> 8; + } + } + A += Ai; + } + return A.left(n); +} + +static QByteArray _q_PKCS12_salt() +{ + QByteArray salt; + salt.resize(8); + for (int i = 0; i < salt.size(); ++i) { + salt[i] = (qrand() & 0xff); + } + return salt; +} + +static QByteArray _q_PKCS12_certBag(const QSslCertificate &cert) +{ + QVector<QAsn1Element> items; + items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.3"); + + // certificate + QVector<QAsn1Element> certItems; + certItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.22.1"); + certItems << wrap(QAsn1Element::Context0Type, + QAsn1Element(QAsn1Element::OctetStringType, cert.toDer())); + items << wrap(QAsn1Element::Context0Type, + QAsn1Element::fromVector(certItems)); + + // local key id + const QByteArray localKeyId = cert.digest(QCryptographicHash::Sha1); + QVector<QAsn1Element> idItems; + idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21"); + idItems << wrap(QAsn1Element::SetType, + QAsn1Element(QAsn1Element::OctetStringType, localKeyId)); + items << wrap(QAsn1Element::SetType, QAsn1Element::fromVector(idItems)); + + // dump + QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items)); + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + root.write(stream); + return ba; +} + +static QAsn1Element _q_PKCS12_key(const QSslKey &key) +{ + Q_ASSERT(key.algorithm() == QSsl::Rsa || key.algorithm() == QSsl::Dsa); + + QVector<QAsn1Element> keyItems; + keyItems << QAsn1Element::fromInteger(0); + QVector<QAsn1Element> algoItems; + if (key.algorithm() == QSsl::Rsa) + algoItems << QAsn1Element::fromObjectId(RSA_ENCRYPTION_OID); + else if (key.algorithm() == QSsl::Dsa) + algoItems << QAsn1Element::fromObjectId(DSA_ENCRYPTION_OID); + algoItems << QAsn1Element(QAsn1Element::NullType); + keyItems << QAsn1Element::fromVector(algoItems); + keyItems << QAsn1Element(QAsn1Element::OctetStringType, key.toDer()); + return QAsn1Element::fromVector(keyItems); +} + +static QByteArray _q_PKCS12_shroudedKeyBag(const QSslKey &key, const QString &passPhrase, const QByteArray &localKeyId) +{ + const int iterations = 2048; + QByteArray salt = _q_PKCS12_salt(); + QByteArray cKey = _q_PKCS12_keygen(1, salt, passPhrase, 24, iterations); + QByteArray cIv = _q_PKCS12_keygen(2, salt, passPhrase, 8, iterations); + + // prepare and encrypt data + QByteArray plain; + QDataStream plainStream(&plain, QIODevice::WriteOnly); + _q_PKCS12_key(key).write(plainStream); + QByteArray crypted = QSslKeyPrivate::encrypt(QSslKeyPrivate::DesEde3Cbc, + plain, cKey, cIv); + + QVector<QAsn1Element> items; + items << QAsn1Element::fromObjectId("1.2.840.113549.1.12.10.1.2"); + + // key + QVector<QAsn1Element> keyItems; + QVector<QAsn1Element> algoItems; + algoItems << QAsn1Element::fromObjectId("1.2.840.113549.1.12.1.3"); + QVector<QAsn1Element> paramItems; + paramItems << QAsn1Element(QAsn1Element::OctetStringType, salt); + paramItems << QAsn1Element::fromInteger(iterations); + algoItems << QAsn1Element::fromVector(paramItems); + keyItems << QAsn1Element::fromVector(algoItems); + keyItems << QAsn1Element(QAsn1Element::OctetStringType, crypted); + items << wrap(QAsn1Element::Context0Type, + QAsn1Element::fromVector(keyItems)); + + // local key id + QVector<QAsn1Element> idItems; + idItems << QAsn1Element::fromObjectId("1.2.840.113549.1.9.21"); + idItems << wrap(QAsn1Element::SetType, + QAsn1Element(QAsn1Element::OctetStringType, localKeyId)); + items << wrap(QAsn1Element::SetType, + QAsn1Element::fromVector(idItems)); + + // dump + QAsn1Element root = wrap(QAsn1Element::SequenceType, QAsn1Element::fromVector(items)); + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + root.write(stream); + return ba; +} + +static QByteArray _q_PKCS12_bag(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase) +{ + QVector<QAsn1Element> items; + + // certs + for (int i = 0; i < certs.size(); ++i) + items << _q_PKCS7_data(_q_PKCS12_certBag(certs[i])); + + // key + const QByteArray localKeyId = certs.first().digest(QCryptographicHash::Sha1); + items << _q_PKCS7_data(_q_PKCS12_shroudedKeyBag(key, passPhrase, localKeyId)); + + // dump + QAsn1Element root = QAsn1Element::fromVector(items); + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + root.write(stream); + return ba; +} + +static QAsn1Element _q_PKCS12_mac(const QByteArray &data, const QString &passPhrase) +{ + const int iterations = 2048; + + // salt generation + QByteArray macSalt = _q_PKCS12_salt(); + QByteArray key = _q_PKCS12_keygen(3, macSalt, passPhrase, 20, iterations); + + // HMAC calculation + QMessageAuthenticationCode hmac(QCryptographicHash::Sha1, key); + hmac.addData(data); + + QVector<QAsn1Element> algoItems; + algoItems << QAsn1Element::fromObjectId("1.3.14.3.2.26"); + algoItems << QAsn1Element(QAsn1Element::NullType); + + QVector<QAsn1Element> digestItems; + digestItems << QAsn1Element::fromVector(algoItems); + digestItems << QAsn1Element(QAsn1Element::OctetStringType, hmac.result()); + + QVector<QAsn1Element> macItems; + macItems << QAsn1Element::fromVector(digestItems); + macItems << QAsn1Element(QAsn1Element::OctetStringType, macSalt); + macItems << QAsn1Element::fromInteger(iterations); + return QAsn1Element::fromVector(macItems); +} + +QByteArray _q_makePkcs12(const QList<QSslCertificate> &certs, const QSslKey &key, const QString &passPhrase) +{ + QVector<QAsn1Element> items; + + // version + items << QAsn1Element::fromInteger(3); + + // auth safe + const QByteArray data = _q_PKCS12_bag(certs, key, passPhrase); + items << _q_PKCS7_data(data); + + // HMAC + items << _q_PKCS12_mac(data, passPhrase); + + // dump + QAsn1Element root = QAsn1Element::fromVector(items); + QByteArray ba; + QDataStream stream(&ba, QIODevice::WriteOnly); + root.write(stream); + return ba; +} + +QT_END_NAMESPACE diff --git a/src/network/ssl/ssl.pri b/src/network/ssl/ssl.pri index 6975264038..b5603c1258 100644 --- a/src/network/ssl/ssl.pri +++ b/src/network/ssl/ssl.pri @@ -56,6 +56,7 @@ qtConfig(ssl) { ssl/qsslkey_mac.cpp \ ssl/qsslsocket_mac_shared.cpp \ ssl/qsslsocket_mac.cpp \ + ssl/qsslsocket_qt.cpp \ ssl/qsslellipticcurve_dummy.cpp } |