Yubikey select one of the special IDs

Yubikey defines and enforces 4 (NEO) or 24 (YubiKey YK4, YubiKey YK5)
slots with special, fixed names.

Add a dropdown box if "fixed_ids" are present and let the user select
the slot during key generation.
This commit is contained in:
Christian Hohnstaedt 2024-02-28 21:59:41 +01:00
parent 844e74632b
commit 4b37902052
4 changed files with 67 additions and 13 deletions

View File

@ -480,7 +480,7 @@ pk11_attr_data pkcs11::findUniqueID(unsigned long oclass) const
}
pk11_attr_data pkcs11::generateKey(QString name, unsigned long mech,
unsigned long bits, int nid)
unsigned long bits, int nid, const pk11_attr_data &id)
{
#ifdef OPENSSL_NO_EC
(void)nid;
@ -492,9 +492,7 @@ pk11_attr_data pkcs11::generateKey(QString name, unsigned long mech,
CK_MECHANISM mechanism = {mech, NULL_PTR, 0};
pk11_attr_data label(CKA_LABEL, name.toUtf8());
pk11_attr_data new_id = findUniqueID(CKO_PUBLIC_KEY);
pub_atts << label << new_id <<
pub_atts << label << id <<
pk11_attr_ulong(CKA_CLASS, CKO_PUBLIC_KEY) <<
pk11_attr_bool(CKA_TOKEN, true) <<
pk11_attr_bool(CKA_PRIVATE, false) <<
@ -502,7 +500,7 @@ pk11_attr_data pkcs11::generateKey(QString name, unsigned long mech,
pk11_attr_bool(CKA_VERIFY, true) <<
pk11_attr_bool(CKA_WRAP, true);
priv_atts << label << new_id <<
priv_atts << label << id <<
pk11_attr_ulong(CKA_CLASS, CKO_PRIVATE_KEY) <<
pk11_attr_bool(CKA_TOKEN, true) <<
pk11_attr_bool(CKA_PRIVATE, true) <<
@ -571,7 +569,7 @@ pk11_attr_data pkcs11::generateKey(QString name, unsigned long mech,
if (rv != CKR_OK) {
pk11error("C_GenerateKeyPair", rv);
}
return new_id;
return id;
}
QList<CK_OBJECT_HANDLE> pkcs11::objectList(pk11_attlist &atts) const

View File

@ -114,6 +114,32 @@ public:
// issue to generate Domain Parameters
return manufacturerID() == "nCipher Corp. Ltd";
}
QList<QStringList> fixed_ids() const
{
// Yubi keys have fixed set of IDs
// Use QStringList to not invent a new type: (QString + unsigned)
static const QList<QStringList> ids {
{ "9a: PIV Authentication", "1" },
{ "9c: Digital Signature", "2" },
{ "9d: Key Management", "3" },
{ "9e: Card Authentication", "4" }
};
if (manufacturerID() == "Yubico (www.yubico.com)") {
if (model() == "YubiKey NEO")
return ids;
if (model() == "YubiKey YK4" || model() == "YubiKey YK5") {
QList<QStringList> retired(ids);
for (int i=0; i< 20; i++)
retired.append(QStringList {
QString("%1: Retired Key %2")
.arg(i+0x82, 0, 16).arg(i+1),
QString::number(i + 5)
});
return retired;
}
}
return QList<QStringList>();
}
};
class pkcs11
@ -177,7 +203,8 @@ class pkcs11
CK_OBJECT_HANDLE createObject(pk11_attlist &attrs);
pk11_attr_data findUniqueID(unsigned long oclass) const;
pk11_attr_data generateKey(QString name,
unsigned long ec_rsa_mech, unsigned long bits, int nid);
unsigned long ec_rsa_mech, unsigned long bits, int nid,
const pk11_attr_data &id);
int deleteObjects(QList<CK_OBJECT_HANDLE> objects);
EVP_PKEY *getPrivateKey(EVP_PKEY *pub, CK_OBJECT_HANDLE obj);
int encrypt(int flen, const unsigned char *from,

View File

@ -19,6 +19,7 @@
#include "XcaWarningCore.h"
#include <QThread>
#include <QInputDialog>
void pki_scard::init(void)
{
@ -450,7 +451,7 @@ void pki_scard::store_token(const slotid &slot, EVP_PKEY *pkey)
load_token(p11, objs[0]);
return;
}
pk11_attr_data new_id = p11.findUniqueID(CKO_PUBLIC_KEY);
pk11_attr_data new_id = select_id(p11);
pub_atts << new_id <<
pk11_attr_bool(CKA_TOKEN, true) <<
@ -654,25 +655,50 @@ class keygenThread: public QThread
{
public:
errorEx err;
pk11_attr_data id;
const keyjob task;
QString name;
pkcs11 *p11;
pk11_attr_data id;
keygenThread(const keyjob &t, const QString &n, pkcs11 *_p11)
: QThread(), task(t), name(n), p11(_p11) { }
keygenThread(const keyjob &t, const QString &n, pkcs11 *_p11,
const pk11_attr_data &_id)
: QThread(), task(t), name(n), p11(_p11), id(_id) { }
void run()
{
try {
id = p11->generateKey(name, task.ktype.mech, task.size,
task.ec_nid);
task.ec_nid, id);
} catch (errorEx &e) {
err = e;
}
}
};
pk11_attr_data pki_scard::select_id(const pkcs11 &p11) const
{
tkInfo ti = p11.tokenInfo();
pk11_attr_data new_id(CKA_ID);
QList<QStringList> fixed_ids = ti.fixed_ids();
if (fixed_ids.size() > 0) {
QMap<QString, unsigned long> map;
QStringList items;
for (QStringList item : fixed_ids) {
items << item[0];
map[item[0]] = item[1].toULong();
}
QString idname = QInputDialog::getItem(nullptr, XCA_TITLE,
tr("Select Slot of %1").arg(ti.model()),
items, 0, false);
if (map.contains(idname))
new_id.setULong(map[idname]);
} else {
new_id = p11.findUniqueID(CKO_PUBLIC_KEY);
}
return new_id;
}
void pki_scard::generate(const keyjob &task)
{
pk11_attlist atts;
@ -681,11 +707,13 @@ void pki_scard::generate(const keyjob &task)
p11.startSession(task.slot, true);
p11.getRandom();
pk11_attr_data new_id = select_id(p11);
if (!p11.tokenLoginForModification())
return;
XcaProgress progress;
keygenThread kt(task, getIntName(), &p11);
keygenThread kt(task, getIntName(), &p11, new_id);
kt.start();
while (!kt.wait(20)) {
progress.increment();

View File

@ -79,6 +79,7 @@ class pki_scard: public pki_key
{
return mech_list;
}
pk11_attr_data select_id(const pkcs11 &p11) const;
pk11_attlist objectAttributes(bool priv) const;
pk11_attlist objectAttributesNoId(EVP_PKEY *pk, bool priv) const;
void setMech_list(QList<CK_MECHANISM_TYPE> ml) { mech_list = ml; };