From 49fee77ccc68424758823dd2579e731e4ef4073f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jeremy=20Lain=C3=A9?= Date: Mon, 1 Sep 2014 11:13:17 +0200 Subject: ssl: add openssl-based QSslKeyPrivate::encrypt / decrypt This adds an OpenSSL-based implementation of the QSslKeyPrivate encrypt and decrypt method. This puts both the OpenSSL-based and non-OpenSSL backends (WinRT for now) on par. Change-Id: I18a75ee5f1c223601e51ebf0933f4430e7c5c29b Reviewed-by: Andrew Knight Reviewed-by: Richard J. Moore --- src/network/ssl/qsslkey_openssl.cpp | 49 ++++++++++++++++++++++++++ src/network/ssl/qsslkey_p.h | 19 +++++----- src/network/ssl/qsslsocket_openssl_symbols.cpp | 18 ++++++++++ src/network/ssl/qsslsocket_openssl_symbols_p.h | 9 +++++ tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp | 2 +- 5 files changed, 87 insertions(+), 10 deletions(-) diff --git a/src/network/ssl/qsslkey_openssl.cpp b/src/network/ssl/qsslkey_openssl.cpp index 33cb81ce71..a90c9411b7 100644 --- a/src/network/ssl/qsslkey_openssl.cpp +++ b/src/network/ssl/qsslkey_openssl.cpp @@ -265,4 +265,53 @@ Qt::HANDLE QSslKeyPrivate::handle() const } } +static QByteArray doCrypt(QSslKeyPrivate::Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv, int enc) +{ + EVP_CIPHER_CTX ctx; + const EVP_CIPHER* type = 0; + int i = 0, len = 0; + + switch (cipher) { + case QSslKeyPrivate::DesCbc: + type = q_EVP_des_cbc(); + break; + case QSslKeyPrivate::DesEde3Cbc: + type = q_EVP_des_ede3_cbc(); + break; + case QSslKeyPrivate::Rc2Cbc: + type = q_EVP_rc2_cbc(); + break; + } + + QByteArray output; + output.resize(data.size() + EVP_MAX_BLOCK_LENGTH); + q_EVP_CIPHER_CTX_init(&ctx); + q_EVP_CipherInit(&ctx, type, NULL, NULL, enc); + q_EVP_CIPHER_CTX_set_key_length(&ctx, key.size()); + if (cipher == QSslKeyPrivate::Rc2Cbc) + q_EVP_CIPHER_CTX_ctrl(&ctx, EVP_CTRL_SET_RC2_KEY_BITS, 8 * key.size(), NULL); + q_EVP_CipherInit(&ctx, NULL, + reinterpret_cast(key.constData()), + reinterpret_cast(iv.constData()), enc); + q_EVP_CipherUpdate(&ctx, + reinterpret_cast(output.data()), &len, + reinterpret_cast(data.constData()), data.size()); + q_EVP_CipherFinal(&ctx, + reinterpret_cast(output.data()) + len, &i); + len += i; + q_EVP_CIPHER_CTX_cleanup(&ctx); + + return output.left(len); +} + +QByteArray QSslKeyPrivate::decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, 0); +} + +QByteArray QSslKeyPrivate::encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv) +{ + return doCrypt(cipher, data, key, iv, 1); +} + QT_END_NAMESPACE diff --git a/src/network/ssl/qsslkey_p.h b/src/network/ssl/qsslkey_p.h index be981bb484..fea0e30bbc 100644 --- a/src/network/ssl/qsslkey_p.h +++ b/src/network/ssl/qsslkey_p.h @@ -90,6 +90,16 @@ public: bool isNull; QSsl::KeyType type; QSsl::KeyAlgorithm algorithm; + + enum Cipher { + DesCbc, + DesEde3Cbc, + Rc2Cbc + }; + + Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); + #ifndef QT_NO_OPENSSL union { EVP_PKEY *opaque; @@ -100,15 +110,6 @@ public: #endif }; #else - enum Cipher { - DesCbc, - DesEde3Cbc, - Rc2Cbc - }; - - Q_AUTOTEST_EXPORT static QByteArray decrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); - Q_AUTOTEST_EXPORT static QByteArray encrypt(Cipher cipher, const QByteArray &data, const QByteArray &key, const QByteArray &iv); - Qt::HANDLE opaque; QByteArray derData; int keyLength; diff --git a/src/network/ssl/qsslsocket_openssl_symbols.cpp b/src/network/ssl/qsslsocket_openssl_symbols.cpp index f12d2ab798..e7829bac90 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols.cpp +++ b/src/network/ssl/qsslsocket_openssl_symbols.cpp @@ -159,7 +159,16 @@ DEFINEFUNC3(X509 *, d2i_X509, X509 **a, a, const unsigned char **b, b, long c, c DEFINEFUNC2(char *, ERR_error_string, unsigned long a, a, char *b, b, return 0, return) DEFINEFUNC(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG) +DEFINEFUNC(void, EVP_CIPHER_CTX_cleanup, EVP_CIPHER_CTX *a, a, return, DUMMYARG) +DEFINEFUNC(void, EVP_CIPHER_CTX_init, EVP_CIPHER_CTX *a, a, return, DUMMYARG) +DEFINEFUNC4(int, EVP_CIPHER_CTX_ctrl, EVP_CIPHER_CTX *ctx, ctx, int type, type, int arg, arg, void *ptr, ptr, return 0, return); +DEFINEFUNC2(int, EVP_CIPHER_CTX_set_key_length, EVP_CIPHER_CTX *ctx, ctx, int keylen, keylen, return 0, return) +DEFINEFUNC5(int, EVP_CipherInit, EVP_CIPHER_CTX *ctx, ctx, const EVP_CIPHER *type, type, const unsigned char *key, key, const unsigned char *iv, iv, int enc, enc, return 0, return); +DEFINEFUNC5(int, EVP_CipherUpdate, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, const unsigned char *in, in, int inl, inl, return 0, return); +DEFINEFUNC3(int, EVP_CipherFinal, EVP_CIPHER_CTX *ctx, ctx, unsigned char *out, out, int *outl, outl, return 0, return); +DEFINEFUNC(const EVP_CIPHER *, EVP_des_cbc, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC(const EVP_CIPHER *, EVP_des_ede3_cbc, DUMMYARG, DUMMYARG, return 0, return) +DEFINEFUNC(const EVP_CIPHER *, EVP_rc2_cbc, DUMMYARG, DUMMYARG, return 0, return) DEFINEFUNC3(int, EVP_PKEY_assign, EVP_PKEY *a, a, int b, b, char *c, c, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_RSA, EVP_PKEY *a, a, RSA *b, b, return -1, return) DEFINEFUNC2(int, EVP_PKEY_set1_DSA, EVP_PKEY *a, a, DSA *b, b, return -1, return) @@ -762,7 +771,16 @@ bool q_resolveOpenSslSymbols() RESOLVEFUNC(ERR_error_string) RESOLVEFUNC(ERR_get_error) RESOLVEFUNC(ERR_free_strings) + RESOLVEFUNC(EVP_CIPHER_CTX_cleanup) + RESOLVEFUNC(EVP_CIPHER_CTX_init) + RESOLVEFUNC(EVP_CIPHER_CTX_ctrl) + RESOLVEFUNC(EVP_CIPHER_CTX_set_key_length) + RESOLVEFUNC(EVP_CipherInit) + RESOLVEFUNC(EVP_CipherUpdate) + RESOLVEFUNC(EVP_CipherFinal) + RESOLVEFUNC(EVP_des_cbc) RESOLVEFUNC(EVP_des_ede3_cbc) + RESOLVEFUNC(EVP_rc2_cbc) RESOLVEFUNC(EVP_PKEY_assign) RESOLVEFUNC(EVP_PKEY_set1_RSA) RESOLVEFUNC(EVP_PKEY_set1_DSA) diff --git a/src/network/ssl/qsslsocket_openssl_symbols_p.h b/src/network/ssl/qsslsocket_openssl_symbols_p.h index a15bf4b87d..7f87f11b7c 100644 --- a/src/network/ssl/qsslsocket_openssl_symbols_p.h +++ b/src/network/ssl/qsslsocket_openssl_symbols_p.h @@ -235,7 +235,16 @@ X509 *q_d2i_X509(X509 **a, const unsigned char **b, long c); char *q_ERR_error_string(unsigned long a, char *b); unsigned long q_ERR_get_error(); void q_ERR_free_strings(); +void q_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *a); +void q_EVP_CIPHER_CTX_init(EVP_CIPHER_CTX *a); +int q_EVP_CIPHER_CTX_ctrl(EVP_CIPHER_CTX *ctx, int type, int arg, void *ptr); +int q_EVP_CIPHER_CTX_set_key_length(EVP_CIPHER_CTX *x, int keylen); +int q_EVP_CipherInit(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, const unsigned char *key, const unsigned char *iv, int enc); +int q_EVP_CipherUpdate(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl, const unsigned char *in, int inl); +int q_EVP_CipherFinal(EVP_CIPHER_CTX *ctx, unsigned char *out, int *outl); +const EVP_CIPHER *q_EVP_des_cbc(); const EVP_CIPHER *q_EVP_des_ede3_cbc(); +const EVP_CIPHER *q_EVP_rc2_cbc(); int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); Q_AUTOTEST_EXPORT int q_EVP_PKEY_set1_RSA(EVP_PKEY *a, RSA *b); int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b); diff --git a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp index d570037015..a7957d3288 100644 --- a/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp +++ b/tests/auto/network/ssl/qsslkey/tst_qsslkey.cpp @@ -39,7 +39,7 @@ #include #include -#if !defined(QT_NO_SSL) && defined(QT_NO_OPENSSL) && defined(QT_BUILD_INTERNAL) +#if !defined(QT_NO_SSL) && defined(QT_BUILD_INTERNAL) #include "private/qsslkey_p.h" #define TEST_CRYPTO #endif -- cgit v1.2.3