diff options
-rw-r--r-- | src/network/ssl/qsslkey_p.cpp | 16 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols.cpp | 4 | ||||
-rw-r--r-- | src/network/ssl/qsslsocket_openssl_symbols_p.h | 10 | ||||
-rw-r--r-- | tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp | 61 |
4 files changed, 78 insertions, 13 deletions
diff --git a/src/network/ssl/qsslkey_p.cpp b/src/network/ssl/qsslkey_p.cpp index 34f664093c..e66ec953a0 100644 --- a/src/network/ssl/qsslkey_p.cpp +++ b/src/network/ssl/qsslkey_p.cpp @@ -56,6 +56,9 @@ #include "qsslkey.h" #include "qsslkey_p.h" +#ifndef QT_NO_OPENSSL +#include "qsslsocket_openssl_symbols_p.h" +#endif #include "qsslsocket.h" #include "qsslsocket_p.h" @@ -277,18 +280,23 @@ QSslKey::QSslKey(QIODevice *device, QSsl::KeyAlgorithm algorithm, QSsl::Encoding \a type specifies whether the key is public or private. QSslKey will take ownership for this key and you must not - free the key using the native library. The algorithm used - when creating a key from a handle will always be QSsl::Opaque. + free the key using the native library. */ QSslKey::QSslKey(Qt::HANDLE handle, QSsl::KeyType type) : d(new QSslKeyPrivate) { #ifndef QT_NO_OPENSSL - d->opaque = reinterpret_cast<EVP_PKEY *>(handle); + EVP_PKEY *evpKey = reinterpret_cast<EVP_PKEY *>(handle); + if (!evpKey || !d->fromEVP_PKEY(evpKey)) { + d->opaque = evpKey; + d->algorithm = QSsl::Opaque; + } else { + q_EVP_PKEY_free(evpKey); + } #else d->opaque = handle; -#endif d->algorithm = QSsl::Opaque; +#endif d->type = type; d->isNull = !d->opaque; } diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index f75df0466f..88fed69d3a 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -206,6 +206,7 @@ DEFINEFUNC(int, OBJ_obj2nid, const ASN1_OBJECT *a, a, return NID_undef, return) DEFINEFUNC6(void *, PEM_ASN1_read_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) DEFINEFUNC6(void *, PEM_ASN1_write_bio, d2i_of_void *a, a, const char *b, b, BIO *c, c, void **d, d, pem_password_cb *e, e, void *f, f, return 0, return) #else +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PrivateKey, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSAPrivateKey, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSAPrivateKey, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) #ifndef OPENSSL_NO_EC @@ -218,6 +219,7 @@ DEFINEFUNC7(int, PEM_write_bio_RSAPrivateKey, BIO *a, a, RSA *b, b, const EVP_CI DEFINEFUNC7(int, PEM_write_bio_ECPrivateKey, BIO *a, a, EC_KEY *b, b, const EVP_CIPHER *c, c, unsigned char *d, d, int e, e, pem_password_cb *f, f, void *g, g, return 0, return) #endif #endif +DEFINEFUNC4(EVP_PKEY *, PEM_read_bio_PUBKEY, BIO *a, a, EVP_PKEY **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(DSA *, PEM_read_bio_DSA_PUBKEY, BIO *a, a, DSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) DEFINEFUNC4(RSA *, PEM_read_bio_RSA_PUBKEY, BIO *a, a, RSA **b, b, pem_password_cb *c, c, void *d, d, return 0, return) #ifndef OPENSSL_NO_EC @@ -836,6 +838,7 @@ bool q_resolveOpenSslSymbols() #ifdef SSLEAY_MACROS // ### verify RESOLVEFUNC(PEM_ASN1_read_bio) #else + RESOLVEFUNC(PEM_read_bio_PrivateKey) RESOLVEFUNC(PEM_read_bio_DSAPrivateKey) RESOLVEFUNC(PEM_read_bio_RSAPrivateKey) #ifndef OPENSSL_NO_EC @@ -848,6 +851,7 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(PEM_write_bio_ECPrivateKey) #endif #endif + RESOLVEFUNC(PEM_read_bio_PUBKEY) RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY) RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY) #ifndef OPENSSL_NO_EC diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index f912d8609b..508fdc2a4b 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -221,12 +221,12 @@ unsigned char * q_ASN1_STRING_data(ASN1_STRING *a); int q_ASN1_STRING_length(ASN1_STRING *a); int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b); long q_BIO_ctrl(BIO *a, int b, long c, void *d); -int q_BIO_free(BIO *a); -BIO *q_BIO_new(BIO_METHOD *a); +Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a); +Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a); BIO *q_BIO_new_mem_buf(void *a, int b); int q_BIO_read(BIO *a, void *b, int c); -BIO_METHOD *q_BIO_s_mem(); -int q_BIO_write(BIO *a, const void *b, int c); +Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem(); +Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c); int q_BN_num_bits(const BIGNUM *a); #if OPENSSL_VERSION_NUMBER >= 0x10100000L int q_BN_is_word(BIGNUM *a, BN_ULONG w); @@ -295,6 +295,7 @@ void *q_PEM_ASN1_read_bio(d2i_of_void *a, const char *b, BIO *c, void **d, pem_p void *f); // ### ditto for write #else +Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PrivateKey(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); DSA *q_PEM_read_bio_DSAPrivateKey(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d); #ifndef OPENSSL_NO_EC @@ -310,6 +311,7 @@ int q_PEM_write_bio_ECPrivateKey(BIO *a, EC_KEY *b, const EVP_CIPHER *c, unsigne int e, pem_password_cb *f, void *g); #endif #endif +Q_AUTOTEST_EXPORT EVP_PKEY *q_PEM_read_bio_PUBKEY(BIO *a, EVP_PKEY **b, pem_password_cb *c, void *d); DSA *q_PEM_read_bio_DSA_PUBKEY(BIO *a, DSA **b, pem_password_cb *c, void *d); RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d); #ifndef OPENSSL_NO_EC diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp index 8afc71a216..0112af4ed7 100644 --- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp +++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp @@ -34,9 +34,14 @@ #include <QtNetwork/qhostaddress.h> #include <QtNetwork/qnetworkproxy.h> -#if !defined(QT_NO_SSL) && defined(QT_BUILD_INTERNAL) -#include "private/qsslkey_p.h" -#define TEST_CRYPTO +#ifdef QT_BUILD_INTERNAL + #ifndef QT_NO_SSL + #include "private/qsslkey_p.h" + #define TEST_CRYPTO + #endif + #ifndef QT_NO_OPENSSL + #include "private/qsslsocket_openssl_symbols_p.h" + #endif #endif class tst_QSslKey : public QObject @@ -58,7 +63,7 @@ class tst_QSslKey : public QObject QList<KeyInfo> keyInfoList; - void createPlainTestRows(); + void createPlainTestRows(bool filter = false, QSsl::EncodingFormat format = QSsl::EncodingFormat::Pem); public slots: void initTestCase(); @@ -69,6 +74,10 @@ private slots: void emptyConstructor(); void constructor_data(); void constructor(); +#ifndef QT_NO_OPENSSL + void constructorHandle_data(); + void constructorHandle(); +#endif void copyAndAssign_data(); void copyAndAssign(); void equalsOperator(); @@ -142,7 +151,7 @@ Q_DECLARE_METATYPE(QSsl::KeyAlgorithm) Q_DECLARE_METATYPE(QSsl::KeyType) Q_DECLARE_METATYPE(QSsl::EncodingFormat) -void tst_QSslKey::createPlainTestRows() +void tst_QSslKey::createPlainTestRows(bool filter, QSsl::EncodingFormat format) { QTest::addColumn<QString>("absFilePath"); QTest::addColumn<QSsl::KeyAlgorithm>("algorithm"); @@ -150,6 +159,9 @@ void tst_QSslKey::createPlainTestRows() QTest::addColumn<int>("length"); QTest::addColumn<QSsl::EncodingFormat>("format"); foreach (KeyInfo keyInfo, keyInfoList) { + if (filter && keyInfo.format != format) + continue; + QTest::newRow(keyInfo.fileInfo.fileName().toLatin1()) << keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type << keyInfo.length << keyInfo.format; @@ -176,6 +188,45 @@ void tst_QSslKey::constructor() QVERIFY(!key.isNull()); } +#ifndef QT_NO_OPENSSL + +void tst_QSslKey::constructorHandle_data() +{ + createPlainTestRows(true); +} + +void tst_QSslKey::constructorHandle() +{ +#ifndef QT_BUILD_INTERNAL + QSKIP("This test requires -developer-build."); +#else + if (!QSslSocket::supportsSsl()) + return; + + QFETCH(QString, absFilePath); + QFETCH(QSsl::KeyAlgorithm, algorithm); + QFETCH(QSsl::KeyType, type); + QFETCH(int, length); + + QByteArray pem = readFile(absFilePath); + auto func = (type == QSsl::KeyType::PublicKey + ? q_PEM_read_bio_PUBKEY + : q_PEM_read_bio_PrivateKey); + + BIO* bio = q_BIO_new(q_BIO_s_mem()); + q_BIO_write(bio, pem.constData(), pem.length()); + QSslKey key(func(bio, nullptr, nullptr, nullptr), type); + q_BIO_free(bio); + + QVERIFY(!key.isNull()); + QCOMPARE(key.algorithm(), algorithm); + QCOMPARE(key.type(), type); + QCOMPARE(key.length(), length); +#endif +} + +#endif + void tst_QSslKey::copyAndAssign_data() { createPlainTestRows(); |