mirror of
https://github.com/chris2511/xca.git
synced 2026-09-12 19:51:05 +05:00
support storing Certificates on the Smart-card
This commit is contained in:
parent
e61e58d917
commit
9182afd71c
@ -44,4 +44,5 @@ class errorEx
|
||||
}
|
||||
};
|
||||
|
||||
#define check_oom(ptr) if(!ptr){throw errorEx(QObject::tr("Out of Memory"));}
|
||||
#endif
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 = "";
|
||||
|
||||
@ -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:
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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);
|
||||
|
||||
};
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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("");
|
||||
|
||||
Loading…
Reference in New Issue
Block a user