support storing Certificates on the Smart-card

This commit is contained in:
Christian Hohnstaedt 2009-11-15 19:40:55 +01:00
parent e61e58d917
commit 9182afd71c
12 changed files with 202 additions and 63 deletions

View File

@ -44,4 +44,5 @@ class errorEx
}
};
#define check_oom(ptr) if(!ptr){throw errorEx(QObject::tr("Out of Memory"));}
#endif

View File

@ -8,13 +8,14 @@
#include "pkcs11.h"
#include "pk11_attribute.h"
#include "exception.h"
#include <qobject.h>
void pk11_attr_ulong::load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
void pk11_attribute::load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
{
CK_RV rv;
rv = pkcs11::p11->C_GetAttributeValue(sess, obj, &attr, 1);
if (rv != CKR_OK)
pkcs11::pk11error("C_GetAttributeValue(ulong)", rv);
pkcs11::pk11error("C_GetAttribute()", rv);
}
void pk11_attr_data::load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
@ -28,8 +29,7 @@ void pk11_attr_data::load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
rv = pkcs11::p11->C_GetAttributeValue(sess, obj, &attr, 1);
if (rv == CKR_OK) {
attr.pValue = malloc(attr.ulValueLen +1);
if (!attr.pValue)
throw errorEx("Out of memory");
check_oom(attr.pValue);
rv = pkcs11::p11->C_GetAttributeValue(sess, obj, &attr, 1); \
if (rv == CKR_OK)
return;
@ -37,13 +37,12 @@ void pk11_attr_data::load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
pkcs11::pk11error("C_GetAttributeValue(data)", rv); \
}
void pk11_attr_data::setValue(const void *ptr, unsigned long len)
void pk11_attr_data::setValue(const unsigned char *ptr, unsigned long len)
{
if (attr.pValue)
free(attr.pValue);
attr.pValue = malloc(len);
if (!attr.pValue)
throw errorEx("Out of Memory");
check_oom(attr.pValue);
memcpy(attr.pValue, ptr, len);
attr.ulValueLen = len;
}
@ -56,3 +55,52 @@ void pk11_attribute::store(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj)
pkcs11::pk11error("C_SetAttributeValue", rv);
}
pk11_attlist::pk11_attlist(const pk11_attlist &a)
{
attlen = a.attlen;
alloc_len = a.alloc_len;
if (alloc_len) {
attributes =
(CK_ATTRIBUTE *)malloc(alloc_len *sizeof(*attributes));
check_oom(attributes);
memcpy(attributes, a.attributes, attlen *sizeof(*attributes));
}
for (unsigned long i=0; i<attlen; i++) {
void *p = malloc(attributes[i].ulValueLen);
check_oom(p);
memcpy(p, attributes[i].pValue, attributes[i].ulValueLen);
}
}
pk11_attlist::~pk11_attlist()
{
for (unsigned long i=0; i<attlen; i++)
free(attributes[i].pValue);
if (attributes)
free(attributes);
}
void pk11_attlist::addAttribute(const pk11_attribute &a)
{
CK_ATTRIBUTE *attr;
if (attlen == alloc_len) {
alloc_len = alloc_len ? alloc_len *2 : 16;
attributes = (CK_ATTRIBUTE *)realloc(attributes,
alloc_len * sizeof(*attributes));
check_oom(attributes);
}
attr = attributes + attlen++;
attr->type = a.attr.type;
attr->ulValueLen = a.attr.ulValueLen;
attr->pValue = malloc(attr->ulValueLen);
memcpy(attr->pValue, a.attr.pValue, attr->ulValueLen);
}
void pk11_attlist::reset()
{
for (unsigned long i=0; i<attlen; i++)
free(attributes[i].pValue);
attlen = 0;
}

View File

