mirror of
https://github.com/QuasarApp/qca.git
synced 2025-05-11 02:09:33 +00:00
initial x509
svn path=/trunk/kdesupport/qca/; revision=238577
This commit is contained in:
parent
ea83f0a99f
commit
aadd9caa59
4
TODO
4
TODO
@ -1,4 +1,6 @@
|
||||
* x509
|
||||
* cert: toDER
|
||||
* cert: toPEM / fromPEM
|
||||
|
||||
* ssl/tls (also server support)
|
||||
* sasl (also server support)
|
||||
|
||||
|
81
certtest.cpp
Normal file
81
certtest.cpp
Normal file
@ -0,0 +1,81 @@
|
||||
#include<qdom.h>
|
||||
#include<qfile.h>
|
||||
#include"base64.h"
|
||||
#include"qca.h"
|
||||
|
||||
QCA::Cert readCertXml(const QDomElement &e)
|
||||
{
|
||||
QCA::Cert cert;
|
||||
// there should be one child data tag
|
||||
QDomElement data = e.elementsByTagName("data").item(0).toElement();
|
||||
if(!data.isNull())
|
||||
cert.fromDER(Base64::stringToArray(data.text()));
|
||||
return cert;
|
||||
}
|
||||
|
||||
struct QCA_CertProperty
|
||||
{
|
||||
QString var;
|
||||
QString val;
|
||||
};
|
||||
|
||||
void showCertInfo(const QCA::Cert &cert)
|
||||
{
|
||||
QValueList<QCA_CertProperty> list = cert.subject();
|
||||
QString cn;
|
||||
for(QValueList<QCA_CertProperty>::ConstIterator it = list.begin(); it != list.end(); ++it) {
|
||||
if((*it).var == "CN") {
|
||||
cn = (*it).val;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" CN: %s\n", cn.latin1());
|
||||
printf(" Valid from: %s, until %s\n",
|
||||
cert.notBefore().toString().latin1(),
|
||||
cert.notAfter().toString().latin1());
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
QCA::init();
|
||||
|
||||
if(!QCA::isSupported(QCA::CAP_X509)) {
|
||||
printf("X509 not supported!\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
// open the Psi rootcerts file
|
||||
QFile f("/usr/local/share/psi/certs/rootcert.xml");
|
||||
if(!f.open(IO_ReadOnly)) {
|
||||
printf("unable to open %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
QDomDocument doc;
|
||||
doc.setContent(&f);
|
||||
f.close();
|
||||
|
||||
QDomElement base = doc.documentElement();
|
||||
if(base.tagName() != "store") {
|
||||
printf("wrong format of %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
QDomNodeList cl = base.elementsByTagName("certificate");
|
||||
if(cl.count() == 0) {
|
||||
printf("no certs found in %s\n", f.name().latin1());
|
||||
return 1;
|
||||
}
|
||||
|
||||
for(int n = 0; n < (int)cl.count(); ++n) {
|
||||
printf("-- Cert %d --\n", n);
|
||||
QCA::Cert cert = readCertXml(cl.item(n).toElement());
|
||||
if(cert.isNull()) {
|
||||
printf("error reading cert\n");
|
||||
continue;
|
||||
}
|
||||
showCertInfo(cert);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
13
certtest.pro
Normal file
13
certtest.pro
Normal file
@ -0,0 +1,13 @@
|
||||
TEMPLATE = app
|
||||
CONFIG += thread
|
||||
TARGET = certtest
|
||||
|
||||
MOC_DIR = .moc
|
||||
OBJECTS_DIR = .obj
|
||||
UI_DIR = .ui
|
||||
|
||||
INCLUDEPATH += src
|
||||
INCLUDEPATH += plugins
|
||||
HEADERS += base64.h src/qca.h
|
||||
SOURCES += base64.cpp certtest.cpp src/qca.cpp
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include"qcaopenssl.h"
|
||||
|
||||
#include<qptrlist.h>
|
||||
#include<openssl/sha.h>
|
||||
#include<openssl/md5.h>
|
||||
#include<openssl/evp.h>
|
||||
@ -8,6 +7,7 @@
|
||||
#include<openssl/pem.h>
|
||||
#include<openssl/rsa.h>
|
||||
#include<openssl/x509.h>
|
||||
#include<openssl/x509v3.h>
|
||||
|
||||
// FIXME: use openssl for entropy instead of stdlib
|
||||
#include<stdlib.h>
|
||||
@ -593,6 +593,221 @@ public:
|
||||
RSA *pub, *sec;
|
||||
};
|
||||
|
||||
static QValueList<QCA_CertProperty> nameToProperties(X509_NAME *name)
|
||||
{
|
||||
QValueList<QCA_CertProperty> list;
|
||||
|
||||
for(int n = 0; n < X509_NAME_entry_count(name); ++n) {
|
||||
X509_NAME_ENTRY *ne = X509_NAME_get_entry(name, n);
|
||||
QCA_CertProperty p;
|
||||
|
||||
ASN1_OBJECT *ao = X509_NAME_ENTRY_get_object(ne);
|
||||
int nid = OBJ_obj2nid(ao);
|
||||
if(nid == NID_undef)
|
||||
continue;
|
||||
p.var = OBJ_nid2sn(nid);
|
||||
|
||||
ASN1_STRING *as = X509_NAME_ENTRY_get_data(ne);
|
||||
QCString c;
|
||||
c.resize(as->length+1);
|
||||
strncpy(c.data(), (char *)as->data, as->length);
|
||||
p.val = QString::fromLatin1(c);
|
||||
list += p;
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
// (taken from kdelibs) -- Justin
|
||||
//
|
||||
// This code is mostly taken from OpenSSL v0.9.5a
|
||||
// by Eric Young
|
||||
QDateTime ASN1_UTCTIME_QDateTime(ASN1_UTCTIME *tm, int *isGmt)
|
||||
{
|
||||
QDateTime qdt;
|
||||
char *v;
|
||||
int gmt=0;
|
||||
int i;
|
||||
int y=0,M=0,d=0,h=0,m=0,s=0;
|
||||
QDate qdate;
|
||||
QTime qtime;
|
||||
|
||||
i = tm->length;
|
||||
v = (char *)tm->data;
|
||||
|
||||
if (i < 10) goto auq_err;
|
||||
if (v[i-1] == 'Z') gmt=1;
|
||||
for (i=0; i<10; i++)
|
||||
if ((v[i] > '9') || (v[i] < '0')) goto auq_err;
|
||||
y = (v[0]-'0')*10+(v[1]-'0');
|
||||
if (y < 50) y+=100;
|
||||
M = (v[2]-'0')*10+(v[3]-'0');
|
||||
if ((M > 12) || (M < 1)) goto auq_err;
|
||||
d = (v[4]-'0')*10+(v[5]-'0');
|
||||
h = (v[6]-'0')*10+(v[7]-'0');
|
||||
m = (v[8]-'0')*10+(v[9]-'0');
|
||||
if ( (v[10] >= '0') && (v[10] <= '9') &&
|
||||
(v[11] >= '0') && (v[11] <= '9'))
|
||||
s = (v[10]-'0')*10+(v[11]-'0');
|
||||
|
||||
// localize the date and display it.
|
||||
qdate.setYMD(y+1900, M, d);
|
||||
qtime.setHMS(h,m,s);
|
||||
qdt.setDate(qdate); qdt.setTime(qtime);
|
||||
auq_err:
|
||||
if (isGmt) *isGmt = gmt;
|
||||
return qdt;
|
||||
}
|
||||
|
||||
class CertContext : public QCA_CertContext
|
||||
{
|
||||
public:
|
||||
CertContext()
|
||||
{
|
||||
x = 0;
|
||||
}
|
||||
|
||||
~CertContext()
|
||||
{
|
||||
reset();
|
||||
}
|
||||
|
||||
QCA_CertContext *clone()
|
||||
{
|
||||
CertContext *c = new CertContext(*this);
|
||||
if(x) {
|
||||
++(x->references);
|
||||
c->x = x;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
void reset()
|
||||
{
|
||||
serial = "";
|
||||
v_subject = "";
|
||||
v_issuer = "";
|
||||
cp_subject.clear();
|
||||
cp_issuer.clear();
|
||||
na = QDateTime();
|
||||
nb = QDateTime();
|
||||
if(x) {
|
||||
X509_free(x);
|
||||
x = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool isNull() const
|
||||
{
|
||||
return (x ? false: true);
|
||||
}
|
||||
|
||||
bool createFromDER(const char *in, unsigned int len)
|
||||
{
|
||||
unsigned char *p = (unsigned char *)in;
|
||||
X509 *t = d2i_X509(NULL, &p, len);
|
||||
if(!t)
|
||||
return false;
|
||||
fromX509(t);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool createFromPEM(const char *in, unsigned int len)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void toDER(char **out, unsigned int *len)
|
||||
{
|
||||
// extract the raw data
|
||||
//int len = i2d_X509(x, NULL);
|
||||
//QByteArray dat(len);
|
||||
//unsigned char *p = (unsigned char *)dat.data();
|
||||
//i2d_X509(x, &p);
|
||||
//d->dat = dat;
|
||||
|
||||
*out = 0;
|
||||
*len = 0;
|
||||
}
|
||||
|
||||
void toPEM(char **out, unsigned int *len)
|
||||
{
|
||||
*out = 0;
|
||||
*len = 0;
|
||||
}
|
||||
|
||||
void fromX509(X509 *t)
|
||||
{
|
||||
reset();
|
||||
++(t->references);
|
||||
x = t;
|
||||
|
||||
// serial number
|
||||
ASN1_INTEGER *ai = X509_get_serialNumber(x);
|
||||
if(ai) {
|
||||
char *rep = i2s_ASN1_INTEGER(NULL, ai);
|
||||
serial = rep;
|
||||
OPENSSL_free(rep);
|
||||
}
|
||||
|
||||
// validity dates
|
||||
nb = ASN1_UTCTIME_QDateTime(X509_get_notBefore(x), NULL);
|
||||
na = ASN1_UTCTIME_QDateTime(X509_get_notAfter(x), NULL);
|
||||
|
||||
// extract the subject/issuer strings
|
||||
X509_NAME *sn = X509_get_subject_name(x);
|
||||
X509_NAME *in = X509_get_issuer_name(x);
|
||||
char buf[1024];
|
||||
X509_NAME_oneline(sn, buf, 1024);
|
||||
v_subject = buf;
|
||||
X509_NAME_oneline(in, buf, 1024);
|
||||
v_issuer = buf;
|
||||
|
||||
// extract the subject/issuer contents
|
||||
cp_subject = nameToProperties(sn);
|
||||
cp_issuer = nameToProperties(in);
|
||||
}
|
||||
|
||||
QString serialNumber() const
|
||||
{
|
||||
return serial;
|
||||
}
|
||||
|
||||
QString subjectString() const
|
||||
{
|
||||
return v_subject;
|
||||
}
|
||||
|
||||
QString issuerString() const
|
||||
{
|
||||
return v_issuer;
|
||||
}
|
||||
|
||||
QValueList<QCA_CertProperty> subject() const
|
||||
{
|
||||
return cp_subject;
|
||||
}
|
||||
|
||||
QValueList<QCA_CertProperty> issuer() const
|
||||
{
|
||||
return cp_issuer;
|
||||
}
|
||||
|
||||
QDateTime notBefore() const
|
||||
{
|
||||
return nb;
|
||||
}
|
||||
|
||||
QDateTime notAfter() const
|
||||
{
|
||||
return na;
|
||||
}
|
||||
|
||||
X509 *x;
|
||||
QString serial, v_subject, v_issuer;
|
||||
QValueList<QCA_CertProperty> cp_subject, cp_issuer;
|
||||
QDateTime nb, na;
|
||||
};
|
||||
|
||||
class QCAOpenSSL : public QCAProvider
|
||||
{
|
||||
@ -602,7 +817,7 @@ public:
|
||||
|
||||
int capabilities() const
|
||||
{
|
||||
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_BlowFish | QCA::CAP_TripleDES | QCA::CAP_AES128 | QCA::CAP_AES256 | QCA::CAP_RSA);
|
||||
return (QCA::CAP_SHA1 | QCA::CAP_MD5 | QCA::CAP_BlowFish | QCA::CAP_TripleDES | QCA::CAP_AES128 | QCA::CAP_AES256 | QCA::CAP_RSA | QCA::CAP_X509);
|
||||
}
|
||||
|
||||
void *context(int cap)
|
||||
@ -621,6 +836,8 @@ public:
|
||||
return new AES256Context;
|
||||
else if(cap == QCA::CAP_RSA)
|
||||
return new RSAKeyContext;
|
||||
else if(cap == QCA::CAP_X509)
|
||||
return new CertContext;
|
||||
return 0;
|
||||
}
|
||||
};
|
||||
|
117
src/qca.cpp
117
src/qca.cpp
@ -379,7 +379,7 @@ class RSAKey::Private
|
||||
public:
|
||||
Private()
|
||||
{
|
||||
c = (QCA_RSAKeyContext *)getContext(CAP_RSA);
|
||||
c = 0;
|
||||
}
|
||||
|
||||
~Private()
|
||||
@ -393,6 +393,7 @@ public:
|
||||
RSAKey::RSAKey()
|
||||
{
|
||||
d = new Private;
|
||||
d->c = (QCA_RSAKeyContext *)getContext(CAP_RSA);
|
||||
}
|
||||
|
||||
RSAKey::RSAKey(const RSAKey &from)
|
||||
@ -403,11 +404,8 @@ RSAKey::RSAKey(const RSAKey &from)
|
||||
|
||||
RSAKey & RSAKey::operator=(const RSAKey &from)
|
||||
{
|
||||
if(d->c)
|
||||
delete d->c;
|
||||
*d = *from.d;
|
||||
d->c = d->c->clone();
|
||||
|
||||
delete d->c;
|
||||
d->c = from.d->c->clone();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -551,3 +549,110 @@ RSAKey RSA::generateKey(unsigned int bits)
|
||||
k.generate(bits);
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Cert
|
||||
//----------------------------------------------------------------------------
|
||||
class Cert::Private
|
||||
{
|
||||
public:
|
||||
Private()
|
||||
{
|
||||
c = 0;
|
||||
}
|
||||
|
||||
~Private()
|
||||
{
|
||||
delete c;
|
||||
}
|
||||
|
||||
QCA_CertContext *c;
|
||||
};
|
||||
|
||||
Cert::Cert()
|
||||
{
|
||||
d = new Private;
|
||||
d->c = (QCA_CertContext *)getContext(CAP_X509);
|
||||
}
|
||||
|
||||
Cert::Cert(const Cert &from)
|
||||
{
|
||||
d = new Private;
|
||||
*this = from;
|
||||
}
|
||||
|
||||
Cert & Cert::operator=(const Cert &from)
|
||||
{
|
||||
delete d->c;
|
||||
d->c = from.d->c->clone();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Cert::~Cert()
|
||||
{
|
||||
delete d;
|
||||
}
|
||||
|
||||
bool Cert::isNull() const
|
||||
{
|
||||
return d->c->isNull();
|
||||
}
|
||||
|
||||
QString Cert::serialNumber() const
|
||||
{
|
||||
return d->c->serialNumber();
|
||||
}
|
||||
|
||||
QString Cert::subjectString() const
|
||||
{
|
||||
return d->c->subjectString();
|
||||
}
|
||||
|
||||
QString Cert::issuerString() const
|
||||
{
|
||||
return d->c->issuerString();
|
||||
}
|
||||
|
||||
QValueList<QCA_CertProperty> Cert::subject() const
|
||||
{
|
||||
return d->c->subject();
|
||||
}
|
||||
|
||||
QValueList<QCA_CertProperty> Cert::issuer() const
|
||||
{
|
||||
return d->c->issuer();
|
||||
}
|
||||
|
||||
QDateTime Cert::notBefore() const
|
||||
{
|
||||
return d->c->notBefore();
|
||||
}
|
||||
|
||||
QDateTime Cert::notAfter() const
|
||||
{
|
||||
return d->c->notAfter();
|
||||
}
|
||||
|
||||
QByteArray Cert::toDER() const
|
||||
{
|
||||
return QByteArray();
|
||||
}
|
||||
|
||||
bool Cert::fromDER(const QByteArray &a)
|
||||
{
|
||||
return d->c->createFromDER(a.data(), a.size());
|
||||
}
|
||||
|
||||
QString Cert::toPEM() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool Cert::fromPEM(const QString &str)
|
||||
{
|
||||
QCString cs = str.latin1();
|
||||
QByteArray a(cs.length());
|
||||
memcpy(a.data(), cs.data(), a.size());
|
||||
return d->c->createFromPEM(a.data(), a.size());
|
||||
}
|
||||
|
44
src/qca.h
44
src/qca.h
@ -3,9 +3,12 @@
|
||||
|
||||
#include<qstring.h>
|
||||
#include<qcstring.h>
|
||||
#include<qdatetime.h>
|
||||
#include<qvaluelist.h>
|
||||
|
||||
class QCA_HashContext;
|
||||
class QCA_CipherContext;
|
||||
struct QCA_CertProperty;
|
||||
|
||||
namespace QCA
|
||||
{
|
||||
@ -18,10 +21,10 @@ namespace QCA
|
||||
CAP_AES128 = 0x0020,
|
||||
CAP_AES256 = 0x0040,
|
||||
CAP_RSA = 0x0080,
|
||||
CAP_X509 = 0x0100,
|
||||
|
||||
//CAP_X509 = 0x0040,
|
||||
//CAP_TLS = 0x0080,
|
||||
//CAP_SASL = 0x0100,
|
||||
//CAP_TLS = 0x0200,
|
||||
//CAP_SASL = 0x0400,
|
||||
};
|
||||
|
||||
enum {
|
||||
@ -221,6 +224,41 @@ namespace QCA
|
||||
private:
|
||||
RSAKey v_key;
|
||||
};
|
||||
|
||||
struct CertProperty
|
||||
{
|
||||
QString var;
|
||||
QString val;
|
||||
};
|
||||
|
||||
class Cert
|
||||
{
|
||||
public:
|
||||
Cert();
|
||||
Cert(const Cert &);
|
||||
Cert & operator=(const Cert &);
|
||||
~Cert();
|
||||
|
||||
bool isNull() const;
|
||||
|
||||
QString serialNumber() const;
|
||||
QString subjectString() const;
|
||||
QString issuerString() const;
|
||||
QValueList<QCA_CertProperty> subject() const;
|
||||
QValueList<QCA_CertProperty> issuer() const;
|
||||
QDateTime notBefore() const;
|
||||
QDateTime notAfter() const;
|
||||
|
||||
QByteArray toDER() const;
|
||||
bool fromDER(const QByteArray &a);
|
||||
|
||||
QString toPEM() const;
|
||||
bool fromPEM(const QString &);
|
||||
|
||||
private:
|
||||
class Private;
|
||||
Private *d;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -2,6 +2,8 @@
|
||||
#define QCAPROVIDER_H
|
||||
|
||||
#include<qglobal.h>
|
||||
#include<qstring.h>
|
||||
#include<qdatetime.h>
|
||||
#include"qca.h"
|
||||
|
||||
#ifdef Q_WS_WIN
|
||||
@ -52,6 +54,7 @@ class QCA_RSAKeyContext
|
||||
public:
|
||||
virtual ~QCA_RSAKeyContext() {}
|
||||
|
||||
virtual QCA_RSAKeyContext *clone()=0;
|
||||
virtual bool isNull() const=0;
|
||||
virtual bool havePublic() const=0;
|
||||
virtual bool havePrivate() const=0;
|
||||
@ -59,7 +62,6 @@ public:
|
||||
virtual bool createFromPEM(const char *in, unsigned int len)=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, bool publicOnly)=0;
|
||||
virtual void toPEM(char **out, unsigned int *len, bool publicOnly)=0;
|
||||
|
||||
@ -67,4 +69,31 @@ public:
|
||||
virtual bool decrypt(const char *in, unsigned int len, char **out, unsigned int *outlen, bool oaep)=0;
|
||||
};
|
||||
|
||||
struct QCA_CertProperty
|
||||
{
|
||||
QString var;
|
||||
QString val;
|
||||
};
|
||||
|
||||
class QCA_CertContext
|
||||
{
|
||||
public:
|
||||
virtual ~QCA_CertContext() {}
|
||||
|
||||
virtual QCA_CertContext *clone()=0;
|
||||
virtual bool isNull() const=0;
|
||||
virtual bool createFromDER(const char *in, unsigned int len)=0;
|
||||
virtual bool createFromPEM(const char *in, unsigned int len)=0;
|
||||
virtual void toDER(char **out, unsigned int *len)=0;
|
||||
virtual void toPEM(char **out, unsigned int *len)=0;
|
||||
|
||||
virtual QString serialNumber() const=0;
|
||||
virtual QString subjectString() const=0;
|
||||
virtual QString issuerString() const=0;
|
||||
virtual QValueList<QCA_CertProperty> subject() const=0;
|
||||
virtual QValueList<QCA_CertProperty> issuer() const=0;
|
||||
virtual QDateTime notBefore() const=0;
|
||||
virtual QDateTime notAfter() const=0;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user