RSA support

svn path=/trunk/kdesupport/qca/; revision=236591
This commit is contained in:
Justin Karneges 2003-07-11 21:30:48 +00:00
parent 89c32cf384
commit 413fb04eb5
5 changed files with 356 additions and 4 deletions

11
TODO
View File

@ -1,8 +1,13 @@
* clean up plugin system
* flesh out rsa and rsakey
* rsa: choice of pad
* make 'cipherkey' class?
* better handling of errors ('empty' arrays are not a good idea)
* ability to disable pkcs padding on ciphers
* better entropy?
* clean up plugin system
* ssl/tls/x509
* sasl
* ssl/tls/x509 (also server support)
* sasl (also server support)
* figure out where to install the lib and plugins. maybe Qt plugin path?

View File

@ -4,6 +4,8 @@
#include<openssl/sha.h>
#include<openssl/md5.h>
#include<openssl/evp.h>
#include<openssl/rsa.h>
#include<openssl/x509.h>
#ifdef QCA_PLUGIN
QCAProvider *createProvider()
@ -71,6 +73,13 @@ 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_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();
@ -109,6 +118,14 @@ struct pair_tdes
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);
@ -139,6 +156,16 @@ static pair_tdes *find_tdes(int ctx)
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;
@ -147,6 +174,8 @@ _QCAOpenSSL::_QCAOpenSSL()
map_md5->setAutoDelete(true);
map_tdes = new MAP_TDES;
map_tdes->setAutoDelete(true);
map_rsakey = new MAP_RSAKEY;
map_rsakey->setAutoDelete(true);
}
_QCAOpenSSL::~_QCAOpenSSL()
@ -157,11 +186,13 @@ _QCAOpenSSL::~_QCAOpenSSL()
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);
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_TripleDES | QCA::CAP_RSA);
}
void *_QCAOpenSSL::functions(int cap)
@ -198,6 +229,17 @@ void *_QCAOpenSSL::functions(int cap)
f->finalSize = tdes_finalSize;
return f;
}
else if(cap == QCA::CAP_RSA) {
QCA_RSAFunctions *f = new QCA_RSAFunctions;
f->keyCreateFromDER = rsa_keyCreateFromDER;
f->keyClone = rsa_keyClone;
f->keyDestroy = rsa_keyDestroy;
f->keyToDER = rsa_keyToDER;
f->encrypt = rsa_encrypt;
f->decrypt = rsa_decrypt;
return f;
}
return 0;
}
@ -408,3 +450,110 @@ unsigned int tdes_finalSize(int ctx)
return i->r.size();
}
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);
}
else {
unsigned char *p = (unsigned char *)in;
r = d2i_RSA_PUBKEY(NULL, &p,len);
}
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_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;
}
/*bool RSAKey::generateKey(int bits)
{
RSA *r = RSA_generate_key(bits, RSA_F4, NULL, NULL);
if(!r)
return false;
d->r = r;
return true;
}*/

View File

@ -338,3 +338,149 @@ AES256::AES256(int dir, const QByteArray &key, const QByteArray &iv)
:Cipher((QCA_CipherFunctions *)getFunctions(CAP_AES256), dir, key, iv)
{
}
//----------------------------------------------------------------------------
// RSAKey
//----------------------------------------------------------------------------
class RSAKey::Private
{
public:
Private()
{
f = (QCA_RSAFunctions *)getFunctions(CAP_RSA);
ctx = -1;
}
~Private()
{
reset();
}
void reset()
{
if(ctx != -1) {
f->keyDestroy(ctx);
ctx = -1;
}
}
QCA_RSAFunctions *f;
int ctx;
};
RSAKey::RSAKey()
{
d = new Private;
}
RSAKey::RSAKey(const RSAKey &from)
{
d = new Private;
*this = from;
}
RSAKey & RSAKey::operator=(const RSAKey &from)
{
d->reset();
*d = *from.d;
if(d->ctx != -1)
d->ctx = d->f->keyClone(d->ctx);
return *this;
}
RSAKey::~RSAKey()
{
delete d;
}
bool RSAKey::isNull() const
{
return (d->ctx == -1 ? true: false);
}
QByteArray RSAKey::toDER() const
{
char *out;
unsigned int len;
d->f->keyToDER(d->ctx, &out, &len);
QByteArray buf(len);
memcpy(buf.data(), out, len);
free(out);
return buf;
}
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;
}
int RSAKey::internalContext() const
{
return d->ctx;
}
//----------------------------------------------------------------------------
// RSA
//----------------------------------------------------------------------------
RSA::RSA()
{
}
RSA::~RSA()
{
}
RSAKey RSA::key() const
{
return v_key;
}
void RSA::setKey(const RSAKey &k)
{
v_key = k;
}
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;
}
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;
}
RSAKey RSA::generateKey(int bits)
{
return RSAKey();
}

View File

@ -16,6 +16,7 @@ namespace QCA
CAP_TripleDES = 0x0008,
CAP_AES128 = 0x0010,
CAP_AES256 = 0x0020,
CAP_RSA = 0x0040,
//CAP_X509 = 0x0040,
//CAP_TLS = 0x0080,
@ -155,6 +156,46 @@ namespace QCA
public:
AES256(int dir=Encrypt, const QByteArray &key=QByteArray(), const QByteArray &iv=QByteArray());
};
class RSA;
class RSAKey
{
public:
RSAKey();
RSAKey(const RSAKey &from);
RSAKey & operator=(const RSAKey &from);
~RSAKey();
bool isNull() const;
QByteArray toDER() const;
bool fromDER(const QByteArray &a, bool sec=false);
private:
class Private;
Private *d;
friend class RSA;
int internalContext() const;
};
class RSA
{
public:
RSA();
~RSA();
RSAKey key() const;
void setKey(const RSAKey &);
bool encrypt(const QByteArray &a, QByteArray *out) const;
bool decrypt(const QByteArray &a, QByteArray *out) const;
static RSAKey generateKey(int bits);
private:
RSAKey v_key;
};
};
#endif

View File

@ -44,4 +44,15 @@ struct QCA_CipherFunctions
unsigned int (*finalSize)(int ctx);
};
struct QCA_RSAFunctions
{
int (*keyCreateFromDER)(const char *in, unsigned int len, bool sec);
int (*keyClone)(int ctx);
void (*keyDestroy)(int ctx);
void (*keyToDER)(int ctx, char **out, unsigned int *len);
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);
};
#endif