@ -15,8 +15,11 @@
#define UTF8QSTRING(x,s) QString::fromUtf8((const char*)(x), s).trimmed();
class pk11_attlist;
class pk11_attribute
{
friend class pk11_attlist;
protected:
CK_ATTRIBUTE attr;
@ -26,13 +29,36 @@ public:
memset(&attr, 0, sizeof(attr));
attr.type = type;
}
virtual void load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj) { }
virtual ~pk11_attribute() { }
const CK_ATTRIBUTE *getAttribute() const
{
return &attr;
}
void store(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
virtual void store(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
virtual void load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
};
class pk11_attr_bool: public pk11_attribute
{
protected:
unsigned char value;
public:
pk11_attr_bool(unsigned long type, bool v = false)
:pk11_attribute(type)
{
attr.pValue = &value;
attr.ulValueLen = sizeof(value);
setValue(v);
}
bool getValue() const
{
return value ? true : false;
}
void setValue(unsigned long v)
{
value = v ? 1 : 0;
}
};
class pk11_attr_ulong: public pk11_attribute
@ -41,10 +67,12 @@ protected:
unsigned long value;
public:
pk11_attr_ulong(unsigned long type) : pk11_attribute(type)
pk11_attr_ulong(unsigned long type, unsigned long v = 0)
:pk11_attribute(type)
{
attr.pValue = &value;
attr.ulValueLen = sizeof(value);
setValue(v);
}
unsigned long getValue() const
{
@ -54,17 +82,16 @@ public:
{
value = v;
}
void load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
};
class pk11_attr_data: public pk11_attribute
{
public:
pk11_attr_data(unsigned long type) : pk11_attribute(type)
pk11_attr_data(unsigned long type, const unsigned char *v = NULL,
unsigned long len = 0) :pk11_attribute(type)
{
attr.pValue = NULL;
attr.ulValueLen = 0;
setValue(v, len);
}
unsigned long getValue(const unsigned char **ptr)
{
@ -86,7 +113,45 @@ public:
attr.ulValueLen, NULL);
}
void load(CK_SESSION_HANDLE sess, CK_OBJECT_HANDLE obj);
void setValue(const void *ptr, unsigned long len);
void setValue(const unsigned char *ptr, unsigned long len);
};
class pk11_attlist {
private:
CK_ATTRIBUTE *attributes;
unsigned long attlen;
unsigned long alloc_len;
void init()
{
attlen = 0;
alloc_len = 0;
attributes = NULL;
}
public:
pk11_attlist()
{
init();
}
pk11_attlist(const pk11_attlist &a);
pk11_attlist(const pk11_attribute &a)
{
init();
addAttribute(a);
}
~pk11_attlist();
unsigned long get(CK_ATTRIBUTE **attp)
{
*attp = attributes;
return attlen;
}
void addAttribute(const pk11_attribute &a);
pk11_attlist &operator << (const pk11_attribute &a)
{
addAttribute(a);
return *this;
}
void reset();
};
#endif

View File

