improve token handling

- add tokenInfo.model to the card information, revamp tokenInfo
 - add driverInfo()
 - use token_info.label (card_label) as token descriptor for reading passwords
 - use only CKA_LABEL as internal name
This commit is contained in:
Christian Hohnstaedt 2010-02-28 10:31:53 +01:00
parent 01fa5628ed
commit 825fea569d
14 changed files with 144 additions and 96 deletions

View File

@ -14,7 +14,8 @@
#include "opensc-pkcs11.h"
#include "exception.h"
#define UTF8QSTRING(x,s) QString::fromUtf8((const char*)(x), s).trimmed();
#define UTF8QSTRING(x,s) QString::fromUtf8((const char*)(x), s).trimmed()
#define ASCIIQSTRING(x,s) QString::fromAscii((const char*)(x), s).trimmed()
class pk11_attlist;

View File

@ -176,7 +176,7 @@ QString pkcs11::tokenLogin(QString name, bool so, bool force)
if (force || need_login) {
if (!need_login)
logout();
if (protAuthPath()) {
if (tokenInfo().protAuthPath()) {
pin = NULL;
pinlen = 0;
} else {
@ -201,9 +201,9 @@ bool pkcs11::selectToken(unsigned long *slot, QWidget *w)
}
QStringList slotnames;
for (int i=0; i<p11_slots.count(); i++) {
QStringList info = tokenInfo(p11_slots[i]);
tkInfo info = tokenInfo(p11_slots[i]);
slotnames << QString("%1 (#%2)").
arg(info[0]).arg(info[2]);
arg(info.label()).arg(info.serial());
}
Ui::SelectToken ui;
QDialog *select_slot = new QDialog(w);
@ -246,9 +246,8 @@ void pkcs11::initToken(unsigned long slot, unsigned char *pin, int pinlen,
pk11error("C_InitToken", rv);
}
QStringList pkcs11::tokenInfo(CK_SLOT_ID slot)
tkInfo pkcs11::tokenInfo(CK_SLOT_ID slot)
{
QStringList l;
CK_TOKEN_INFO token_info;
CK_RV rv;
@ -256,34 +255,34 @@ QStringList pkcs11::tokenInfo(CK_SLOT_ID slot)
if (rv != CKR_OK) {
pk11error("C_GetTokenInfo", rv);
}
l << UTF8QSTRING(token_info.label, 32);
l << UTF8QSTRING(token_info.manufacturerID, 32);
l << UTF8QSTRING(token_info.serialNumber, 16);
return l;
return tkInfo(&token_info);
}
QStringList pkcs11::tokenInfo()
QString pkcs11::driverInfo()
{
CK_INFO info;
CK_RV rv;
rv = p11->C_GetInfo(&info);
if (rv != CKR_OK) {
pk11error("C_GetInfo", rv);
}
return QString(
"Cryptoki version: %1.%2\n"
"Manufacturer: %3\n"
"Library: %4 (%5.%6)\n").
arg(info.cryptokiVersion.major).arg(info.cryptokiVersion.minor).
arg(UTF8QSTRING(info.manufacturerID, 32)).
arg(UTF8QSTRING(info.libraryDescription, 32)).
arg(info.libraryVersion.major).arg(info.libraryVersion.minor);
}
tkInfo pkcs11::tokenInfo()
{
return tokenInfo(slot_id);
}
bool pkcs11::protAuthPath(CK_SLOT_ID slot)
{
CK_TOKEN_INFO token_info;
CK_RV rv;
rv = p11->C_GetTokenInfo(slot, &token_info);
if (rv != CKR_OK) {
pk11error("C_GetTokenInfo", rv);
}
return !!(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH);
}
bool pkcs11::protAuthPath()
{
return protAuthPath(slot_id);
}
void pkcs11::loadAttribute(pk11_attribute &attribute, CK_OBJECT_HANDLE object)
{
attribute.load(session, object);

View File

@ -9,6 +9,45 @@
#include "pk11_attribute.h"
class tkInfo
{
private:
CK_TOKEN_INFO token_info;
public:
tkInfo(const CK_TOKEN_INFO *ti)
{
set(ti);
}
tkInfo(const tkInfo &tk)
{
set(&tk.token_info);
}
void set(const CK_TOKEN_INFO *ti)
{
memcpy(&token_info, ti, sizeof(token_info));
}
QString label() const
{
return UTF8QSTRING(token_info.label, 32);
}
QString manufacturerID() const
{
return UTF8QSTRING(token_info.manufacturerID, 32);
}
QString model() const
{
return UTF8QSTRING(token_info.model, 16);
}
QString serial() const
{
return ASCIIQSTRING(token_info.serialNumber, 16);
}
bool protAuthPath() const
{
return !!(token_info.flags & CKF_PROTECTED_AUTHENTICATION_PATH);
}
};
class pkcs11
{
friend class pk11_attribute;
@ -23,18 +62,18 @@ class pkcs11
CK_SLOT_ID slot_id;
CK_OBJECT_HANDLE object;
public:
void init_pkcs11();
static void pk11error(QString fmt, int r);
static bool loaded() { return !!p11; };
static bool loaded()
{
return !!p11;
};
pkcs11();
~pkcs11();
static bool load_lib(QString file, bool silent);
QStringList tokenInfo(CK_SLOT_ID slot);
QStringList tokenInfo();
bool protAuthPath(CK_SLOT_ID slot);
bool protAuthPath();
tkInfo tokenInfo(CK_SLOT_ID slot);
tkInfo tokenInfo();
void startSession(unsigned long slot, bool rw = false);
QList<unsigned long> getSlotList();
@ -61,6 +100,7 @@ class pkcs11
void initToken(unsigned long slot, unsigned char *pin,
int pinlen, QString label);
bool selectToken(unsigned long *slot, QWidget *w);
QString driverInfo();
};
#endif

View File

@ -71,7 +71,8 @@ static void incProgress(int, int, void *progress)
QString pki_evp::removeTypeFromIntName(QString n)
{
if (n.right(1) != ")" ) return n;
if (n.right(1) != ")" )
return n;
n.truncate(n.length() - 6);
return n;
}
@ -644,14 +645,6 @@ void pki_evp::writeKey(const QString fname, const EVP_CIPHER *enc,
fclose(fp);
}
QString pki_evp::length()
{
if (key->type == EVP_PKEY_DSA && key->pkey.dsa->p == NULL) {
return QString("???");
}
return QString("%1 bit").arg(EVP_PKEY_bits(key));
}
bool pki_evp::isPubKey() const
{
if (encKey_len == 0 || encKey == NULL) {

View File

@ -64,7 +64,6 @@ class pki_evp: public pki_key
void fromData(const unsigned char *p, db_header_t *head);
void oldFromData(unsigned char *p, int size);
unsigned char *toData(int *size);
QString length();
void writeKey(const QString fname, const EVP_CIPHER *enc,
pem_password_cb *cb, bool pem);
void writePKCS8(const QString fname, const EVP_CIPHER *enc,

View File

@ -44,6 +44,14 @@ pki_key::~pki_key()
EVP_PKEY_free(key);
}
QString pki_key::length()
{
if (key->type == EVP_PKEY_DSA && key->pkey.dsa->p == NULL) {
return QString("???");
}
return QString("%1 bit").arg(EVP_PKEY_bits(key));
}
QString pki_key::getTypeString()
{
QString type;

View File

@ -39,13 +39,12 @@ class pki_key: public pki_base
virtual bool isPubKey() const { return true; };
virtual const EVP_MD *getDefaultMD() { return NULL; };
virtual bool isToken();
virtual QString length() { return tr("Unknown"); };
virtual QString getTypeString(void);
virtual QString getIntNameWithType(void);
virtual QList<int> possibleHashNids()
{ return QList<int>(); };
virtual QString getFriendlyClassName();
virtual QString length();
void writePublic(const QString fname, bool pem);
bool compare(pki_base *ref);

View File

@ -84,6 +84,7 @@ bool pki_scard::init_p11engine(QString file, bool silent)
if (!pkcs11::load_lib(file, silent))
return false;
log += "Successfully loaded PKCS#11 library: " +file +"\n";
#ifdef WIN32
engine_path = ".\\" ENGINE_LIB;
#else
@ -101,6 +102,10 @@ bool pki_scard::init_p11engine(QString file, bool silent)
XCA_ENGINE_cmd("VERBOSE", NULL);
ENGINE_init(e);
pkcs11 p11;
log += p11.driverInfo();
if (!silent) {
openssl_error(log);
} else {
@ -115,12 +120,12 @@ void pki_scard::init(void)
{
class_name = "pki_scard";
ownPass = ptPin;
dataVersion = 1;
dataVersion = 2;
pkiType = smartCard;
cols = 5;
card_serial = card_manufacturer = card_label = "";
bit_length = slot_label = "";
card_model = slot_label = "";
}
pki_scard::pki_scard(const QString name)
@ -212,10 +217,11 @@ EVP_PKEY *pki_scard::load_pubkey(pkcs11 &p11, CK_OBJECT_HANDLE object) const
void pki_scard::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
{
QStringList sl = p11.tokenInfo();
card_label = sl[0];
card_manufacturer = sl[1];
card_serial = sl[2];
tkInfo ti = p11.tokenInfo();
card_label = ti.label();
card_manufacturer = ti.manufacturerID();
card_serial = ti.serial();
card_model = ti.model();
pk11_attr_data id(CKA_ID);
p11.loadAttribute(id, object);
@ -255,9 +261,8 @@ void pki_scard::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
if (key)
EVP_PKEY_free(key);
key = pkey;
bit_length.setNum(EVP_PKEY_bits(pkey));
}
setIntName(card_label + " (" + slot_label + ")");
setIntName(slot_label);
openssl_error();
}
@ -287,7 +292,7 @@ void pki_scard::deleteFromToken()
pkcs11 p11;
p11.startSession(slot, true);
if (p11.tokenLogin(getIntName(), false).isNull())
if (p11.tokenLogin(card_label, false).isNull())
return;
pk11_attlist attrs(pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY));
@ -341,7 +346,7 @@ void pki_scard::store_token(unsigned int slot, EVP_PKEY *pkey)
pub_atts <<
pk11_attr_bool(CKA_TOKEN, true) <<
pk11_attr_data(CKA_LABEL, desc.toUtf8()) <<
pk11_attr_data(CKA_LABEL, getIntName().toUtf8()) <<
new_id <<
pk11_attr_data(CKA_PUBLIC_EXPONENT, rsakey->e, false) <<
pk11_attr_bool(CKA_ENCRYPT, true) <<
@ -362,9 +367,8 @@ void pki_scard::store_token(unsigned int slot, EVP_PKEY *pkey)
pk11_attr_bool(CKA_DECRYPT, true) <<
pk11_attr_bool(CKA_SIGN, true);
QStringList sl = p11.tokenInfo();
setIntName(sl[0] + " (" + desc + ")");
if (p11.tokenLogin(getIntName(), false).isNull())
tkInfo ti = p11.tokenInfo();
if (p11.tokenLogin(ti.label(), false).isNull())
return;
p11.createObject(pub_atts);
@ -445,18 +449,20 @@ bool pki_scard::prepare_card(unsigned long *slot, bool verifyPubkey) const
p11_slots = p11.getSlotList();
for (i=0; i<p11_slots.count(); i++) {
pkcs11 myp11;
QStringList sl = myp11.tokenInfo(p11_slots[i]);
if (sl[0] == card_label &&
sl[1] == card_manufacturer &&
sl[2] == card_serial)
tkInfo ti = myp11.tokenInfo(p11_slots[i]);
if (ti.label() == card_label &&
ti.manufacturerID() == card_manufacturer &&
ti.serial() == card_serial &&
(card_model.isEmpty() || ti.model() == card_model))
{
break;
}
}
if (i < p11_slots.count())
break;
QString msg = tr("Please insert card: %1 [%2] with Serial: %3").
arg(card_manufacturer).arg(card_label).arg(card_serial);
QString msg = tr("Please insert card: %1 %2 [%3] with Serial: %4").
arg(card_manufacturer).arg(card_model).
arg(card_label).arg(card_serial);
int r = QMessageBox::warning(NULL, XCA_TITLE, msg,
QMessageBox::Cancel | QMessageBox::Ok);
@ -496,16 +502,14 @@ void pki_scard::generateKey_card(unsigned long slot, int size, QProgressBar *bar
pkcs11 p11;
p11.startSession(slot, true);
QString name = getIntName();
QStringList sl = p11.tokenInfo();
setIntName(sl[0] + " (" + name + ")");
tkInfo ti = p11.tokenInfo();
if (p11.tokenLogin(getIntName(), false).isNull())
if (p11.tokenLogin(ti.label(), false).isNull())
return;
bar->setValue(bar->value()+1);
pk11_attr_data id = p11.generateRSAKey(name, size);
pk11_attr_data id = p11.generateRSAKey(getIntName(), size);
atts << pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY) << id;
QList<CK_OBJECT_HANDLE> objects = p11.objectList(atts);
@ -529,7 +533,7 @@ unsigned char *pki_scard::toData(int *size)
int i;
s = card_serial.length() + card_manufacturer.length() +
card_label.length() + bit_length.length() +
card_label.length() + card_model.length() +
slot_label.length() + object_id.length() +
7 *sizeof(char) + i2d_PUBKEY(key, NULL) +
(mech_list.count() + 1) * sizeof(uint32_t);
@ -543,7 +547,7 @@ unsigned char *pki_scard::toData(int *size)
db::stringToData(&p1, card_manufacturer);
db::stringToData(&p1, card_label);
db::stringToData(&p1, slot_label);
db::stringToData(&p1, bit_length);
db::stringToData(&p1, card_model);
db::stringToData(&p1, object_id);
db::intToData(&p1, mech_list.count());
for (i=0; i<mech_list.count(); i++)
@ -569,7 +573,9 @@ void pki_scard::fromData(const unsigned char *p, db_header_t *head )
card_manufacturer = db::stringFromData(&p1);
card_label = db::stringFromData(&p1);
slot_label = db::stringFromData(&p1);
bit_length = db::stringFromData(&p1);
card_model = db::stringFromData(&p1);
if (version < 2)
card_model.clear();
object_id = db::stringFromData(&p1);
count = db::intFromData(&p1);
mech_list.clear();
@ -612,7 +618,7 @@ EVP_PKEY *pki_scard::decryptKey() const
pkcs11 p11;
p11.startSession(slot_id, true);
pin = p11.tokenLogin(getIntName(), false);
pin = p11.tokenLogin(card_label, false);
if (pin.isNull())
throw errorEx(tr("Invalid Pin for the token"));
cb_data.password = strdup(CCHAR(pin));
@ -635,10 +641,10 @@ void pki_scard::changePin()
pkcs11 p11;
p11.startSession(slot, true);
p11.logout();
if (p11.protAuthPath()) {
if (p11.tokenInfo().protAuthPath()) {
p11.setPin(NULL, 0, NULL ,0);
}
pin = p11.tokenLogin(getIntName(), false, true);
pin = p11.tokenLogin(card_label, false, true);
if (pin.isNull())
return;
pass_info p(XCA_TITLE, tr("Please enter the new Pin for the token '%1'").
@ -726,11 +732,6 @@ bool pki_scard::isToken()
return true;
}
QString pki_scard::length()
{
return bit_length + " bit";
}
QVariant pki_scard::getIcon(int column)
{
return column == 0 ? QVariant(*icon[0]) : QVariant();

View File

@ -20,7 +20,7 @@ class pki_scard: public pki_key
protected:
QString card_serial;
QString card_manufacturer;
QString bit_length;
QString card_model;
QString card_label;
QString slot_label;
QString object_id;
@ -41,12 +41,12 @@ class pki_scard: public pki_key
QString getTypeString(void);
QString getManufacturer() const { return card_manufacturer; }
QString getSerial() const { return card_serial; }
QString getModel() const { return card_model; }
QString getLabel() const { return slot_label; }
QString getId() const { return object_id; }
pk11_attr_data getIdAttr() const;
QString getCardLabel() const { return card_label; }
EVP_PKEY *decryptKey() const;
QString length();
QString scardLogin(pkcs11 &p11, bool so, bool force=false)const;
void changePin();
void initPin();

View File

@ -182,7 +182,6 @@ a1int pki_x509::getQASerial(const a1int &secret) const
void pki_x509::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
{
QStringList sl = p11.tokenInfo();
const unsigned char *p;
unsigned long s;
QString desc;
@ -223,7 +222,7 @@ void pki_x509::load_token(pkcs11 &p11, CK_OBJECT_HANDLE object)
// IGNORE
}
}
setIntName(sl[0] + " (" + desc + ")");
setIntName(desc);
openssl_error();
}
@ -317,15 +316,15 @@ void pki_x509::deleteFromToken()
if (!objs.count())
continue;
QStringList info = p11.tokenInfo(slot);
tkInfo ti = p11.tokenInfo(slot);
if (QMessageBox::question(NULL, XCA_TITLE,
tr("Delete the certificate '%1' from the token '%2 (#%3)' ?").
arg(getIntName()).arg(info[0]).arg(info[2]),
arg(getIntName()).arg(ti.label()).arg(ti.serial()),
QMessageBox::Yes | QMessageBox::No) != QMessageBox::Yes)
{
continue;
}
if (p11.tokenLogin(info[0], false).isNull())
if (p11.tokenLogin(ti.label(), false).isNull())
continue;
p11.deleteObjects(attrs);

View File

@ -53,7 +53,8 @@ void KeyDetail::setKey(pki_key *key)
image->setPixmap(*MainWindow::scardImg);
pki_scard *card = (pki_scard *)key;
cardBox->setTitle(tr("Token") +" [" +card->getCardLabel() +"]");
cardManufacturer->setText(card->getManufacturer());
cardManufacturer->setText(card->getManufacturer() + " " +
card->getModel());
cardSerial->setText(card->getSerial());
keyPrivEx->setText(tr("Security token ID:%1").arg(card->getId()));
keyBox->setTitle(tr("Key") + " [" + card->getLabel() + "]");

View File

@ -375,9 +375,9 @@ void MainWindow::initToken()
if (!p11.selectToken(&slot, this))
return;
QStringList info = p11.tokenInfo(slot);
tkInfo ti = p11.tokenInfo(slot);
QString slotname = QString("%1 (#%2)").
arg(info[0]).arg(info[2]);
arg(ti.label()).arg(ti.serial());
pass_info p(XCA_TITLE,
tr("Please enter the SO PIN (PUK) of the token '%1'").

View File

@ -42,10 +42,10 @@ class keyListItem
slot = nslot;
CK_MECHANISM_INFO mechinfo;
p11->mechanismInfo(slot, m, &mechinfo);
QStringList info = p11->tokenInfo(slot);
tkInfo ti = p11->tokenInfo(slot);
tl = typeList; //idx of EVP_PKEY_RSA
printname = QString("%1 #%2 (%3 Key of %4 - %5 bits)").
arg(info[0]).arg(info[2]).
arg(ti.label()).arg(ti.serial()).
arg(tl->name).
arg(mechinfo.ulMinKeySize).
arg(mechinfo.ulMaxKeySize);

View File

@ -90,12 +90,20 @@ void Options::on_tryLoadButton_clicked(void)
{
try {
QString lib = pkcs11path->text();
#ifdef WIN32
pkcs11::load_lib(lib, false);
#else
pki_scard::init_p11engine(lib, false);
pkcs11 p11;
p11.getSlotList();
#endif
QString info;
if (pkcs11::loaded()) {
pkcs11 p11;
info = p11.driverInfo();
}
if (!lib.isEmpty()) {
QMessageBox::information(this, XCA_TITLE,
tr("Successfully loaded PKCS#11 library: ") + lib);
tr("Successfully loaded PKCS#11 library: %1\n").
arg(lib) + info);
}
} catch (errorEx &err) {
mw->Error(err);