From e6adfbd2b3746f1093764d5e745be9cdcece10ab Mon Sep 17 00:00:00 2001 From: Justin Karneges Date: Sun, 20 Jul 2003 13:40:20 +0000 Subject: [PATCH] changed plugin system to use C++ svn path=/trunk/kdesupport/qca/; revision=238159 --- TODO | 2 + ciphertest.cpp | 29 +- plugins/qcaopenssl.cpp | 783 ++++++++++++++++------------------------- plugins/qcaopenssl.h | 8 +- plugins/qcaopenssl.pro | 2 +- plugins/qcaopenssl_p.h | 16 - rsatest.cpp | 15 +- src/qca.cpp | 185 +++++----- src/qca.h | 11 +- src/qcaprovider.h | 56 +-- 10 files changed, 461 insertions(+), 646 deletions(-) delete mode 100644 plugins/qcaopenssl_p.h diff --git a/TODO b/TODO index cc33e543..505928be 100644 --- a/TODO +++ b/TODO @@ -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) diff --git a/ciphertest.cpp b/ciphertest.cpp index a7f55556..301f07a7 100644 --- a/ciphertest.cpp +++ b/ciphertest.cpp @@ -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("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(" #include @@ -7,13 +7,6 @@ #include #include -#ifdef QCA_PLUGIN -QCAProvider *createProvider() -{ - return (new _QCAOpenSSL); -} -#endif - #include 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 MAP_SHA1; -MAP_SHA1 *map = 0; - -struct pair_md5 -{ - int ctx; - MD5_CTX c; -}; -typedef QPtrList 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 MAP_TDES; -MAP_TDES *map_tdes = 0; - -struct pair_rsakey -{ - int ctx; - RSA *r; -}; -typedef QPtrList MAP_RSAKEY; -MAP_RSAKEY *map_rsakey = 0; - -static pair_sha1 *find(int ctx) -{ - QPtrListIterator 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 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 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 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); } diff --git a/plugins/qcaopenssl.h b/plugins/qcaopenssl.h index 98dbb339..5d759815 100644 --- a/plugins/qcaopenssl.h +++ b/plugins/qcaopenssl.h @@ -5,12 +5,8 @@ #ifdef QCA_PLUGIN QCA_EXPORT QCAProvider *createProvider(); +#else +QCAProvider *createProviderOpenSSL(); #endif -class QCAOpenSSL : public QCAProvider -{ -public: - QCAOpenSSL() {} -}; - #endif diff --git a/plugins/qcaopenssl.pro b/plugins/qcaopenssl.pro index f323cc05..d0744c91 100644 --- a/plugins/qcaopenssl.pro +++ b/plugins/qcaopenssl.pro @@ -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 diff --git a/plugins/qcaopenssl_p.h b/plugins/qcaopenssl_p.h deleted file mode 100644 index c1ad962e..00000000 --- a/plugins/qcaopenssl_p.h +++ /dev/null @@ -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 diff --git a/rsatest.cpp b/rsatest.cpp index ebd92241..15fc4508 100644 --- a/rsatest.cpp +++ b/rsatest.cpp @@ -2,7 +2,7 @@ #include"qca.h" #include -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; diff --git a/src/qca.cpp b/src/qca.cpp index 0349590d..5020fb91 100644 --- a/src/qca.cpp +++ b/src/qca.cpp @@ -9,7 +9,7 @@ #include #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) diff --git a/src/qca.h b/src/qca.h index 16970747..82f7b865 100644 --- a/src/qca.h +++ b/src/qca.h @@ -4,8 +4,8 @@ #include #include -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); }; diff --git a/src/qcaprovider.h b/src/qcaprovider.h index 2adc2f49..0f397e9e 100644 --- a/src/qcaprovider.h +++ b/src/qcaprovider.h @@ -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