@ -60,8 +60,7 @@ QList<unsigned long> pkcs11::getSlotList()
p11_slots = (CK_SLOT_ID *)realloc(p11_slots,
num_slots *sizeof(CK_SLOT_ID));
if (!p11_slots)
throw errorEx("C_GetSlotList(Out of Memory)");
check_oom(p11_slots);
}
for (i=0; i<num_slots; i++) {
@ -82,8 +81,7 @@ QList<CK_MECHANISM_TYPE> pkcs11::mechanismList(unsigned long slot)
rv = p11->C_GetMechanismList(slot, NULL, &count);
if (count != 0) {
m = (CK_MECHANISM_TYPE *)malloc(count *sizeof(*m));
if (!m)
throw errorEx("C_GetMechanismList(Out of Memory)");
check_oom(m);
rv = p11->C_GetMechanismList(slot, m, &count);
if (rv != CKR_OK)
@ -112,7 +110,7 @@ bool pkcs11::needsLogin(bool so)
rv = p11->C_GetSessionInfo(session, &sinfo);
if (rv != CKR_OK)
pk11error("C_GetSessionInfo", rv);
printf("C_GetSessionInfo: %d\n", sinfo.state);
printf("C_GetSessionInfo: %lu\n", sinfo.state);
switch (sinfo.state) {
case CKS_RO_PUBLIC_SESSION:
@ -210,19 +208,33 @@ void pkcs11::storeAttribute(pk11_attribute &attribute, CK_OBJECT_HANDLE object)
attribute.store(session, object);
}
QList<CK_OBJECT_HANDLE> pkcs11::objectList(const pk11_attribute *att)
CK_OBJECT_HANDLE pkcs11::createObject(pk11_attlist &attrs)
{
CK_RV rv;
CK_ATTRIBUTE *attributes;
unsigned long num;
CK_OBJECT_HANDLE obj;
num = attrs.get(&attributes);
rv = p11->C_CreateObject(session, attributes, num, &obj);
if (rv != CKR_OK) {
pk11error("C_CreateObject", rv);
}
return obj;
}
QList<CK_OBJECT_HANDLE> pkcs11::objectList(pk11_attlist &atts)
{
CK_RV rv;
CK_OBJECT_HANDLE objects[256];
QList<CK_OBJECT_HANDLE> list;
unsigned long len, i;
const CK_ATTRIBUTE *attribute = NULL;
unsigned long len, i, att_num;
CK_ATTRIBUTE *attribute;
if (att)
attribute = att->getAttribute();
att_num = atts.get(&attribute);
rv = p11->C_FindObjectsInit(session, attribute, att_num);
rv = p11->C_FindObjectsInit(session, (CK_ATTRIBUTE *)attribute,
attribute ? 1 : 0);
if (rv != CKR_OK)
pk11error("C_FindObjectsInit", rv);

View File

@ -42,7 +42,7 @@ class pkcs11
CK_OBJECT_HANDLE object);
void storeAttribute(pk11_attribute &attribute,
CK_OBJECT_HANDLE object);
QList<CK_OBJECT_HANDLE> objectList(const pk11_attribute *att);
QList<CK_OBJECT_HANDLE> objectList(pk11_attlist &atts);
void login(unsigned char *pin, unsigned long pinlen, bool so);
void logout();
bool needsLogin(bool so);
@ -50,6 +50,7 @@ class pkcs11
unsigned char *pin, unsigned long pinLen);
void initPin(unsigned char *pin, unsigned long pinLen);
QList<CK_MECHANISM_TYPE> mechanismList(unsigned long slot);
CK_OBJECT_HANDLE createObject(pk11_attlist &attrs);
};
#endif

View File

@ -90,12 +90,6 @@ void pki_base::my_error(const QString error) const
}
}
void pki_base::check_oom(const void *ptr) const
{
if (!ptr)
my_error(tr("Out of memory"));
}
void pki_base::openssl_error(const QString txt) const
{
QString errtxt = "";

View File

@ -28,7 +28,6 @@ class pki_base : public QObject
pki_base *parent;
void my_error(const QString myerr) const;
void check_oom(const void *ptr) const;
void fopen_error(const QString fname);
public:

View File

@ -250,6 +250,17 @@ void pki_scard::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
openssl_error();
}
int pki_scard::getIdBin(unsigned char **to)
{
int l;
BIGNUM *bn = NULL;
BN_hex2bn(&bn, CCHAR(object_id));
l = BN_num_bytes(bn);
*to = (unsigned char*)malloc(l);
BN_bn2bin(bn, *to);
return l;
}
QList<int> pki_scard::possibleHashNids()
{
QList<int> nids;
@ -265,13 +276,12 @@ QList<int> pki_scard::possibleHashNids()
case CKM_SHA384_RSA_PKCS: nids << NID_sha384; break;
case CKM_SHA512_RSA_PKCS: nids << NID_sha512; break;
case CKM_RIPEMD160_RSA_PKCS: nids << NID_ripemd160; break;
case CKM_RSA_PKCS:
QList<int> n; n << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
printf("ALL NIDS\n");
return n;
}
}
if (nids.count() == 0) {
nids << NID_md5 << NID_sha1 << NID_sha256 <<
NID_sha384 << NID_sha512 << NID_ripemd160;
}
return nids;
}
@ -310,14 +320,13 @@ int pki_scard::prepare_card() const
}
}
pk11_attr_ulong class_att = pk11_attr_ulong(CKA_CLASS);
QList<CK_OBJECT_HANDLE> objects;
for (i=0; i<p11_slots.count(); i++) {
p11.startSession(p11_slots[i]);
class_att.setValue(CKO_PUBLIC_KEY);
objects = p11.objectList(&class_att);
pk11_attlist cls (pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY));
objects = p11.objectList(cls);
for (int j=0; j< objects.count(); j++) {
CK_OBJECT_HANDLE object = objects[j];

View File

@ -57,6 +57,7 @@ class pki_scard: public pki_key
void setMech_list(QList<CK_MECHANISM_TYPE> ml) { mech_list = ml; };
QList<int> possibleHashNids();
EVP_PKEY *load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const;
int getIdBin(unsigned char **to);
};

