xca/lib/pkcs11.h
Christian Hohnstaedt 4b37902052 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.
2024-02-29 17:57:46 +01:00

218 lines
5.7 KiB
C++

/* vi: set sw=4 ts=4:
*
* Copyright (C) 2009 - 2011 Christian Hohnstaedt.
*
* All rights reserved.
*/
#ifndef __XCA_PKCS11_H
#define __XCA_PKCS11_H
#include "pkcs11_lib.h"
#include "opensc-pkcs11.h"
#include <QStringList>
#include <QString>
#include <QList>
#include "pk11_attribute.h"
#include "func.h"
void waitcursor(int start, int line);
#define WAITCURSOR_START waitcursor(1, __LINE__);
#define WAITCURSOR_END waitcursor(0, __LINE__);
extern char segv_data[1024];
#define CALL_P11_C(l, func, ...) do { \
snprintf(segv_data, sizeof segv_data, "Crashed in %s in %s from %s:%d\n" \
"This looks like a bug in the PKC#11 library and not in XCA\n", \
#func, CCHAR((l)->filename()), __func__, __LINE__); \
if (IS_GUI_APP) \
QApplication::setOverrideCursor(QCursor(Qt::WaitCursor)); \
rv = l->ptr()->func(__VA_ARGS__); \
segv_data[0] = 0; \
if (IS_GUI_APP) \
QApplication::restoreOverrideCursor(); \
ign_openssl_error(); \
} while(0);
class tkInfo
{
private:
CK_TOKEN_INFO token_info{};
public:
tkInfo() { }
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));
// sanitize strings
for (int i=0; i<32; i++) {
if (token_info.label[i] == 0)
token_info.label[i] = ' ';
if (token_info.manufacturerID[i] == 0)
token_info.manufacturerID[i] = ' ';
}
for (int i=0; i<16; i++) {
if (token_info.model[i] == 0)
token_info.model[i] = ' ';
if (token_info.serialNumber[i] == 0)
token_info.serialNumber[i] = ' ';
}
}
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);
}
bool tokenInitialized() const
{
return !!(token_info.flags & CKF_TOKEN_INITIALIZED);
}
QString pinInfo() const
{
return QObject::tr("Required PIN size: %1 - %2").
arg(token_info.ulMinPinLen).
arg(token_info.ulMaxPinLen);
}
bool force_keygen_named_curve() const
{
// Workaround for "www.CardContact.de" bug
return manufacturerID() == "www.CardContact.de";
}
bool need_SO_for_object_mod() const
{
// Yubikey Need SO Pin to modify objects
return manufacturerID() == "Yubico (www.yubico.com)";
}
bool set_token_attr_false_dsa_param() const
{
// nCipher Attributes
// as on 10/26/2015 - Thales' PKCS11 provider has
// 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
{
friend class pk11_attribute;
friend class pk11_attr_ulong;
friend class pk11_attr_data;
private:
slotid p11slot;
CK_SESSION_HANDLE session;
CK_OBJECT_HANDLE p11obj;
static int pctr;
public:
static pkcs11_lib_list libraries;
pkcs11();
~pkcs11();
CK_RV tokenInfo(const slotid &slot, tkInfo *tkinfo) const;
tkInfo tokenInfo(const slotid &slot) const;
tkInfo tokenInfo() const
{
return tokenInfo(p11slot);
}
QString driverInfo(const slotid &slot) const
{
return slot.lib->driverInfo();
}
static slotidList getSlotList()
{
return libraries.getSlotList();
}
void closeSession(const slotid &slot);
bool selectToken(slotid *slot, QWidget *w);
void changePin(const slotid &slot, bool so);
void initPin(const slotid &slot);
void initToken(const slotid &slot, unsigned char *pin,
int pinlen, QString label);
QList<CK_MECHANISM_TYPE> mechanismList(const slotid &slot);
void mechanismInfo(const slotid &slot, CK_MECHANISM_TYPE m,
CK_MECHANISM_INFO *info);
void startSession(const slotid &slot, bool rw = false);
/* Session based functions */
void loadAttribute(pk11_attribute &attribute,
CK_OBJECT_HANDLE object);
void storeAttribute(pk11_attribute &attribute,
CK_OBJECT_HANDLE object);
QList<CK_OBJECT_HANDLE> objectList(pk11_attlist &atts) const;
QString tokenLogin(const QString &name, bool so, bool force=false);
bool tokenLoginForModification();
void getRandom();
void logout();
bool needsLogin(bool so);
void login(unsigned char *pin, unsigned long pinlen, bool so);
void setPin(unsigned char *oldPin, unsigned long oldPinLen,
unsigned char *pin, unsigned long pinLen);
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,
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,
unsigned char *to, int tolen, unsigned long m);
int decrypt(int flen, const unsigned char *from,
unsigned char *to, int tolen, unsigned long m);
};
#endif