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 <andrew.knight@intopalo.com>
Reviewed-by: Richard J. Moore <rich@kde.org>
This commit is contained in:
Jeremy Lainé 2014-09-01 11:13:17 +02:00
parent a92a72dd11
commit 49fee77ccc
5 changed files with 87 additions and 10 deletions

View File

@ -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<const unsigned char *>(key.constData()),
reinterpret_cast<const unsigned char *>(iv.constData()), enc);
q_EVP_CipherUpdate(&ctx,
reinterpret_cast<unsigned char *>(output.data()), &len,
reinterpret_cast<const unsigned char *>(data.constData()), data.size());
q_EVP_CipherFinal(&ctx,
reinterpret_cast<unsigned char *>(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 QT_END_NAMESPACE

View File

@ -90,6 +90,16 @@ public:
bool isNull; bool isNull;
QSsl::KeyType type; QSsl::KeyType type;
QSsl::KeyAlgorithm algorithm; 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 #ifndef QT_NO_OPENSSL
union { union {
EVP_PKEY *opaque; EVP_PKEY *opaque;
@ -100,15 +110,6 @@ public:
#endif #endif
}; };
#else #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; Qt::HANDLE opaque;
QByteArray derData; QByteArray derData;
int keyLength; int keyLength;

View File

@ -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) 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(unsigned long, ERR_get_error, DUMMYARG, DUMMYARG, return 0, return)
DEFINEFUNC(void, ERR_free_strings, void, DUMMYARG, return, DUMMYARG) 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_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) 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_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) 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_error_string)
RESOLVEFUNC(ERR_get_error) RESOLVEFUNC(ERR_get_error)
RESOLVEFUNC(ERR_free_strings) 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_des_ede3_cbc)
RESOLVEFUNC(EVP_rc2_cbc)
RESOLVEFUNC(EVP_PKEY_assign) RESOLVEFUNC(EVP_PKEY_assign)
RESOLVEFUNC(EVP_PKEY_set1_RSA) RESOLVEFUNC(EVP_PKEY_set1_RSA)
RESOLVEFUNC(EVP_PKEY_set1_DSA) RESOLVEFUNC(EVP_PKEY_set1_DSA)

View File

@ -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); char *q_ERR_error_string(unsigned long a, char *b);
unsigned long q_ERR_get_error(); unsigned long q_ERR_get_error();
void q_ERR_free_strings(); 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_des_ede3_cbc();
const EVP_CIPHER *q_EVP_rc2_cbc();
int q_EVP_PKEY_assign(EVP_PKEY *a, int b, char *c); 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); 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); int q_EVP_PKEY_set1_DSA(EVP_PKEY *a, DSA *b);

View File

@ -39,7 +39,7 @@
#include <QtNetwork/qhostaddress.h> #include <QtNetwork/qhostaddress.h>
#include <QtNetwork/qnetworkproxy.h> #include <QtNetwork/qnetworkproxy.h>
#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" #include "private/qsslkey_p.h"
#define TEST_CRYPTO #define TEST_CRYPTO
#endif #endif