View File

@ -9,6 +9,7 @@
#include "pki_temp.h"
#include "func.h"
#include "db.h"
#include "exception.h"
#include <qdir.h>
QPixmap *pki_temp::icon= NULL;

View File

@ -207,8 +207,9 @@ void pki_x509::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
void pki_x509::store_token()
{
pki_scard *card = (pki_scard *)privkey;
int slot, size;
unsigned char*p, *p1;
int slot, size, id_size;
unsigned char *p, *p1, *id;
const unsigned char *label;
QList<CK_OBJECT_HANDLE> objects;
if (!privkey || !privkey->isScard())
@ -219,28 +220,32 @@ void pki_x509::store_token()
size = i2d_X509(cert, NULL);
openssl_error();
p = p1 = (unsigned char*)OPENSSL_malloc(size);
i2d_X509(cert, &p1);
openssl_error();
pk11_attr_data x509(CKA_VALUE);
x509.setValue(p, size);
free(p);
pk11_attr_ulong class_att = pk11_attr_ulong(CKA_CLASS);
class_att.setValue(CKO_CERTIFICATE);
id_size = card->getIdBin(&id);
openssl_error();
label = (const unsigned char *)desc.toUtf8().constData();
pk11_attlist p11_atts;
p11_atts <<
pk11_attr_ulong(CKA_CLASS, CKO_CERTIFICATE) <<
pk11_attr_ulong(CKA_CERTIFICATE_TYPE, CKC_X_509) <<
pk11_attr_bool(CKA_TOKEN, true) <<
pk11_attr_data(CKA_VALUE, p, size) <<
pk11_attr_data(CKA_ID, id, id_size) <<
pk11_attr_data(CKA_LABEL, label, strlen((const char*)label));
free(p);
free(id);
pkcs11 p11;
p11.startSession(slot, true);
objects = p11.objectList(&class_att);
if (objects.count() == 0)
throw errorEx(tr("No certificate object found"));
if (objects.count() > 1)
throw errorEx(tr("More than one certificate objects found"));
if (card->scardLogin(p11, false).isNull())
return;
p11.storeAttribute(x509, objects[0]);
openssl_error();
p11.createObject(p11_atts);
}
bool pki_x509::verifyQASerial(const a1int &secret) const

View File

@ -366,7 +366,6 @@ void MainWindow::importScard()
try {
ImportMulti *dlgi = new ImportMulti(this);
QList<CK_OBJECT_HANDLE> objects;
pk11_attr_ulong class_att = pk11_attr_ulong(CKA_CLASS);
p11_slots = p11.getSlotList();
if (p11_slots.count() == 0)
@ -377,8 +376,10 @@ void MainWindow::importScard()
QList<CK_MECHANISM_TYPE> ml = p11.mechanismList(i);
if (ml.count() == 0)
ml << CKM_SHA1_RSA_PKCS;
class_att.setValue(CKO_PUBLIC_KEY);
objects = p11.objectList(&class_att);
pk11_attlist atts(pk11_attr_ulong(CKA_CLASS,
CKO_PUBLIC_KEY));
objects = p11.objectList(atts);
for (int j=0; j< objects.count(); j++) {
card = new pki_scard("");
@ -392,8 +393,10 @@ void MainWindow::importScard()
}
card = NULL;
}
class_att.setValue(CKO_CERTIFICATE);
objects = p11.objectList(&class_att);
atts.reset();
atts << pk11_attr_ulong(CKA_CLASS, CKO_CERTIFICATE) <<
pk11_attr_ulong(CKA_CERTIFICATE_TYPE,CKC_X_509);
objects = p11.objectList(atts);
for (int j=0; j< objects.count(); j++) {
cert = new pki_x509("");