2003-07-20 13:40:20 +00:00
|
|
|
#include"qcaopenssl.h"
|
2003-07-02 16:59:53 +00:00
|
|
|
|
|
|
|
#include<qptrlist.h>
|
|
|
|
#include<openssl/sha.h>
|
2003-07-03 02:23:29 +00:00
|
|
|
#include<openssl/md5.h>
|
2003-07-09 00:31:45 +00:00
|
|
|
#include<openssl/evp.h>
|
2003-07-20 21:10:30 +00:00
|
|
|
#include<openssl/bio.h>
|
|
|
|
#include<openssl/pem.h>
|
2003-07-11 21:30:48 +00:00
|
|
|
#include<openssl/rsa.h>
|
|
|
|
#include<openssl/x509.h>
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-10 23:23:40 +00:00
|
|
|
#include<stdlib.h>
|
|
|
|
static bool seeded = false;
|
|
|
|
class QRandom
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
static uchar randomChar();
|
|
|
|
static uint randomInt();
|
|
|
|
static QByteArray randomArray(uint size);
|
|
|
|
};
|
|
|
|
|
|
|
|
uchar QRandom::randomChar()
|
|
|
|
{
|
|
|
|
if(!seeded) {
|
|
|
|
srand(time(NULL));
|
|
|
|
seeded = true;
|
|
|
|
}
|
|
|
|
return rand();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint QRandom::randomInt()
|
|
|
|
{
|
|
|
|
QByteArray a = randomArray(sizeof(uint));
|
|
|
|
uint x;
|
|
|
|
memcpy(&x, a.data(), a.size());
|
|
|
|
return x;
|
|
|
|
}
|
|
|
|
|
|
|
|
QByteArray QRandom::randomArray(uint size)
|
|
|
|
{
|
|
|
|
QByteArray a(size);
|
|
|
|
for(uint n = 0; n < size; ++n)
|
|
|
|
a[n] = randomChar();
|
|
|
|
return a;
|
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
static bool lib_generateKeyIV(const EVP_CIPHER *type, const QByteArray &data, const QByteArray &salt, QByteArray *key, QByteArray *iv)
|
|
|
|
{
|
|
|
|
QByteArray k, i;
|
|
|
|
unsigned char *kp = 0;
|
|
|
|
unsigned char *ip = 0;
|
|
|
|
if(key) {
|
|
|
|
k.resize(type->key_len);
|
|
|
|
kp = (unsigned char *)k.data();
|
|
|
|
}
|
|
|
|
if(iv) {
|
|
|
|
i.resize(type->iv_len);
|
|
|
|
ip = (unsigned char *)i.data();
|
|
|
|
}
|
|
|
|
if(!EVP_BytesToKey(type, EVP_sha1(), (unsigned char *)salt.data(), (unsigned char *)data.data(), data.size(), 1, kp, ip))
|
|
|
|
return false;
|
|
|
|
if(key)
|
|
|
|
*key = k;
|
|
|
|
if(iv)
|
|
|
|
*iv = i;
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-11 21:30:48 +00:00
|
|
|
|
2003-07-09 00:31:45 +00:00
|
|
|
static void appendArray(QByteArray *a, const QByteArray &b)
|
|
|
|
{
|
|
|
|
int oldsize = a->size();
|
|
|
|
a->resize(oldsize + b.size());
|
|
|
|
memcpy(a->data() + oldsize, b.data(), b.size());
|
|
|
|
}
|
|
|
|
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class SHA1Context : public QCA_HashContext
|
2003-07-02 16:59:53 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
SHA1Context()
|
|
|
|
{
|
|
|
|
reset();
|
|
|
|
}
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
SHA1_Init(&c);
|
|
|
|
}
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void update(const char *in, unsigned int len)
|
|
|
|
{
|
|
|
|
SHA1_Update(&c, in, len);
|
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void final(char **out, unsigned int *outlen)
|
|
|
|
{
|
|
|
|
*outlen = 20;
|
|
|
|
unsigned char *outbuf = (unsigned char *)malloc(*outlen);
|
|
|
|
SHA1_Final(outbuf, &c);
|
|
|
|
*out = (char *)outbuf;
|
|
|
|
}
|
|
|
|
|
|
|
|
SHA_CTX c;
|
2003-07-11 21:30:48 +00:00
|
|
|
};
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class MD5Context : public QCA_HashContext
|
2003-07-02 16:59:53 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
MD5Context()
|
|
|
|
{
|
|
|
|
reset();
|
2003-07-02 16:59:53 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
MD5_Init(&c);
|
2003-07-03 02:23:29 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void update(const char *in, unsigned int len)
|
|
|
|
{
|
|
|
|
MD5_Update(&c, in, len);
|
2003-07-09 00:31:45 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void final(char **out, unsigned int *outlen)
|
|
|
|
{
|
|
|
|
*outlen = 16;
|
|
|
|
unsigned char *outbuf = (unsigned char *)malloc(*outlen);
|
|
|
|
MD5_Final(outbuf, &c);
|
|
|
|
*out = (char *)outbuf;
|
2003-07-11 21:30:48 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
MD5_CTX c;
|
|
|
|
};
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class EVPCipherContext : public QCA_CipherContext
|
2003-07-02 16:59:53 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
EVPCipherContext()
|
|
|
|
{
|
|
|
|
type = 0;
|
|
|
|
}
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
virtual ~EVPCipherContext()
|
|
|
|
{
|
|
|
|
memset(&c, 0, sizeof(EVP_CIPHER_CTX));
|
|
|
|
}
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
virtual const EVP_CIPHER *getType(int mode) const=0;
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-21 16:44:45 +00:00
|
|
|
int keySize() { return getType(QCA::CBC)->key_len; }
|
|
|
|
int blockSize() { return getType(QCA::CBC)->block_size; }
|
2003-07-02 16:59:53 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool generateKey(char *out)
|
|
|
|
{
|
|
|
|
QByteArray a;
|
|
|
|
if(!lib_generateKeyIV(getType(QCA::CBC), QRandom::randomArray(128), QRandom::randomArray(2), &a, 0))
|
|
|
|
return false;
|
|
|
|
memcpy(out, a.data(), a.size());
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool generateIV(char *out)
|
|
|
|
{
|
|
|
|
QByteArray a;
|
|
|
|
if(!lib_generateKeyIV(getType(QCA::CBC), QRandom::randomArray(128), QRandom::randomArray(2), 0, &a))
|
|
|
|
return false;
|
|
|
|
memcpy(out, a.data(), a.size());
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-10 17:31:04 +00:00
|
|
|
|
2003-07-21 17:48:23 +00:00
|
|
|
bool setup(int _dir, int mode, const char *key, const char *iv, bool _pad)
|
2003-07-20 13:40:20 +00:00
|
|
|
{
|
|
|
|
dir = _dir;
|
2003-07-21 17:48:23 +00:00
|
|
|
pad = _pad;
|
2003-07-20 13:40:20 +00:00
|
|
|
type = getType(mode);
|
2003-07-21 16:44:45 +00:00
|
|
|
r.resize(0);
|
2003-07-20 13:40:20 +00:00
|
|
|
EVP_CIPHER_CTX_init(&c);
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
if(dir == QCA::Encrypt) {
|
2003-07-21 17:48:23 +00:00
|
|
|
if(!EVP_EncryptInit(&c, type, (unsigned char *)key, (unsigned char *)iv))
|
2003-07-20 13:40:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
2003-07-21 17:48:23 +00:00
|
|
|
if(!EVP_DecryptInit(&c, type, (unsigned char *)key, (unsigned char *)iv))
|
2003-07-20 13:40:20 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool update(const char *in, unsigned int len)
|
|
|
|
{
|
|
|
|
QByteArray result(len + type->block_size);
|
|
|
|
int olen;
|
2003-07-21 17:48:23 +00:00
|
|
|
if(dir == QCA::Encrypt || !pad) {
|
2003-07-20 13:40:20 +00:00
|
|
|
if(!EVP_EncryptUpdate(&c, (unsigned char *)result.data(), &olen, (const unsigned char *)in, len))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(!EVP_DecryptUpdate(&c, (unsigned char *)result.data(), &olen, (const unsigned char *)in, len))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result.resize(olen);
|
|
|
|
appendArray(&r, result);
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool final(char **out, unsigned int *outlen)
|
|
|
|
{
|
2003-07-21 17:48:23 +00:00
|
|
|
if(pad) {
|
|
|
|
QByteArray result(type->block_size);
|
|
|
|
int olen;
|
|
|
|
if(dir == QCA::Encrypt) {
|
|
|
|
if(!EVP_EncryptFinal(&c, (unsigned char *)result.data(), &olen))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(!EVP_DecryptFinal(&c, (unsigned char *)result.data(), &olen))
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
result.resize(olen);
|
|
|
|
appendArray(&r, result);
|
2003-07-20 13:40:20 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
*outlen = r.size();
|
|
|
|
unsigned char *outbuf = (unsigned char *)malloc(*outlen);
|
|
|
|
*out = (char *)outbuf;
|
|
|
|
memcpy(outbuf, r.data(), r.size());
|
2003-07-21 16:44:45 +00:00
|
|
|
|
|
|
|
r.resize(0);
|
2003-07-20 13:40:20 +00:00
|
|
|
return true;
|
|
|
|
}
|
2003-07-03 02:23:29 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
EVP_CIPHER_CTX c;
|
|
|
|
const EVP_CIPHER *type;
|
|
|
|
QByteArray r;
|
|
|
|
int dir;
|
2003-07-21 17:48:23 +00:00
|
|
|
bool pad;
|
2003-07-20 13:40:20 +00:00
|
|
|
};
|
2003-07-10 17:31:04 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class BlowFishContext : public EVPCipherContext
|
2003-07-10 23:23:40 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
const EVP_CIPHER *getType(int mode) const
|
|
|
|
{
|
|
|
|
if(mode == QCA::CBC)
|
|
|
|
return EVP_bf_cbc();
|
|
|
|
else if(mode == QCA::CFB)
|
|
|
|
return EVP_bf_cfb();
|
|
|
|
else
|
|
|
|
return 0;
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
};
|
2003-07-10 23:23:40 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class TripleDESContext : public EVPCipherContext
|
2003-07-10 23:23:40 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
const EVP_CIPHER *getType(int mode) const
|
|
|
|
{
|
|
|
|
if(mode == QCA::CBC)
|
|
|
|
return EVP_des_ede3_cbc();
|
|
|
|
else if(mode == QCA::CFB)
|
|
|
|
return EVP_des_ede3_cfb();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2003-07-10 23:23:40 +00:00
|
|
|
|
2003-07-21 16:44:45 +00:00
|
|
|
class AES128Context : public EVPCipherContext
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
const EVP_CIPHER *getType(int mode) const
|
|
|
|
{
|
|
|
|
if(mode == QCA::CBC)
|
|
|
|
return EVP_aes_128_cbc();
|
|
|
|
else if(mode == QCA::CFB)
|
|
|
|
return EVP_aes_128_cfb();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class AES256Context : public EVPCipherContext
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
const EVP_CIPHER *getType(int mode) const
|
|
|
|
{
|
|
|
|
if(mode == QCA::CBC)
|
|
|
|
return EVP_aes_256_cbc();
|
|
|
|
else if(mode == QCA::CFB)
|
|
|
|
return EVP_aes_256_cfb();
|
|
|
|
else
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class RSAKeyContext : public QCA_RSAKeyContext
|
2003-07-09 00:31:45 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
RSAKeyContext()
|
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
pub = 0;
|
|
|
|
sec = 0;
|
2003-07-20 13:40:20 +00:00
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
~RSAKeyContext()
|
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
reset();
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset()
|
|
|
|
{
|
|
|
|
if(pub) {
|
|
|
|
RSA_free(pub);
|
|
|
|
pub = 0;
|
|
|
|
}
|
|
|
|
if(sec) {
|
|
|
|
RSA_free(sec);
|
|
|
|
sec = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void separate(RSA *r, RSA **pub, RSA **sec)
|
|
|
|
{
|
|
|
|
// public
|
|
|
|
unsigned char *buf, *p;
|
|
|
|
int len = i2d_RSAPublicKey(r, NULL);
|
|
|
|
if(len > 0) {
|
|
|
|
buf = (unsigned char *)malloc(len);
|
|
|
|
p = buf;
|
|
|
|
i2d_RSAPublicKey(r, &p);
|
|
|
|
p = buf;
|
|
|
|
*pub = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len);
|
|
|
|
free(buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
len = i2d_RSAPrivateKey(r, NULL);
|
|
|
|
if(len > 0) {
|
|
|
|
buf = (unsigned char *)malloc(len);
|
|
|
|
p = buf;
|
|
|
|
i2d_RSAPrivateKey(r, &p);
|
|
|
|
p = buf;
|
|
|
|
*sec = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len);
|
|
|
|
free(buf);
|
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool isNull() const
|
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
if(!pub && !sec)
|
|
|
|
return true;
|
|
|
|
return false;
|
2003-07-20 13:40:20 +00:00
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
bool havePublic() const
|
2003-07-20 13:40:20 +00:00
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
return pub ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool havePrivate() const
|
|
|
|
{
|
|
|
|
return sec ? true : false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool createFromDER(const char *in, unsigned int len)
|
|
|
|
{
|
|
|
|
RSA *r;
|
|
|
|
void *p;
|
|
|
|
|
|
|
|
// private?
|
|
|
|
p = (void *)in;
|
|
|
|
r = d2i_RSAPrivateKey(NULL, (const unsigned char **)&p, len);
|
|
|
|
if(r) {
|
|
|
|
reset();
|
|
|
|
|
|
|
|
// private means both, I think, so separate them
|
|
|
|
separate(r, &pub, &sec);
|
|
|
|
return true;
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
else {
|
2003-07-20 21:10:30 +00:00
|
|
|
// public?
|
|
|
|
p = (void *)in;
|
|
|
|
r = d2i_RSAPublicKey(NULL, (const unsigned char **)&p, len);
|
|
|
|
if(!r) {
|
|
|
|
// try this other public function, for whatever reason
|
|
|
|
p = (void *)in;
|
|
|
|
r = d2i_RSA_PUBKEY(NULL, (unsigned char **)&p, len);
|
|
|
|
}
|
|
|
|
if(r) {
|
|
|
|
if(pub)
|
|
|
|
RSA_free(pub);
|
|
|
|
pub = r;
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool createFromPEM(const char *in, unsigned int len)
|
|
|
|
{
|
|
|
|
BIO *bi;
|
|
|
|
|
|
|
|
// private?
|
|
|
|
bi = BIO_new(BIO_s_mem());
|
|
|
|
BIO_write(bi, in, len);
|
|
|
|
RSA *r = PEM_read_bio_RSAPrivateKey(bi, NULL, NULL, NULL);
|
|
|
|
BIO_free(bi);
|
|
|
|
if(r) {
|
|
|
|
reset();
|
|
|
|
separate(r, &pub, &sec);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
// public?
|
|
|
|
bi = BIO_new(BIO_s_mem());
|
|
|
|
BIO_write(bi, in, len);
|
|
|
|
r = PEM_read_bio_RSAPublicKey(bi, NULL, NULL, NULL);
|
|
|
|
BIO_free(bi);
|
|
|
|
if(r) {
|
|
|
|
if(pub)
|
|
|
|
RSA_free(pub);
|
|
|
|
pub = r;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return false;
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
bool createFromNative(void *in)
|
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
reset();
|
|
|
|
separate((RSA *)in, &pub, &sec);
|
2003-07-20 13:40:20 +00:00
|
|
|
return true;
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
|
|
|
|
bool generate(unsigned int bits)
|
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
|
|
|
if(!r)
|
2003-07-10 23:23:40 +00:00
|
|
|
return false;
|
2003-07-20 21:10:30 +00:00
|
|
|
separate(r, &pub, &sec);
|
|
|
|
RSA_free(r);
|
2003-07-20 13:40:20 +00:00
|
|
|
return true;
|
2003-07-10 23:23:40 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
QCA_RSAKeyContext *clone()
|
|
|
|
{
|
|
|
|
RSAKeyContext *c = new RSAKeyContext;
|
2003-07-20 21:10:30 +00:00
|
|
|
if(pub) {
|
|
|
|
++(pub->references);
|
|
|
|
c->pub = pub;
|
|
|
|
}
|
|
|
|
if(sec) {
|
|
|
|
++(sec->references);
|
|
|
|
c->sec = sec;
|
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
return c;
|
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
void toDER(char **out, unsigned int *outlen, bool publicOnly)
|
2003-07-20 13:40:20 +00:00
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
if(sec && !publicOnly) {
|
|
|
|
int len = i2d_RSAPrivateKey(sec, NULL);
|
|
|
|
unsigned char *buf, *p;
|
|
|
|
buf = (unsigned char *)malloc(len);
|
|
|
|
p = buf;
|
|
|
|
i2d_RSAPrivateKey(sec, &p);
|
|
|
|
*out = (char *)buf;
|
|
|
|
*outlen = len;
|
|
|
|
}
|
|
|
|
else if(pub) {
|
|
|
|
int len = i2d_RSAPublicKey(pub, NULL);
|
|
|
|
unsigned char *buf, *p;
|
|
|
|
buf = (unsigned char *)malloc(len);
|
|
|
|
p = buf;
|
|
|
|
i2d_RSAPublicKey(pub, &p);
|
|
|
|
*out = (char *)buf;
|
|
|
|
*outlen = len;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*out = 0;
|
|
|
|
*outlen = 0;
|
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
}
|
2003-07-09 00:31:45 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
void toPEM(char **out, unsigned int *outlen, bool publicOnly)
|
2003-07-20 13:40:20 +00:00
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
BIO *bo;
|
|
|
|
if(sec && !publicOnly) {
|
|
|
|
bo = BIO_new(BIO_s_mem());
|
|
|
|
PEM_write_bio_RSAPrivateKey(bo, sec, NULL, NULL, 0, NULL, NULL);
|
|
|
|
}
|
|
|
|
else if(pub) {
|
|
|
|
bo = BIO_new(BIO_s_mem());
|
|
|
|
PEM_write_bio_RSAPublicKey(bo, pub);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*out = 0;
|
|
|
|
*outlen = 0;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
char *buf = (char *)malloc(1);
|
|
|
|
int size = 0;
|
|
|
|
while(1) {
|
|
|
|
char block[1024];
|
|
|
|
int ret = BIO_read(bo, block, 1024);
|
|
|
|
buf = (char *)realloc(buf, size + ret);
|
|
|
|
memcpy(buf + size, block, ret);
|
|
|
|
size += ret;
|
|
|
|
if(ret != 1024)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
BIO_free(bo);
|
|
|
|
*out = buf;
|
|
|
|
*outlen = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool encrypt(const char *in, unsigned int len, char **out, unsigned int *outlen, bool oaep)
|
|
|
|
{
|
|
|
|
if(!pub)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int size = RSA_size(pub);
|
2003-07-20 13:40:20 +00:00
|
|
|
int flen = len;
|
2003-07-20 21:10:30 +00:00
|
|
|
if(oaep) {
|
|
|
|
if(flen >= size - 41)
|
|
|
|
flen = size - 41;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
if(flen >= size - 11)
|
|
|
|
flen = size - 11;
|
|
|
|
}
|
2003-07-20 13:40:20 +00:00
|
|
|
QByteArray result(size);
|
|
|
|
unsigned char *from = (unsigned char *)in;
|
|
|
|
unsigned char *to = (unsigned char *)result.data();
|
2003-07-20 21:10:30 +00:00
|
|
|
int ret = RSA_public_encrypt(flen, from, to, pub, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
|
2003-07-20 13:40:20 +00:00
|
|
|
if(ret == -1)
|
|
|
|
return false;
|
|
|
|
result.resize(ret);
|
2003-07-11 21:30:48 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
*out = (char *)malloc(result.size());
|
|
|
|
memcpy((*out), result.data(), result.size());
|
|
|
|
*outlen = result.size();
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-20 10:49:34 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
bool decrypt(const char *in, unsigned int len, char **out, unsigned int *outlen, bool oaep)
|
2003-07-20 13:40:20 +00:00
|
|
|
{
|
2003-07-20 21:10:30 +00:00
|
|
|
if(!sec)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
int size = RSA_size(sec);
|
2003-07-20 13:40:20 +00:00
|
|
|
int flen = len;
|
|
|
|
QByteArray result(size);
|
|
|
|
unsigned char *from = (unsigned char *)in;
|
|
|
|
unsigned char *to = (unsigned char *)result.data();
|
2003-07-20 21:10:30 +00:00
|
|
|
int ret = RSA_private_decrypt(flen, from, to, sec, oaep ? RSA_PKCS1_OAEP_PADDING : RSA_PKCS1_PADDING);
|
2003-07-20 13:40:20 +00:00
|
|
|
if(ret == -1)
|
|
|
|
return false;
|
|
|
|
result.resize(ret);
|
2003-07-20 10:49:34 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
*out = (char *)malloc(result.size());
|
|
|
|
memcpy((*out), result.data(), result.size());
|
|
|
|
*outlen = result.size();
|
|
|
|
return true;
|
|
|
|
}
|
2003-07-11 21:30:48 +00:00
|
|
|
|
2003-07-20 21:10:30 +00:00
|
|
|
RSA *pub, *sec;
|
2003-07-20 13:40:20 +00:00
|
|
|
};
|
2003-07-11 21:30:48 +00:00
|
|
|
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
class QCAOpenSSL : public QCAProvider
|
2003-07-11 21:30:48 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
public:
|
|
|
|
QCAOpenSSL() {}
|
|
|
|
~QCAOpenSSL() {}
|
2003-07-11 21:30:48 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
int capabilities() const
|
|
|
|
{
|
2003-07-21 16:44:45 +00:00
|
|
|
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_BlowFish | QCA::CAP_TripleDES | QCA::CAP_AES128 | QCA::CAP_AES256 | QCA::CAP_RSA);
|
2003-07-11 21:30:48 +00:00
|
|
|
}
|
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
void *functions(int cap)
|
|
|
|
{
|
|
|
|
if(cap == QCA::CAP_SHA1)
|
|
|
|
return new SHA1Context;
|
|
|
|
else if(cap == QCA::CAP_MD5)
|
|
|
|
return new MD5Context;
|
|
|
|
else if(cap == QCA::CAP_BlowFish)
|
|
|
|
return new BlowFishContext;
|
|
|
|
else if(cap == QCA::CAP_TripleDES)
|
|
|
|
return new TripleDESContext;
|
2003-07-21 16:44:45 +00:00
|
|
|
else if(cap == QCA::CAP_AES128)
|
|
|
|
return new AES128Context;
|
|
|
|
else if(cap == QCA::CAP_AES256)
|
|
|
|
return new AES256Context;
|
2003-07-20 13:40:20 +00:00
|
|
|
else if(cap == QCA::CAP_RSA)
|
|
|
|
return new RSAKeyContext;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
};
|
2003-07-11 21:30:48 +00:00
|
|
|
|
2003-07-20 13:40:20 +00:00
|
|
|
#ifdef QCA_PLUGIN
|
|
|
|
QCAProvider *createProvider()
|
|
|
|
#else
|
|
|
|
QCAProvider *createProviderOpenSSL()
|
|
|
|
#endif
|
2003-07-11 21:30:48 +00:00
|
|
|
{
|
2003-07-20 13:40:20 +00:00
|
|
|
return (new QCAOpenSSL);
|
2003-07-14 14:45:27 +00:00
|
|
|
}
|