4
0
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:
Justin Karneges 2003-07-22 16:54:36 +00:00
parent ea83f0a99f
commit aadd9caa59
7 changed files with 498 additions and 13 deletions

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

@ -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

@ -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;
}
};

@ -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());
}

@ -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