changed plugin system to use C++

svn path=/trunk/kdesupport/qca/; revision=238159
This commit is contained in:
Justin Karneges 2003-07-20 13:40:20 +00:00
parent 4a286c05a1
commit e6adfbd2b3
10 changed files with 461 additions and 646 deletions

2
TODO
View File

@ -1,3 +1,4 @@
* rsakey: to DER
* rsakey: to/from PEM
* rsakey: detect for private/public capability (get rid of 'bool sec')
* rsa: choice of pad
@ -5,6 +6,7 @@
* cipher: better handling of errors ('empty' arrays are not a good idea)
* cipher: ability to disable pkcs padding
* cipher: better entropy for keygen?
* cipher: aes128, aes256
* clean up openssl plugin
* ssl/tls/x509 (also server support)

View File

@ -9,6 +9,27 @@ int main(int argc, char **argv)
QCA::init();
QCString cs = (argc >= 2) ? argv[1] : "hello";
if(!QCA::isSupported(QCA::CAP_BlowFish))
printf("BlowFish not supported!\n");
else {
// encrypt
QByteArray key = QCA::BlowFish::generateKey();
QByteArray iv = QCA::BlowFish::generateIV();
printf("bfish:key:%s\n", QCA::arrayToHex(key).latin1());
printf("bfish:iv:%s\n", QCA::arrayToHex(iv).latin1());
QCA::BlowFish c(QCA::Encrypt, QCA::CBC, key, iv);
c.update(cstringToArray(cs));
QByteArray f = c.final();
QString result = QCA::arrayToHex(f);
printf(">bfish(\"%s\") = [%s]\n", cs.data(), result.latin1());
// decrypt
QCA::BlowFish d(QCA::Decrypt, QCA::CBC, key, iv);
d.update(f);
QCString dec = arrayToCString(d.final());
printf("<bfish(\"%s\") = [%s]\n", result.latin1(), dec.data());
}
if(!QCA::isSupported(QCA::CAP_TripleDES))
printf("TripleDES not supported!\n");
else {
@ -17,14 +38,14 @@ int main(int argc, char **argv)
QByteArray iv = QCA::TripleDES::generateIV();
printf("3des:key:%s\n", QCA::arrayToHex(key).latin1());
printf("3des:iv:%s\n", QCA::arrayToHex(iv).latin1());
QCA::TripleDES c(QCA::Encrypt, key, iv);
QCA::TripleDES c(QCA::Encrypt, QCA::CBC, key, iv);
c.update(cstringToArray(cs));
QByteArray f = c.final();
QString result = QCA::arrayToHex(f);
printf(">3des(\"%s\") = [%s]\n", cs.data(), result.latin1());
// decrypt
QCA::TripleDES d(QCA::Decrypt, key, iv);
QCA::TripleDES d(QCA::Decrypt, QCA::CBC, key, iv);
d.update(f);
QCString dec = arrayToCString(d.final());
printf("<3des(\"%s\") = [%s]\n", result.latin1(), dec.data());
@ -36,14 +57,14 @@ int main(int argc, char **argv)
// encrypt
QByteArray key = QCA::AES128::generateKey();
QByteArray iv = QCA::AES128::generateIV();
QCA::AES128 c(QCA::Encrypt, key, iv);
QCA::AES128 c(QCA::Encrypt, QCA::CBC, key, iv);
c.update(cstringToArray(cs));
QByteArray f = c.final();
QString result = QCA::arrayToHex(f);
printf(">aes128(\"%s\") = [%s]\n", cs.data(), result.latin1());
// decrypt
QCA::AES128 d(QCA::Decrypt, key, iv);
QCA::AES128 d(QCA::Decrypt, QCA::CBC, key, iv);
d.update(f);
QCString dec = arrayToCString(d.final());
printf("<aes128(\"%s\") = [%s]\n", result.latin1(), dec.data());

View File

@ -1,4 +1,4 @@
#include"qcaopenssl_p.h"
#include"qcaopenssl.h"
#include<qptrlist.h>
#include<openssl/sha.h>
@ -7,13 +7,6 @@
#include<openssl/rsa.h>
#include<openssl/x509.h>
#ifdef QCA_PLUGIN
QCAProvider *createProvider()
{
return (new _QCAOpenSSL);
}
#endif
#include<stdlib.h>
static bool seeded = false;
class QRandom
@ -49,268 +42,6 @@ QByteArray QRandom::randomArray(uint size)
return a;
}
static int sha1_create();
static void sha1_destroy(int ctx);
static void sha1_update(int ctx, const char *in, unsigned int len);
static void sha1_final(int ctx, char *out);
static unsigned int sha1_finalSize(int ctx);
static int md5_create();
static void md5_destroy(int ctx);
static void md5_update(int ctx, const char *in, unsigned int len);
static void md5_final(int ctx, char *out);
static unsigned int md5_finalSize(int ctx);
static int tdes_keySize() { return 24; }
static int tdes_blockSize() { return 8; }
static bool tdes_generateKey(char *out);
static bool tdes_generateIV(char *out);
static int tdes_create();
static void tdes_destroy(int ctx);
static bool tdes_setup(int ctx, int dir, int mode, const char *key, const char *iv);
static bool tdes_update(int ctx, const char *in, unsigned int len);
static bool tdes_final(int ctx, char *out);
static unsigned int tdes_finalSize(int ctx);
static int rsa_keyCreateFromDER(const char *in, unsigned int len, bool sec);
static int rsa_keyCreateFromNative(void *in);
static int rsa_keyCreateGenerate(unsigned int bits);
static int rsa_keyClone(int ctx);
static void rsa_keyDestroy(int ctx);
static void rsa_keyToDER(int ctx, char **out, unsigned int *len);
static bool rsa_encrypt(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen);
static bool rsa_decrypt(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen);
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());
}
static int counter = 0;
struct pair_sha1
{
int ctx;
SHA_CTX c;
};
typedef QPtrList<pair_sha1> MAP_SHA1;
MAP_SHA1 *map = 0;
struct pair_md5
{
int ctx;
MD5_CTX c;
};
typedef QPtrList<pair_md5> MAP_MD5;
MAP_MD5 *map_md5 = 0;
struct pair_tdes
{
int ctx;
EVP_CIPHER_CTX c;
const EVP_CIPHER *type;
QByteArray r;
int dir;
bool done;
bool err;
};
typedef QPtrList<pair_tdes> MAP_TDES;
MAP_TDES *map_tdes = 0;
struct pair_rsakey
{
int ctx;
RSA *r;
};
typedef QPtrList<pair_rsakey> MAP_RSAKEY;
MAP_RSAKEY *map_rsakey = 0;
static pair_sha1 *find(int ctx)
{
QPtrListIterator<pair_sha1> it(*map);
for(pair_sha1 *p; (p = it.current()); ++it) {
if(p->ctx == ctx)
return p;
}
return 0;
}
static pair_md5 *find_md5(int ctx)
{
QPtrListIterator<pair_md5> it(*map_md5);
for(pair_md5 *p; (p = it.current()); ++it) {
if(p->ctx == ctx)
return p;
}
return 0;
}
static pair_tdes *find_tdes(int ctx)
{
QPtrListIterator<pair_tdes> it(*map_tdes);
for(pair_tdes *p; (p = it.current()); ++it) {
if(p->ctx == ctx)
return p;
}
return 0;
}
static pair_rsakey *find_rsakey(int ctx)
{
QPtrListIterator<pair_rsakey> it(*map_rsakey);
for(pair_rsakey *p; (p = it.current()); ++it) {
if(p->ctx == ctx)
return p;
}
return 0;
}
_QCAOpenSSL::_QCAOpenSSL()
{
map = new MAP_SHA1;
map->setAutoDelete(true);
map_md5 = new MAP_MD5;
map_md5->setAutoDelete(true);
map_tdes = new MAP_TDES;
map_tdes->setAutoDelete(true);
map_rsakey = new MAP_RSAKEY;
map_rsakey->setAutoDelete(true);
}
_QCAOpenSSL::~_QCAOpenSSL()
{
delete map;
map = 0;
delete map_md5;
map_md5 = 0;
delete map_tdes;
map_tdes = 0;
delete map_rsakey;
map_rsakey = 0;
}
int _QCAOpenSSL::capabilities() const
{
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_TripleDES | QCA::CAP_RSA);
}
void *_QCAOpenSSL::functions(int cap)
{
if(cap == QCA::CAP_SHA1) {
QCA_HashFunctions *f = new QCA_HashFunctions;
f->create = sha1_create;
f->destroy = sha1_destroy;
f->update = sha1_update;
f->final = sha1_final;
f->finalSize = sha1_finalSize;
return f;
}
else if(cap == QCA::CAP_MD5) {
QCA_HashFunctions *f = new QCA_HashFunctions;
f->create = md5_create;
f->destroy = md5_destroy;
f->update = md5_update;
f->final = md5_final;
f->finalSize = md5_finalSize;
return f;
}
else if(cap == QCA::CAP_TripleDES) {
QCA_CipherFunctions *f = new QCA_CipherFunctions;
f->keySize = tdes_keySize;
f->blockSize = tdes_blockSize;
f->generateKey = tdes_generateKey;
f->generateIV = tdes_generateIV;
f->create = tdes_create;
f->destroy = tdes_destroy;
f->setup = tdes_setup;
f->update = tdes_update;
f->final = tdes_final;
f->finalSize = tdes_finalSize;
return f;
}
else if(cap == QCA::CAP_RSA) {
QCA_RSAFunctions *f = new QCA_RSAFunctions;
f->keyCreateFromDER = rsa_keyCreateFromDER;
f->keyCreateFromNative = rsa_keyCreateFromNative;
f->keyCreateGenerate = rsa_keyCreateGenerate;
f->keyClone = rsa_keyClone;
f->keyDestroy = rsa_keyDestroy;
f->keyToDER = rsa_keyToDER;
f->encrypt = rsa_encrypt;
f->decrypt = rsa_decrypt;
return f;
}
return 0;
}
int sha1_create()
{
pair_sha1 *i = new pair_sha1;
i->ctx = counter++;
SHA1_Init(&i->c);
map->append(i);
return i->ctx;
}
void sha1_destroy(int ctx)
{
pair_sha1 *i = find(ctx);
map->removeRef(i);
}
void sha1_update(int ctx, const char *in, unsigned int len)
{
pair_sha1 *i = find(ctx);
SHA1_Update(&i->c, in, len);
}
void sha1_final(int ctx, char *out)
{
pair_sha1 *i = find(ctx);
SHA1_Final((unsigned char *)out, &i->c);
}
unsigned int sha1_finalSize(int)
{
return 20;
}
int md5_create()
{
pair_md5 *i = new pair_md5;
i->ctx = counter++;
MD5_Init(&i->c);
map_md5->append(i);
return i->ctx;
}
void md5_destroy(int ctx)
{
pair_md5 *i = find_md5(ctx);
map_md5->removeRef(i);
}
void md5_update(int ctx, const char *in, unsigned int len)
{
pair_md5 *i = find_md5(ctx);
MD5_Update(&i->c, in, len);
}
void md5_final(int ctx, char *out)
{
pair_md5 *i = find_md5(ctx);
MD5_Final((unsigned char *)out, &i->c);
}
unsigned int md5_finalSize(int)
{
return 16;
}
static bool lib_generateKeyIV(const EVP_CIPHER *type, const QByteArray &data, const QByteArray &salt, QByteArray *key, QByteArray *iv)
{
QByteArray k, i;
@ -333,246 +64,340 @@ static bool lib_generateKeyIV(const EVP_CIPHER *type, const QByteArray &data, co
return true;
}
bool tdes_generateKey(char *out)
static void appendArray(QByteArray *a, const QByteArray &b)
{
const EVP_CIPHER *type = EVP_des_ede3_cbc();
QByteArray a;
if(!lib_generateKeyIV(type, QRandom::randomArray(128), QRandom::randomArray(2), &a, 0))
return false;
memcpy(out, a.data(), a.size());
return true;
int oldsize = a->size();
a->resize(oldsize + b.size());
memcpy(a->data() + oldsize, b.data(), b.size());
}
bool tdes_generateIV(char *out)
{
const EVP_CIPHER *type = EVP_des_ede3_cbc();
QByteArray a;
if(!lib_generateKeyIV(type, QRandom::randomArray(128), QRandom::randomArray(2), 0, &a))
return false;
memcpy(out, a.data(), a.size());
return true;
}
int tdes_create()
class SHA1Context : public QCA_HashContext
{
pair_tdes *i = new pair_tdes;
i->ctx = counter++;
i->type = EVP_des_ede3_cbc();
i->dir = 0;
i->done = false;
i->err = false;
EVP_CIPHER_CTX_init(&i->c);
map_tdes->append(i);
return i->ctx;
}
public:
SHA1Context()
{
reset();
}
void tdes_destroy(int ctx)
void reset()
{
SHA1_Init(&c);
}
void update(const char *in, unsigned int len)
{
SHA1_Update(&c, in, len);
}
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;
};
class MD5Context : public QCA_HashContext
{
pair_tdes *i = find_tdes(ctx);
memset(&i->c, 0, sizeof(EVP_CIPHER_CTX));
map_tdes->removeRef(i);
}
public:
MD5Context()
{
reset();
}
bool tdes_setup(int ctx, int dir, int mode, const char *key, const char *iv)
void reset()
{
MD5_Init(&c);
}
void update(const char *in, unsigned int len)
{
MD5_Update(&c, in, len);
}
void final(char **out, unsigned int *outlen)
{
*outlen = 16;
unsigned char *outbuf = (unsigned char *)malloc(*outlen);
MD5_Final(outbuf, &c);
*out = (char *)outbuf;
}
MD5_CTX c;
};
class EVPCipherContext : public QCA_CipherContext
{
pair_tdes *i = find_tdes(ctx);
i->dir = dir;
public:
EVPCipherContext()
{
type = 0;
}
if(i->dir == 0) {
if(!EVP_EncryptInit_ex(&i->c, i->type, NULL, (const unsigned char *)key, (const unsigned char *)iv)) {
virtual ~EVPCipherContext()
{
memset(&c, 0, sizeof(EVP_CIPHER_CTX));
}
virtual const EVP_CIPHER *getType(int mode) const=0;
int keySize() { return 24; }
int blockSize() { return 8; }
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;
}
else {
if(!EVP_DecryptInit_ex(&i->c, i->type, NULL, (const unsigned char *)key, (const unsigned char *)iv)) {
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;
}
return true;
}
bool tdes_update(int ctx, const char *in, unsigned int len)
bool setup(int _dir, int mode, const char *key, const char *iv)
{
dir = _dir;
type = getType(mode);
EVP_CIPHER_CTX_init(&c);
if(dir == QCA::Encrypt) {
if(!EVP_EncryptInit(&c, type, (unsigned char *)key, (unsigned char *)iv))
return false;
}
else {
if(!EVP_DecryptInit(&c, type, (unsigned char *)key, (unsigned char *)iv))
return false;
}
return true;
}
bool update(const char *in, unsigned int len)
{
QByteArray result(len + type->block_size);
int olen;
if(dir == QCA::Encrypt) {
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;
}
bool final(char **out, unsigned int *outlen)
{
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);
*outlen = r.size();
unsigned char *outbuf = (unsigned char *)malloc(*outlen);
*out = (char *)outbuf;
memcpy(outbuf, r.data(), r.size());
return true;
}
EVP_CIPHER_CTX c;
const EVP_CIPHER *type;
QByteArray r;
int dir;
};
class BlowFishContext : public EVPCipherContext
{
pair_tdes *i = find_tdes(ctx);
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;
}
};
i->done = false;
i->err = false;
QByteArray result(len + i->type->block_size);
int olen;
if(i->dir == 0) {
if(!EVP_EncryptUpdate(&i->c, (unsigned char *)result.data(), &olen, (const unsigned char *)in, len))
class TripleDESContext : public EVPCipherContext
{
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;
}
};
class RSAKeyContext : public QCA_RSAKeyContext
{
public:
RSAKeyContext()
{
r = 0;
}
~RSAKeyContext()
{
if(r)
RSA_free(r);
}
bool isNull() const
{
return (r ? false: true);
}
bool createFromDER(const char *in, unsigned int len, bool sec)
{
RSA *t;
if(sec) {
const unsigned char *p = (const unsigned char *)in;
t = d2i_RSAPrivateKey(NULL, &p, len);
}
else {
unsigned char *p = (unsigned char *)in;
t = d2i_RSA_PUBKEY(NULL, &p,len);
}
if(!t)
return false;
r = t;
return true;
}
else {
if(!EVP_DecryptUpdate(&i->c, (unsigned char *)result.data(), &olen, (const unsigned char *)in, len))
bool createFromNative(void *in)
{
r = (RSA *)in;
++(r->references);
return true;
}
bool generate(unsigned int bits)
{
RSA *t = RSA_generate_key(bits, RSA_F4, NULL, NULL);
if(!t)
return false;
r = t;
return true;
}
result.resize(olen);
appendArray(&i->r, result);
return true;
}
static void tdes_ensureFinal(pair_tdes *i)
{
if(i->done)
return;
QByteArray result(i->type->block_size);
int olen;
if(i->dir == 0) {
if(!EVP_EncryptFinal(&i->c, (unsigned char *)result.data(), &olen)) {
i->err = true;
return;
}
QCA_RSAKeyContext *clone()
{
RSAKeyContext *c = new RSAKeyContext;
if(r)
c->createFromNative(r);
return c;
}
else {
if(!EVP_DecryptFinal(&i->c, (unsigned char *)result.data(), &olen)) {
i->err = true;
return;
}
void toDER(char **out, unsigned int *len)
{
*out = 0;
*len = 0;
}
result.resize(olen);
appendArray(&i->r, result);
i->done = true;
}
bool tdes_final(int ctx, char *out)
{
pair_tdes *i = find_tdes(ctx);
if(i->err)
return false;
bool encrypt(const char *in, unsigned int len, char **out, unsigned int *outlen)
{
int size = RSA_size(r);
int flen = len;
if(flen >= size - 11)
flen = size - 11;
QByteArray result(size);
unsigned char *from = (unsigned char *)in;
unsigned char *to = (unsigned char *)result.data();
int ret = RSA_public_encrypt(flen, from, to, r, RSA_PKCS1_PADDING);
if(ret == -1)
return false;
result.resize(ret);
tdes_ensureFinal(i);
memcpy(out, i->r.data(), i->r.size());
return true;
}
*out = (char *)malloc(result.size());
memcpy((*out), result.data(), result.size());
*outlen = result.size();
return true;
}
unsigned int tdes_finalSize(int ctx)
{
pair_tdes *i = find_tdes(ctx);
tdes_ensureFinal(i);
return i->r.size();
}
bool decrypt(const char *in, unsigned int len, char **out, unsigned int *outlen)
{
int size = RSA_size(r);
int flen = len;
QByteArray result(size);
unsigned char *from = (unsigned char *)in;
unsigned char *to = (unsigned char *)result.data();
int ret = RSA_private_decrypt(flen, from, to, r, RSA_PKCS1_PADDING);
if(ret == -1)
return false;
result.resize(ret);
*out = (char *)malloc(result.size());
memcpy((*out), result.data(), result.size());
*outlen = result.size();
return true;
}
int rsa_keyCreateFromDER(const char *in, unsigned int len, bool sec)
{
RSA *r;
if(sec) {
const unsigned char *p = (const unsigned char *)in;
r = d2i_RSAPrivateKey(NULL, &p, len);
};
class QCAOpenSSL : public QCAProvider
{
public:
QCAOpenSSL() {}
~QCAOpenSSL() {}
int capabilities() const
{
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_BlowFish | QCA::CAP_TripleDES | QCA::CAP_RSA);
}
else {
unsigned char *p = (unsigned char *)in;
r = d2i_RSA_PUBKEY(NULL, &p,len);
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;
else if(cap == QCA::CAP_RSA)
return new RSAKeyContext;
return 0;
}
if(!r)
return -1;
};
pair_rsakey *i = new pair_rsakey;
i->ctx = counter++;
i->r = r;
map_rsakey->append(i);
//printf("created %d\n", i->ctx);
return i->ctx;
}
int rsa_keyCreateFromNative(void *in)
#ifdef QCA_PLUGIN
QCAProvider *createProvider()
#else
QCAProvider *createProviderOpenSSL()
#endif
{
RSA *r = (RSA *)in;
pair_rsakey *i = new pair_rsakey;
i->ctx = counter++;
i->r = r;
map_rsakey->append(i);
return i->ctx;
}
int rsa_keyClone(int ctx)
{
pair_rsakey *from = find_rsakey(ctx);
pair_rsakey *i = new pair_rsakey;
i->ctx = counter++;
++from->r->references;
i->r = from->r;
map_rsakey->append(i);
//printf("cloned %d to %d\n", from->ctx, i->ctx);
return i->ctx;
}
void rsa_keyDestroy(int ctx)
{
//printf("destroying %d\n", ctx);
pair_rsakey *i = find_rsakey(ctx);
RSA_free(i->r);
map_rsakey->removeRef(i);
}
void rsa_keyToDER(int ctx, char **out, unsigned int *len)
{
ctx = -1;
*out = 0;
*len = 0;
}
bool rsa_encrypt(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen)
{
pair_rsakey *i = find_rsakey(ctx);
//printf("using context %d [r=%p]\n", ctx, i->r);
int size = RSA_size(i->r);
int flen = len;
if(flen >= size - 11)
flen = size - 11;
QByteArray result(size);
unsigned char *from = (unsigned char *)in;
unsigned char *to = (unsigned char *)result.data();
int r = RSA_public_encrypt(flen, from, to, i->r, RSA_PKCS1_PADDING);
if(r == -1)
return false;
result.resize(r);
*out = (char *)malloc(result.size());
memcpy((*out), result.data(), result.size());
*outlen = result.size();
return true;
}
bool rsa_decrypt(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen)
{
pair_rsakey *i = find_rsakey(ctx);
if(!i) {
//printf("no key!!\n");
return false;
}
//printf("using context %d [r=%p]\n", ctx, i->r);
int size = RSA_size(i->r);
int flen = len;
QByteArray result(size);
unsigned char *from = (unsigned char *)in;
unsigned char *to = (unsigned char *)result.data();
//printf("about to decrypt\n");
int r = RSA_private_decrypt(flen, from, to, i->r, RSA_PKCS1_PADDING);
//printf("done decrypt\n");
if(r == -1)
return false;
result.resize(r);
*out = (char *)malloc(result.size());
memcpy((*out), result.data(), result.size());
*outlen = result.size();
return true;
}
int rsa_keyCreateGenerate(unsigned int bits)
{
RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL);
if(!r)
return -1;
pair_rsakey *i = new pair_rsakey;
i->ctx = counter++;
i->r = r;
map_rsakey->append(i);
return i->ctx;
return (new QCAOpenSSL);
}

View File

@ -5,12 +5,8 @@
#ifdef QCA_PLUGIN
QCA_EXPORT QCAProvider *createProvider();
#else
QCAProvider *createProviderOpenSSL();
#endif
class QCAOpenSSL : public QCAProvider
{
public:
QCAOpenSSL() {}
};
#endif

View File

@ -9,7 +9,7 @@ INCLUDEPATH += ../src
# RH 9
INCLUDEPATH += /usr/kerberos/include
HEADERS = qcaopenssl.h qcaopenssl_p.h
HEADERS = qcaopenssl.h
SOURCES = qcaopenssl.cpp
DEFINES += QCA_PLUGIN

View File

@ -1,16 +0,0 @@
#ifndef QCAOPENSSL_P_H
#define QCAOPENSSL_P_H
#include"qcaopenssl.h"
class _QCAOpenSSL : public QCAOpenSSL
{
public:
_QCAOpenSSL();
~_QCAOpenSSL();
int capabilities() const;
void *functions(int cap);
};
#endif

View File

@ -2,7 +2,7 @@
#include"qca.h"
#include<stdio.h>
static QCA::RSAKey readKeyFile(const QString &name, bool sec=false)
QCA::RSAKey readKeyFile(const QString &name, bool sec=false)
{
QCA::RSAKey k;
QFile f(name);
@ -30,12 +30,13 @@ int main(int argc, char **argv)
if(!QCA::isSupported(QCA::CAP_RSA))
printf("RSA not supported!\n");
else {
/*QCA::RSAKey pubkey = readKeyFile("keypublic.der");
if(pubkey.isNull())
return 1;
QCA::RSAKey seckey = readKeyFile("keyprivate.der", true);
if(seckey.isNull())
return 1;*/
//QCA::RSAKey pubkey = readKeyFile("keypublic.der");
//if(pubkey.isNull())
// return 1;
//QCA::RSAKey seckey = readKeyFile("keyprivate.der", true);
//if(seckey.isNull())
// return 1;
QCA::RSAKey seckey = QCA::RSA::generateKey(1024);
if(seckey.isNull())
return 1;

View File

@ -9,7 +9,7 @@
#include<stdio.h>
#ifdef USE_OPENSSL
#include"qcaopenssl_p.h"
#include"qcaopenssl.h"
#endif
#if defined(Q_OS_WIN32)
@ -52,7 +52,7 @@ void QCA::init()
{
providerList.clear();
#ifdef USE_OPENSSL
providerList.append(new _QCAOpenSSL);
providerList.append(createProviderOpenSSL());
#endif
// load plugins
@ -71,6 +71,7 @@ void QCA::init()
}
void *s = lib->resolve("createProvider");
if(!s) {
printf("can't resolve\n");
delete lib;
continue;
}
@ -113,35 +114,32 @@ static void *getFunctions(int cap)
class Hash::Private
{
public:
Private(QCA_HashFunctions *_f)
Private(QCA_HashContext *_c)
{
f = _f;
ctx = f->create();
c = _c;
}
~Private()
{
f->destroy(ctx);
delete c;
}
void reset()
{
f->destroy(ctx);
ctx = f->create();
c->reset();
}
QCA_HashFunctions *f;
int ctx;
QCA_HashContext *c;
};
Hash::Hash(QCA_HashFunctions *f)
Hash::Hash(QCA_HashContext *c)
{
d = new Private(f);
d = new Private(c);
}
Hash::Hash(const Hash &from)
{
d = new Private(from.d->f);
d = new Private(from.d->c);
*this = from;
}
@ -163,13 +161,17 @@ void Hash::clear()
void Hash::update(const QByteArray &a)
{
d->f->update(d->ctx, a.data(), a.size());
d->c->update(a.data(), a.size());
}
QByteArray Hash::final()
{
QByteArray buf(d->f->finalSize(d->ctx));
d->f->final(d->ctx, buf.data());
char *out;
unsigned int len;
d->c->final(&out, &len);
QByteArray buf(len);
memcpy(buf.data(), out, len);
free(out);
return buf;
}
@ -180,50 +182,48 @@ QByteArray Hash::final()
class Cipher::Private
{
public:
Private(QCA_CipherFunctions *_f)
Private(QCA_CipherContext *_c)
{
f = _f;
ctx = f->create();
c = _c;
}
~Private()
{
f->destroy(ctx);
delete c;
}
void reset()
{
f->destroy(ctx);
ctx = f->create();
//c->reset();
dir = Encrypt;
key.resize(0);
iv.resize(0);
err = false;
}
QCA_CipherFunctions *f;
int ctx;
QCA_CipherContext *c;
int dir;
int mode;
QByteArray key, iv;
bool err;
};
Cipher::Cipher(QCA_CipherFunctions *f, int dir, int mode, const QByteArray &key, const QByteArray &iv)
Cipher::Cipher(QCA_CipherContext *c, int dir, int mode, const QByteArray &key, const QByteArray &iv)
{
d = new Private(f);
d = new Private(c);
reset(dir, mode, key, iv);
}
Cipher::Cipher(const Cipher &from)
{
d = new Private(from.d->f);
d = new Private(from.d->c);
*this = from;
}
Cipher & Cipher::operator=(const Cipher &from)
{
reset(from.d->dir, from.d->key, from.d->iv);
reset(from.d->dir, from.d->mode, from.d->key, from.d->iv);
return *this;
}
@ -234,16 +234,16 @@ Cipher::~Cipher()
QByteArray Cipher::dyn_generateKey() const
{
QByteArray buf(d->f->keySize());
if(!d->f->generateKey(buf.data()))
QByteArray buf(d->c->keySize());
if(!d->c->generateKey(buf.data()))
return QByteArray();
return buf;
}
QByteArray Cipher::dyn_generateIV() const
{
QByteArray buf(d->f->blockSize());
if(!d->f->generateIV(buf.data()))
QByteArray buf(d->c->blockSize());
if(!d->c->generateIV(buf.data()))
return QByteArray();
return buf;
}
@ -255,7 +255,7 @@ void Cipher::reset(int dir, int mode, const QByteArray &key, const QByteArray &i
d->mode = mode;
d->key = key.copy();
d->iv = iv.copy();
if(!d->f->setup(d->ctx, d->dir, d->mode, d->key.data(), d->iv.isEmpty() ? 0 : d->iv.data())) {
if(!d->c->setup(d->dir, d->mode, d->key.data(), d->iv.isEmpty() ? 0 : d->iv.data())) {
d->err = true;
return;
}
@ -266,7 +266,7 @@ bool Cipher::update(const QByteArray &a)
if(d->err)
return false;
if(!d->f->update(d->ctx, a.data(), a.size())) {
if(!d->c->update(a.data(), a.size())) {
d->err = true;
return false;
}
@ -278,12 +278,15 @@ QByteArray Cipher::final()
if(d->err)
return QByteArray();
QByteArray buf(d->f->finalSize(d->ctx));
if(!d->f->final(d->ctx, buf.data())) {
char *out;
unsigned int len;
if(!d->c->final(&out, &len)) {
d->err = true;
return QByteArray();
}
QByteArray buf(len);
memcpy(buf.data(), out, len);
free(out);
return buf;
}
@ -292,7 +295,7 @@ QByteArray Cipher::final()
// SHA1
//----------------------------------------------------------------------------
SHA1::SHA1()
:Hash((QCA_HashFunctions *)getFunctions(CAP_SHA1))
:Hash((QCA_HashContext *)getFunctions(CAP_SHA1))
{
}
@ -301,7 +304,7 @@ SHA1::SHA1()
// SHA256
//----------------------------------------------------------------------------
SHA256::SHA256()
:Hash((QCA_HashFunctions *)getFunctions(CAP_SHA256))
:Hash((QCA_HashContext *)getFunctions(CAP_SHA256))
{
}
@ -310,7 +313,7 @@ SHA256::SHA256()
// MD5
//----------------------------------------------------------------------------
MD5::MD5()
:Hash((QCA_HashFunctions *)getFunctions(CAP_MD5))
:Hash((QCA_HashContext *)getFunctions(CAP_MD5))
{
}
@ -319,7 +322,7 @@ MD5::MD5()
// BlowFish
//----------------------------------------------------------------------------
BlowFish::BlowFish(int dir, int mode, const QByteArray &key, const QByteArray &iv)
:Cipher((QCA_CipherFunctions *)getFunctions(CAP_BlowFish), dir, mode, key, iv)
:Cipher((QCA_CipherContext *)getFunctions(CAP_BlowFish), dir, mode, key, iv)
{
}
@ -328,7 +331,7 @@ BlowFish::BlowFish(int dir, int mode, const QByteArray &key, const QByteArray &i
// TripleDES
//----------------------------------------------------------------------------
TripleDES::TripleDES(int dir, int mode, const QByteArray &key, const QByteArray &iv)
:Cipher((QCA_CipherFunctions *)getFunctions(CAP_TripleDES), dir, mode, key, iv)
:Cipher((QCA_CipherContext *)getFunctions(CAP_TripleDES), dir, mode, key, iv)
{
}
@ -337,7 +340,7 @@ TripleDES::TripleDES(int dir, int mode, const QByteArray &key, const QByteArray
// AES128
//----------------------------------------------------------------------------
AES128::AES128(int dir, int mode, const QByteArray &key, const QByteArray &iv)
:Cipher((QCA_CipherFunctions *)getFunctions(CAP_AES128), dir, mode, key, iv)
:Cipher((QCA_CipherContext *)getFunctions(CAP_AES128), dir, mode, key, iv)
{
}
@ -346,7 +349,7 @@ AES128::AES128(int dir, int mode, const QByteArray &key, const QByteArray &iv)
// AES256
//----------------------------------------------------------------------------
AES256::AES256(int dir, int mode, const QByteArray &key, const QByteArray &iv)
:Cipher((QCA_CipherFunctions *)getFunctions(CAP_AES256), dir, mode, key, iv)
:Cipher((QCA_CipherContext *)getFunctions(CAP_AES256), dir, mode, key, iv)
{
}
@ -359,25 +362,15 @@ class RSAKey::Private
public:
Private()
{
f = (QCA_RSAFunctions *)getFunctions(CAP_RSA);
ctx = -1;
c = (QCA_RSAKeyContext *)getFunctions(CAP_RSA);
}
~Private()
{
reset();
delete c;
}
void reset()
{
if(ctx != -1) {
f->keyDestroy(ctx);
ctx = -1;
}
}
QCA_RSAFunctions *f;
int ctx;
QCA_RSAKeyContext *c;
};
RSAKey::RSAKey()
@ -393,10 +386,11 @@ RSAKey::RSAKey(const RSAKey &from)
RSAKey & RSAKey::operator=(const RSAKey &from)
{
d->reset();
if(d->c)
delete d->c;
*d = *from.d;
if(d->ctx != -1)
d->ctx = d->f->keyClone(d->ctx);
d->c = d->c->clone();
return *this;
}
@ -407,14 +401,14 @@ RSAKey::~RSAKey()
bool RSAKey::isNull() const
{
return (d->ctx == -1 ? true: false);
return d->c->isNull();
}
QByteArray RSAKey::toDER() const
{
char *out;
unsigned int len;
d->f->keyToDER(d->ctx, &out, &len);
d->c->toDER(&out, &len);
QByteArray buf(len);
memcpy(buf.data(), out, len);
free(out);
@ -423,34 +417,41 @@ QByteArray RSAKey::toDER() const
bool RSAKey::fromDER(const QByteArray &a, bool sec)
{
int ctx = d->f->keyCreateFromDER(a.data(), a.size(), sec);
if(ctx == -1)
return false;
d->ctx = ctx;
return true;
return d->c->createFromDER(a.data(), a.size(), sec);
}
bool RSAKey::fromNative(void *p)
{
int ctx = d->f->keyCreateFromNative(p);
if(ctx == -1)
return d->c->createFromNative(p);
}
bool RSAKey::encrypt(const QByteArray &a, QByteArray *b) const
{
char *out;
unsigned int len;
if(!d->c->encrypt(a.data(), a.size(), &out, &len))
return false;
d->ctx = ctx;
b->resize(len);
memcpy(b->data(), out, len);
free(out);
return true;
}
bool RSAKey::decrypt(const QByteArray &a, QByteArray *b) const
{
char *out;
unsigned int len;
if(!d->c->decrypt(a.data(), a.size(), &out, &len))
return false;
b->resize(len);
memcpy(b->data(), out, len);
free(out);
return true;
}
bool RSAKey::generate(unsigned int bits)
{
int ctx = d->f->keyCreateGenerate(bits);
if(ctx == -1)
return false;
d->ctx = ctx;
return true;
}
int RSAKey::internalContext() const
{
return d->ctx;
return d->c->generate(bits);
}
@ -479,34 +480,14 @@ bool RSA::encrypt(const QByteArray &a, QByteArray *b) const
{
if(v_key.isNull())
return false;
QCA_RSAFunctions *f = (QCA_RSAFunctions *)getFunctions(CAP_RSA);
char *out;
unsigned int len;
if(!f->encrypt(v_key.internalContext(), a.data(), a.size(), &out, &len))
return false;
b->resize(len);
memcpy(b->data(), out, len);
free(out);
return true;
return v_key.encrypt(a, b);
}
bool RSA::decrypt(const QByteArray &a, QByteArray *b) const
{
if(v_key.isNull())
return false;
QCA_RSAFunctions *f = (QCA_RSAFunctions *)getFunctions(CAP_RSA);
char *out;
unsigned int len;
if(!f->decrypt(v_key.internalContext(), a.data(), a.size(), &out, &len))
return false;
b->resize(len);
memcpy(b->data(), out, len);
free(out);
return true;
return v_key.decrypt(a, b);
}
RSAKey RSA::generateKey(unsigned int bits)

View File

@ -4,8 +4,8 @@
#include<qstring.h>
#include<qcstring.h>
struct QCA_HashFunctions;
struct QCA_CipherFunctions;
class QCA_HashContext;
class QCA_CipherContext;
namespace QCA
{
@ -52,7 +52,7 @@ namespace QCA
QByteArray final();
protected:
Hash(QCA_HashFunctions *);
Hash(QCA_HashContext *);
private:
class Private;
@ -104,7 +104,7 @@ namespace QCA
QByteArray final();
protected:
Cipher(QCA_CipherFunctions *, int dir, int mode, const QByteArray &key, const QByteArray &iv);
Cipher(QCA_CipherContext *, int dir, int mode, const QByteArray &key, const QByteArray &iv);
private:
class Private;
@ -194,7 +194,8 @@ namespace QCA
Private *d;
friend class RSA;
int internalContext() const;
bool encrypt(const QByteArray &a, QByteArray *out) const;
bool decrypt(const QByteArray &a, QByteArray *out) const;
bool generate(unsigned int bits);
};

View File

@ -20,41 +20,45 @@ public:
virtual void *functions(int cap)=0;
};
struct QCA_HashFunctions
class QCA_HashContext
{
int (*create)();
void (*destroy)(int ctx);
void (*update)(int ctx, const char *in, unsigned int len);
void (*final)(int ctx, char *out);
unsigned int (*finalSize)(int ctx);
public:
virtual ~QCA_HashContext() {}
virtual void reset()=0;
virtual void update(const char *in, unsigned int len)=0;
virtual void final(char **out, unsigned int *outlen)=0;
};
struct QCA_CipherFunctions
class QCA_CipherContext
{
int (*keySize)();
int (*blockSize)();
bool (*generateKey)(char *out);
bool (*generateIV)(char *out);
public:
virtual ~QCA_CipherContext() {}
int (*create)();
void (*destroy)(int ctx);
bool (*setup)(int ctx, int dir, int mode, const char *key, const char *iv);
bool (*update)(int ctx, const char *in, unsigned int len);
bool (*final)(int ctx, char *out);
unsigned int (*finalSize)(int ctx);
virtual int keySize()=0;
virtual int blockSize()=0;
virtual bool generateKey(char *out)=0;
virtual bool generateIV(char *out)=0;
virtual bool setup(int dir, int mode, const char *key, const char *iv)=0;
virtual bool update(const char *in, unsigned int len)=0;
virtual bool final(char **out, unsigned int *outlen)=0;
};
struct QCA_RSAFunctions
class QCA_RSAKeyContext
{
int (*keyCreateFromDER)(const char *in, unsigned int len, bool sec);
int (*keyCreateFromNative)(void *in);
int (*keyCreateGenerate)(unsigned int bits);
int (*keyClone)(int ctx);
void (*keyDestroy)(int ctx);
void (*keyToDER)(int ctx, char **out, unsigned int *len);
public:
virtual ~QCA_RSAKeyContext() {}
bool (*encrypt)(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen);
bool (*decrypt)(int ctx, const char *in, unsigned int len, char **out, unsigned int *outlen);
virtual bool isNull() const=0;
virtual bool createFromDER(const char *in, unsigned int len, bool sec)=0;
virtual bool createFromNative(void *in)=0;
virtual bool generate(unsigned int bits)=0;
virtual QCA_RSAKeyContext *clone()=0;
virtual void toDER(char **out, unsigned int *len)=0;
virtual bool encrypt(const char *in, unsigned int len, char **out, unsigned int *outlen)=0;
virtual bool decrypt(const char *in, unsigned int len, char **out, unsigned int *outlen)=0;
};
#endif