Store QSslKey in specific key format to provide more details for key
In a TLS handshake the ephemeral server key is saved in the ssl configuration. Clients who want to get the length or algorithm of the key only get "Opaque" and "-1" as a result because the key is always stored as "Opaque". This change converts the key to specific type so more details are available and the client don't need to convert the handle by hand. Change-Id: I60f90fc2c1805e528640d391b20c676b6eeeb49e Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
This commit is contained in:
parent
997fa05d90
commit
7f77dc84fb
@ -56,6 +56,9 @@
|
|||||||
|
|
||||||
#include "qsslkey.h"
|
#include "qsslkey.h"
|
||||||
#include "qsslkey_p.h"
|
#include "qsslkey_p.h"
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
|
#include "qsslsocket_openssl_symbols_p.h"
|
||||||
|
#endif
|
||||||
#include "qsslsocket.h"
|
#include "qsslsocket.h"
|
||||||
#include "qsslsocket_p.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.
|
\a type specifies whether the key is public or private.
|
||||||
|
|
||||||
QSslKey will take ownership for this key and you must not
|
QSslKey will take ownership for this key and you must not
|
||||||
free the key using the native library. The algorithm used
|
free the key using the native library.
|
||||||
when creating a key from a handle will always be QSsl::Opaque.
|
|
||||||
*/
|
*/
|
||||||
QSslKey::QSslKey(Qt::HANDLE handle, QSsl::KeyType type)
|
QSslKey::QSslKey(Qt::HANDLE handle, QSsl::KeyType type)
|
||||||
: d(new QSslKeyPrivate)
|
: d(new QSslKeyPrivate)
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_OPENSSL
|
#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
|
#else
|
||||||
d->opaque = handle;
|
d->opaque = handle;
|
||||||
#endif
|
|
||||||
d->algorithm = QSsl::Opaque;
|
d->algorithm = QSsl::Opaque;
|
||||||
|
#endif
|
||||||
d->type = type;
|
d->type = type;
|
||||||
d->isNull = !d->opaque;
|
d->isNull = !d->opaque;
|
||||||
}
|
}
|
||||||
|
@ -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_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)
|
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
|
#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(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)
|
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
|
#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)
|
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
|
||||||
#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(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)
|
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
|
#ifndef OPENSSL_NO_EC
|
||||||
@ -836,6 +838,7 @@ bool q_resolveOpenSslSymbols()
|
|||||||
#ifdef SSLEAY_MACROS // ### verify
|
#ifdef SSLEAY_MACROS // ### verify
|
||||||
RESOLVEFUNC(PEM_ASN1_read_bio)
|
RESOLVEFUNC(PEM_ASN1_read_bio)
|
||||||
#else
|
#else
|
||||||
|
RESOLVEFUNC(PEM_read_bio_PrivateKey)
|
||||||
RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
|
RESOLVEFUNC(PEM_read_bio_DSAPrivateKey)
|
||||||
RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
|
RESOLVEFUNC(PEM_read_bio_RSAPrivateKey)
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
@ -848,6 +851,7 @@ bool q_resolveOpenSslSymbols()
|
|||||||
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
|
RESOLVEFUNC(PEM_write_bio_ECPrivateKey)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
RESOLVEFUNC(PEM_read_bio_PUBKEY)
|
||||||
RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
|
RESOLVEFUNC(PEM_read_bio_DSA_PUBKEY)
|
||||||
RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
|
RESOLVEFUNC(PEM_read_bio_RSA_PUBKEY)
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
|
@ -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_length(ASN1_STRING *a);
|
||||||
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
|
int q_ASN1_STRING_to_UTF8(unsigned char **a, ASN1_STRING *b);
|
||||||
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
|
long q_BIO_ctrl(BIO *a, int b, long c, void *d);
|
||||||
int q_BIO_free(BIO *a);
|
Q_AUTOTEST_EXPORT int q_BIO_free(BIO *a);
|
||||||
BIO *q_BIO_new(BIO_METHOD *a);
|
Q_AUTOTEST_EXPORT BIO *q_BIO_new(BIO_METHOD *a);
|
||||||
BIO *q_BIO_new_mem_buf(void *a, int b);
|
BIO *q_BIO_new_mem_buf(void *a, int b);
|
||||||
int q_BIO_read(BIO *a, void *b, int c);
|
int q_BIO_read(BIO *a, void *b, int c);
|
||||||
BIO_METHOD *q_BIO_s_mem();
|
Q_AUTOTEST_EXPORT BIO_METHOD *q_BIO_s_mem();
|
||||||
int q_BIO_write(BIO *a, const void *b, int c);
|
Q_AUTOTEST_EXPORT int q_BIO_write(BIO *a, const void *b, int c);
|
||||||
int q_BN_num_bits(const BIGNUM *a);
|
int q_BN_num_bits(const BIGNUM *a);
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
|
||||||
int q_BN_is_word(BIGNUM *a, BN_ULONG w);
|
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);
|
void *f);
|
||||||
// ### ditto for write
|
// ### ditto for write
|
||||||
#else
|
#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);
|
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);
|
RSA *q_PEM_read_bio_RSAPrivateKey(BIO *a, RSA **b, pem_password_cb *c, void *d);
|
||||||
#ifndef OPENSSL_NO_EC
|
#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);
|
int e, pem_password_cb *f, void *g);
|
||||||
#endif
|
#endif
|
||||||
#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);
|
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);
|
RSA *q_PEM_read_bio_RSA_PUBKEY(BIO *a, RSA **b, pem_password_cb *c, void *d);
|
||||||
#ifndef OPENSSL_NO_EC
|
#ifndef OPENSSL_NO_EC
|
||||||
|
@ -34,9 +34,14 @@
|
|||||||
#include <QtNetwork/qhostaddress.h>
|
#include <QtNetwork/qhostaddress.h>
|
||||||
#include <QtNetwork/qnetworkproxy.h>
|
#include <QtNetwork/qnetworkproxy.h>
|
||||||
|
|
||||||
#if !defined(QT_NO_SSL) && defined(QT_BUILD_INTERNAL)
|
#ifdef QT_BUILD_INTERNAL
|
||||||
#include "private/qsslkey_p.h"
|
#ifndef QT_NO_SSL
|
||||||
#define TEST_CRYPTO
|
#include "private/qsslkey_p.h"
|
||||||
|
#define TEST_CRYPTO
|
||||||
|
#endif
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
|
#include "private/qsslsocket_openssl_symbols_p.h"
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class tst_QSslKey : public QObject
|
class tst_QSslKey : public QObject
|
||||||
@ -58,7 +63,7 @@ class tst_QSslKey : public QObject
|
|||||||
|
|
||||||
QList<KeyInfo> keyInfoList;
|
QList<KeyInfo> keyInfoList;
|
||||||
|
|
||||||
void createPlainTestRows();
|
void createPlainTestRows(bool filter = false, QSsl::EncodingFormat format = QSsl::EncodingFormat::Pem);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void initTestCase();
|
void initTestCase();
|
||||||
@ -69,6 +74,10 @@ private slots:
|
|||||||
void emptyConstructor();
|
void emptyConstructor();
|
||||||
void constructor_data();
|
void constructor_data();
|
||||||
void constructor();
|
void constructor();
|
||||||
|
#ifndef QT_NO_OPENSSL
|
||||||
|
void constructorHandle_data();
|
||||||
|
void constructorHandle();
|
||||||
|
#endif
|
||||||
void copyAndAssign_data();
|
void copyAndAssign_data();
|
||||||
void copyAndAssign();
|
void copyAndAssign();
|
||||||
void equalsOperator();
|
void equalsOperator();
|
||||||
@ -142,7 +151,7 @@ Q_DECLARE_METATYPE(QSsl::KeyAlgorithm)
|
|||||||
Q_DECLARE_METATYPE(QSsl::KeyType)
|
Q_DECLARE_METATYPE(QSsl::KeyType)
|
||||||
Q_DECLARE_METATYPE(QSsl::EncodingFormat)
|
Q_DECLARE_METATYPE(QSsl::EncodingFormat)
|
||||||
|
|
||||||
void tst_QSslKey::createPlainTestRows()
|
void tst_QSslKey::createPlainTestRows(bool filter, QSsl::EncodingFormat format)
|
||||||
{
|
{
|
||||||
QTest::addColumn<QString>("absFilePath");
|
QTest::addColumn<QString>("absFilePath");
|
||||||
QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
|
QTest::addColumn<QSsl::KeyAlgorithm>("algorithm");
|
||||||
@ -150,6 +159,9 @@ void tst_QSslKey::createPlainTestRows()
|
|||||||
QTest::addColumn<int>("length");
|
QTest::addColumn<int>("length");
|
||||||
QTest::addColumn<QSsl::EncodingFormat>("format");
|
QTest::addColumn<QSsl::EncodingFormat>("format");
|
||||||
foreach (KeyInfo keyInfo, keyInfoList) {
|
foreach (KeyInfo keyInfo, keyInfoList) {
|
||||||
|
if (filter && keyInfo.format != format)
|
||||||
|
continue;
|
||||||
|
|
||||||
QTest::newRow(keyInfo.fileInfo.fileName().toLatin1())
|
QTest::newRow(keyInfo.fileInfo.fileName().toLatin1())
|
||||||
<< keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
|
<< keyInfo.fileInfo.absoluteFilePath() << keyInfo.algorithm << keyInfo.type
|
||||||
<< keyInfo.length << keyInfo.format;
|
<< keyInfo.length << keyInfo.format;
|
||||||
@ -176,6 +188,45 @@ void tst_QSslKey::constructor()
|
|||||||
QVERIFY(!key.isNull());
|
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()
|
void tst_QSslKey::copyAndAssign_data()
|
||||||
{
|
{
|
||||||
createPlainTestRows();
|
createPlainTestRows();
|
||||||
|
Loading…
Reference in New Issue
Block a user