This library provides a simple and nice C++ wrapper around these libraries, so that programmers can concentrate on functionality. It offers general support for PCSC-lite, OpenSSL, PKCS#11, plus specific functionality for the SuisseID.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1263 lines
42 KiB

#ifndef CRYPTOKI_HXX
#define CRYPTOKI_HXX
/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#include <opencryptoki/apiclient.h>
#include <string>
#include <vector>
#include <set>
//! C++ Wrapper around Cryptoki API
namespace cryptoki {
#ifndef CRYPTOKI_FN_LOG
#if __GNUC__ >= 2
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
+std::string(__PRETTY_FUNCTION__))
#else
#define CRYPTOKI_FN_LOG(X) X " failed in \
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__)
#endif
#define UNDEF_CRYPTOKI_FN_LOG
#endif
//============================================================================
class exception: public std::exception {
public:
exception(const std::string& reason) throw():
_what("cryptoki: "+reason) {
}
~exception() throw() {}
const char* what() const throw() {
return _what.c_str();
}
private:
std::string _what;
};
//----------------------------------------------------------------------------
class not_implemented: public exception {
public:
not_implemented(const std::string& reason) throw():
exception("feature is not implemented:\n"+reason) {
}
};
//----------------------------------------------------------------------------
class access_error: public exception {
public:
access_error(const std::string& reason) throw():
exception("smardcard access error:\n"+reason) {
}
};
class Slot;
typedef std::vector<Slot> SlotList;
enum Mechanism {
RSA_PKCS_KEY_PAIR_GEN = CKM_RSA_PKCS_KEY_PAIR_GEN,
RSA_PKCS = CKM_RSA_PKCS,
RSA_9796 = CKM_RSA_9796,
RSA_X_509 = CKM_RSA_X_509,
MD2_RSA_PKCS = CKM_MD2_RSA_PKCS,
MD5_RSA_PKCS = CKM_MD5_RSA_PKCS,
SHA1_RSA_PKCS = CKM_SHA1_RSA_PKCS,
RIPEMD128_RSA_PKCS = CKM_RIPEMD128_RSA_PKCS,
RIPEMD160_RSA_PKCS = CKM_RIPEMD160_RSA_PKCS,
RSA_PKCS_OAEP = CKM_RSA_PKCS_OAEP,
RSA_X9_31_KEY_PAIR_GEN = CKM_RSA_X9_31_KEY_PAIR_GEN,
RSA_X9_31 = CKM_RSA_X9_31,
SHA1_RSA_X9_31 = CKM_SHA1_RSA_X9_31,
RSA_PKCS_PSS = CKM_RSA_PKCS_PSS,
SHA1_RSA_PKCS_PSS = CKM_SHA1_RSA_PKCS_PSS,
DSA_KEY_PAIR_GEN = CKM_DSA_KEY_PAIR_GEN,
DSA = CKM_DSA,
DSA_SHA1 = CKM_DSA_SHA1,
DH_PKCS_KEY_PAIR_GEN = CKM_DH_PKCS_KEY_PAIR_GEN,
DH_PKCS_DERIVE = CKM_DH_PKCS_DERIVE,
X9_42_DH_KEY_PAIR_GEN = CKM_X9_42_DH_KEY_PAIR_GEN,
X9_42_DH_DERIVE = CKM_X9_42_DH_DERIVE,
X9_42_DH_HYBRID_DERIVE = CKM_X9_42_DH_HYBRID_DERIVE,
X9_42_MQV_DERIVE = CKM_X9_42_MQV_DERIVE,
SHA256_RSA_PKCS = CKM_SHA256_RSA_PKCS,
RC2_KEY_GEN = CKM_RC2_KEY_GEN,
RC2_ECB = CKM_RC2_ECB,
RC2_CBC = CKM_RC2_CBC,
RC2_MAC = CKM_RC2_MAC,
RC2_MAC_GENERAL = CKM_RC2_MAC_GENERAL,
RC2_CBC_PAD = CKM_RC2_CBC_PAD,
RC4_KEY_GEN = CKM_RC4_KEY_GEN,
RC4 = CKM_RC4,
DES_KEY_GEN = CKM_DES_KEY_GEN,
DES_ECB = CKM_DES_ECB,
DES_CBC = CKM_DES_CBC,
DES_MAC = CKM_DES_MAC,
DES_MAC_GENERAL = CKM_DES_MAC_GENERAL,
DES_CBC_PAD = CKM_DES_CBC_PAD,
DES2_KEY_GEN = CKM_DES2_KEY_GEN,
DES3_KEY_GEN = CKM_DES3_KEY_GEN,
DES3_ECB = CKM_DES3_ECB,
DES3_CBC = CKM_DES3_CBC,
DES3_MAC = CKM_DES3_MAC,
DES3_MAC_GENERAL = CKM_DES3_MAC_GENERAL,
DES3_CBC_PAD = CKM_DES3_CBC_PAD,
CDMF_KEY_GEN = CKM_CDMF_KEY_GEN,
CDMF_ECB = CKM_CDMF_ECB,
CDMF_CBC = CKM_CDMF_CBC,
CDMF_MAC = CKM_CDMF_MAC,
CDMF_MAC_GENERAL = CKM_CDMF_MAC_GENERAL,
CDMF_CBC_PAD = CKM_CDMF_CBC_PAD,
MD2 = CKM_MD2,
MD2_HMAC = CKM_MD2_HMAC,
MD2_HMAC_GENERAL = CKM_MD2_HMAC_GENERAL,
MD5 = CKM_MD5,
MD5_HMAC = CKM_MD5_HMAC,
MD5_HMAC_GENERAL = CKM_MD5_HMAC_GENERAL,
SHA_1 = CKM_SHA_1,
SHA_1_HMAC = CKM_SHA_1_HMAC,
SHA_1_HMAC_GENERAL = CKM_SHA_1_HMAC_GENERAL,
RIPEMD128 = CKM_RIPEMD128,
RIPEMD128_HMAC = CKM_RIPEMD128_HMAC,
RIPEMD128_HMAC_GENERAL = CKM_RIPEMD128_HMAC_GENERAL,
RIPEMD160 = CKM_RIPEMD160,
RIPEMD160_HMAC = CKM_RIPEMD160_HMAC,
RIPEMD160_HMAC_GENERAL = CKM_RIPEMD160_HMAC_GENERAL,
SHA256 = CKM_SHA256,
SHA256_HMAC = CKM_SHA256_HMAC,
SHA256_HMAC_GENERAL = CKM_SHA256_HMAC_GENERAL,
SHA384 = CKM_SHA384,
SHA384_HMAC = CKM_SHA384_HMAC,
SHA384_HMAC_GENERAL = CKM_SHA384_HMAC_GENERAL,
SHA512 = CKM_SHA512,
SHA512_HMAC = CKM_SHA512_HMAC,
SHA512_HMAC_GENERAL = CKM_SHA512_HMAC_GENERAL,
CAST_KEY_GEN = CKM_CAST_KEY_GEN,
CAST_ECB = CKM_CAST_ECB,
CAST_CBC = CKM_CAST_CBC,
CAST_MAC = CKM_CAST_MAC,
CAST_MAC_GENERAL = CKM_CAST_MAC_GENERAL,
CAST_CBC_PAD = CKM_CAST_CBC_PAD,
CAST3_KEY_GEN = CKM_CAST3_KEY_GEN,
CAST3_ECB = CKM_CAST3_ECB,
CAST3_CBC = CKM_CAST3_CBC,
CAST3_MAC = CKM_CAST3_MAC,
CAST3_MAC_GENERAL = CKM_CAST3_MAC_GENERAL,
CAST3_CBC_PAD = CKM_CAST3_CBC_PAD,
CAST5_KEY_GEN = CKM_CAST5_KEY_GEN,
CAST128_KEY_GEN = CKM_CAST128_KEY_GEN,
CAST5_ECB = CKM_CAST5_ECB,
CAST128_ECB = CKM_CAST128_ECB,
CAST5_CBC = CKM_CAST5_CBC,
CAST128_CBC = CKM_CAST128_CBC,
CAST5_MAC = CKM_CAST5_MAC,
CAST128_MAC = CKM_CAST128_MAC,
CAST5_MAC_GENERAL = CKM_CAST5_MAC_GENERAL,
CAST128_MAC_GENERAL = CKM_CAST128_MAC_GENERAL,
CAST5_CBC_PAD = CKM_CAST5_CBC_PAD,
CAST128_CBC_PAD = CKM_CAST128_CBC_PAD,
RC5_KEY_GEN = CKM_RC5_KEY_GEN,
RC5_ECB = CKM_RC5_ECB,
RC5_CBC = CKM_RC5_CBC,
RC5_MAC = CKM_RC5_MAC,
RC5_MAC_GENERAL = CKM_RC5_MAC_GENERAL,
RC5_CBC_PAD = CKM_RC5_CBC_PAD,
IDEA_KEY_GEN = CKM_IDEA_KEY_GEN,
IDEA_ECB = CKM_IDEA_ECB,
IDEA_CBC = CKM_IDEA_CBC,
IDEA_MAC = CKM_IDEA_MAC,
IDEA_MAC_GENERAL = CKM_IDEA_MAC_GENERAL,
IDEA_CBC_PAD = CKM_IDEA_CBC_PAD,
GENERIC_SECRET_KEY_GEN = CKM_GENERIC_SECRET_KEY_GEN,
CONCATENATE_BASE_AND_KEY = CKM_CONCATENATE_BASE_AND_KEY,
CONCATENATE_BASE_AND_DATA = CKM_CONCATENATE_BASE_AND_DATA,
CONCATENATE_DATA_AND_BASE = CKM_CONCATENATE_DATA_AND_BASE,
XOR_BASE_AND_DATA = CKM_XOR_BASE_AND_DATA,
EXTRACT_KEY_FROM_KEY = CKM_EXTRACT_KEY_FROM_KEY,
SSL3_PRE_MASTER_KEY_GEN = CKM_SSL3_PRE_MASTER_KEY_GEN,
SSL3_MASTER_KEY_DERIVE = CKM_SSL3_MASTER_KEY_DERIVE,
SSL3_KEY_AND_MAC_DERIVE = CKM_SSL3_KEY_AND_MAC_DERIVE,
SSL3_MASTER_KEY_DERIVE_DH = CKM_SSL3_MASTER_KEY_DERIVE_DH,
TLS_PRE_MASTER_KEY_GEN = CKM_TLS_PRE_MASTER_KEY_GEN,
TLS_MASTER_KEY_DERIVE = CKM_TLS_MASTER_KEY_DERIVE,
TLS_KEY_AND_MAC_DERIVE = CKM_TLS_KEY_AND_MAC_DERIVE,
TLS_MASTER_KEY_DERIVE_DH = CKM_TLS_MASTER_KEY_DERIVE_DH,
SSL3_MD5_MAC = CKM_SSL3_MD5_MAC,
SSL3_SHA1_MAC = CKM_SSL3_SHA1_MAC,
MD5_KEY_DERIVATION = CKM_MD5_KEY_DERIVATION,
MD2_KEY_DERIVATION = CKM_MD2_KEY_DERIVATION,
SHA1_KEY_DERIVATION = CKM_SHA1_KEY_DERIVATION,
SHA256_KEY_DERIVATION = CKM_SHA256_KEY_DERIVATION,
PBE_MD2_DES_CBC = CKM_PBE_MD2_DES_CBC,
PBE_MD5_DES_CBC = CKM_PBE_MD5_DES_CBC,
PBE_MD5_CAST_CBC = CKM_PBE_MD5_CAST_CBC,
PBE_MD5_CAST3_CBC = CKM_PBE_MD5_CAST3_CBC,
PBE_MD5_CAST5_CBC = CKM_PBE_MD5_CAST5_CBC,
PBE_MD5_CAST128_CBC = CKM_PBE_MD5_CAST128_CBC,
PBE_SHA1_CAST5_CBC = CKM_PBE_SHA1_CAST5_CBC,
PBE_SHA1_CAST128_CBC = CKM_PBE_SHA1_CAST128_CBC,
PBE_SHA1_RC4_128 = CKM_PBE_SHA1_RC4_128,
PBE_SHA1_RC4_40 = CKM_PBE_SHA1_RC4_40,
PBE_SHA1_DES3_EDE_CBC = CKM_PBE_SHA1_DES3_EDE_CBC,
PBE_SHA1_DES2_EDE_CBC = CKM_PBE_SHA1_DES2_EDE_CBC,
PBE_SHA1_RC2_128_CBC = CKM_PBE_SHA1_RC2_128_CBC,
PBE_SHA1_RC2_40_CBC = CKM_PBE_SHA1_RC2_40_CBC,
PKCS5_PBKD2 = CKM_PKCS5_PBKD2,
PBA_SHA1_WITH_SHA1_HMAC = CKM_PBA_SHA1_WITH_SHA1_HMAC,
KEY_WRAP_LYNKS = CKM_KEY_WRAP_LYNKS,
KEY_WRAP_SET_OAEP = CKM_KEY_WRAP_SET_OAEP,
SKIPJACK_KEY_GEN = CKM_SKIPJACK_KEY_GEN,
SKIPJACK_ECB64 = CKM_SKIPJACK_ECB64,
SKIPJACK_CBC64 = CKM_SKIPJACK_CBC64,
SKIPJACK_OFB64 = CKM_SKIPJACK_OFB64,
SKIPJACK_CFB64 = CKM_SKIPJACK_CFB64,
SKIPJACK_CFB32 = CKM_SKIPJACK_CFB32,
SKIPJACK_CFB16 = CKM_SKIPJACK_CFB16,
SKIPJACK_CFB8 = CKM_SKIPJACK_CFB8,
SKIPJACK_WRAP = CKM_SKIPJACK_WRAP,
SKIPJACK_PRIVATE_WRAP = CKM_SKIPJACK_PRIVATE_WRAP,
SKIPJACK_RELAYX = CKM_SKIPJACK_RELAYX,
KEA_KEY_PAIR_GEN = CKM_KEA_KEY_PAIR_GEN,
KEA_KEY_DERIVE = CKM_KEA_KEY_DERIVE,
FORTEZZA_TIMESTAMP = CKM_FORTEZZA_TIMESTAMP,
BATON_KEY_GEN = CKM_BATON_KEY_GEN,
BATON_ECB128 = CKM_BATON_ECB128,
BATON_ECB96 = CKM_BATON_ECB96,
BATON_CBC128 = CKM_BATON_CBC128,
BATON_COUNTER = CKM_BATON_COUNTER,
BATON_SHUFFLE = CKM_BATON_SHUFFLE,
BATON_WRAP = CKM_BATON_WRAP,
ECDSA_KEY_PAIR_GEN = CKM_ECDSA_KEY_PAIR_GEN,
EC_KEY_PAIR_GEN = CKM_EC_KEY_PAIR_GEN,
ECDSA = CKM_ECDSA,
ECDSA_SHA1 = CKM_ECDSA_SHA1,
ECDH1_DERIVE = CKM_ECDH1_DERIVE,
ECDH1_COFACTOR_DERIVE = CKM_ECDH1_COFACTOR_DERIVE,
ECMQV_DERIVE = CKM_ECMQV_DERIVE,
JUNIPER_KEY_GEN = CKM_JUNIPER_KEY_GEN,
JUNIPER_ECB128 = CKM_JUNIPER_ECB128,
JUNIPER_CBC128 = CKM_JUNIPER_CBC128,
JUNIPER_COUNTER = CKM_JUNIPER_COUNTER,
JUNIPER_SHUFFLE = CKM_JUNIPER_SHUFFLE,
JUNIPER_WRAP = CKM_JUNIPER_WRAP,
FASTHASH = CKM_FASTHASH,
AES_KEY_GEN = CKM_AES_KEY_GEN,
AES_ECB = CKM_AES_ECB,
AES_CBC = CKM_AES_CBC,
AES_MAC = CKM_AES_MAC,
AES_MAC_GENERAL = CKM_AES_MAC_GENERAL,
AES_CBC_PAD = CKM_AES_CBC_PAD,
DSA_PARAMETER_GEN = CKM_DSA_PARAMETER_GEN,
DH_PKCS_PARAMETER_GEN = CKM_DH_PKCS_PARAMETER_GEN,
X9_42_DH_PARAMETER_GEN = CKM_X9_42_DH_PARAMETER_GEN,
VENDOR_DEFINED = CKM_VENDOR_DEFINED
};
typedef std::set<Mechanism> MechanismList;
template<std::string::size_type SIZE>
class FixString: public std::string {
public:
FixString() {}
FixString(const char* const cStr) {
*this = std::string(cStr, SIZE);
size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0);
}
FixString(const unsigned char* const cStr) {
*this = std::string((const char*)cStr, SIZE);
size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0);
}
FixString& operator=(const std::string& other) {
std::string::operator=(other);
return *this;
}
FixString& operator=(const char* const cStr) {
*this = std::string(cStr, SIZE);
size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0);
return *this;
}
FixString& operator=(const unsigned char* const cStr) {
*this = std::string((const char*)cStr, SIZE);
size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0);
return *this;
}
FixString fix() {
FixString cpy(*this);
cpy.resize(SIZE, ' ');
return cpy;
}
};
typedef CK_MECHANISM_INFO MechanismInfo;
struct SlotInfo {
FixString<64> slotDescription;
FixString<32> manufacturerID;
CK_FLAGS flags;
CK_VERSION hardwareVersion;
CK_VERSION firmwareVersion;
};
struct TokenInfo {
FixString<32> label;
FixString<32> manufacturerID;
FixString<16> model;
FixString<16> serialNumber;
CK_FLAGS flags;
CK_ULONG maxSessionCount;
CK_ULONG sessionCount;
CK_ULONG maxRwSessionCount;
CK_ULONG rwSessionCount;
CK_ULONG maxPinLen;
CK_ULONG minPinLen;
CK_ULONG totalPublicMemory;
CK_ULONG freePublicMemory;
CK_ULONG totalPrivateMemory;
CK_ULONG freePrivateMemory;
CK_VERSION hardwareVersion;
CK_VERSION firmwareVersion;
FixString<16> utcTime;
};
struct Info {
CK_VERSION cryptokiVersion;
FixString<32> manufacturerID;
CK_FLAGS flags;
FixString<32> libraryDescription;
CK_VERSION libraryVersion;
};
//! to be instanciated before first use
class Init {
private:
friend class Slot;
friend class Session;
friend class Object;
bool _exc;
CK_RV _res;
CK_FUNCTION_LIST* _fn;
Init(const Init&); // forbidden
Init& operator=(const Init&); // forbidden
//! Initialize Funcion List for this Instance
bool functionList(const std::string& library);
bool check(CK_RV result, const std::string& context="");
/*! @return error text of last cryptoki call */
std::string error(CK_RV res);
public:
//! Initialize for a given library (default cryptoki)
/*! Please notem, that you must not instanciate more than one
Init per unique function list!
@param fn function list to be used within this instance
@param exc wether exceptions should be thrown */
Init(const std::string& library="onepin-opensc-pkcs11.so", bool exc=true);
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
handling. If you disable it, you must check after every
operation whether it was successful or not. These methods
provide all you need for that. */
//@{
/*! @return @c true if last cryptoki on this object call was successful */
operator bool();
/*! @return error text of last cryptoki call */
std::string error();
//@}
Info info() {
Info inf;
CK_INFO cInf;
//! calls @c C_GetInfo
if (!check(_fn->C_GetInfo(&cInf), CRYPTOKI_FN_LOG("C_GetInfo")))
return inf;
inf.cryptokiVersion = cInf.cryptokiVersion;
inf.manufacturerID = cInf.manufacturerID;
inf.flags = cInf.flags;
inf.libraryDescription = cInf.libraryDescription;
inf.libraryVersion = cInf.libraryVersion;
return inf;
}
//! Get a list of available slots
/*! @param tokenPresent whether a token must be inserted into the reader
@return list of matching slots */
SlotList slotList(bool tokenPresent=true);
};
//! Slot and Token Management
class Slot {
private:
friend class Init;
friend class Session;
friend class Object;
Init* _init;
CK_SLOT_ID _slot;
CK_RV _res;
Slot(Init& init, CK_SLOT_ID slot):
_init(&init), _slot(slot), _res(CKR_OK) {
}
bool check(CK_RV result, const std::string& context="") {
_res = result;
if (_init->_exc && !*this)
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return _res==CKR_OK;
}
public:
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
handling. If you disable it, you must check after every
operation whether it was successful or not. These methods
provide all you need for that. */
//@{
/*! @return @c true if last cryptoki on this object call was successful */
operator bool() {
return _res==CKR_OK;
}
/*! @return error text of last cryptoki call */
std::string error() {
return _init->error(_res);
}
//@}
MechanismInfo mechanismInfo(Mechanism mechanism) {
MechanismInfo info;
//! calls @c C_GetMechanismInfo
check(_init->_fn->C_GetMechanismInfo(_slot, mechanism, &info),
CRYPTOKI_FN_LOG("C_GetMechanismInfo"));
return info;
}
MechanismList mechanismlist() {
MechanismList res;
CK_ULONG count(0);
//! calls @c C_GetMechanismList
if (!check(_init->_fn->C_GetMechanismList(_slot, 0, &count),
CRYPTOKI_FN_LOG("C_GetMechanismList")) || !count) return res;
CK_MECHANISM_TYPE* mechanisms = 0;
try {
mechanisms = new CK_MECHANISM_TYPE[count];
if (!check(_init->_fn->C_GetMechanismList(_slot, mechanisms, &count),
CRYPTOKI_FN_LOG("C_GetMechanismList"))) {
delete[] mechanisms;
return res;
}
for (CK_ULONG i(0); i<count; ++i) res.insert((Mechanism)mechanisms[i]);
} catch (...) {
delete[] mechanisms;
throw;
}
delete[] mechanisms;
return res;
}
SlotInfo slotInfo() {
SlotInfo info;
CK_SLOT_INFO cInfo;
//! calls @c C_GetSlotInfo
if (!check(_init->_fn->C_GetSlotInfo(_slot, &cInfo),
CRYPTOKI_FN_LOG("C_GetSlotInfo"))) return info;
info.slotDescription = cInfo.slotDescription;
info.manufacturerID = cInfo.manufacturerID;
info.flags = cInfo.flags;
info.hardwareVersion = cInfo.hardwareVersion;
info.firmwareVersion = cInfo.firmwareVersion;
return info;
}
TokenInfo tokenInfo() {
TokenInfo info;
//! calls @c C_GetTokenInfo
CK_TOKEN_INFO cInfo;
if (!check(_init->_fn->C_GetTokenInfo(_slot, &cInfo),
CRYPTOKI_FN_LOG("C_GetTokenInfo"))) return info;
info.label = cInfo.label;
info.manufacturerID = cInfo.manufacturerID;
info.model = cInfo.model;
info.serialNumber = cInfo.serialNumber;
info.flags = cInfo.flags;
info.maxSessionCount = cInfo.ulMaxSessionCount;
info.sessionCount = cInfo.ulSessionCount;
info.maxRwSessionCount = cInfo.ulMaxRwSessionCount;
info.rwSessionCount = cInfo.ulRwSessionCount;
info.maxPinLen = cInfo.ulMaxPinLen;
info.minPinLen = cInfo.ulMinPinLen;
info.totalPublicMemory = cInfo.ulTotalPublicMemory;
info.freePublicMemory = cInfo.ulFreePublicMemory;
info.totalPrivateMemory = cInfo.ulTotalPrivateMemory;
info.freePrivateMemory = cInfo.ulFreePrivateMemory;
info.hardwareVersion = cInfo.hardwareVersion;
info.firmwareVersion = cInfo.firmwareVersion;
info.utcTime = cInfo.utcTime;
return info;
}
std::string inittoken(std::string in) {
std::string res;
res.resize(in.size());
//! calls @c C_InitToken
check(_init->_fn->C_InitToken
(_slot,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->()),
CRYPTOKI_FN_LOG("C_InitToken"));
return res;
}
/*! @todo Not implemented:
@code
class SlotEventListener {
public: virtual void slotEvent() = 0;
}
bool registerforslotevent(SlotEventListener&) {
//! calls @c C_WaitForSlotEvent
return check(_init->_fn->C_WaitForSlotEvent(CK_FLAGS, &_slot, CK_VOID_PTR),
CRYPTOKI_FN_LOG("C_WaitForSlotEvent"));
}
@endcode */
};
//! Session Management
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
class Session {
private:
friend class Object;
Slot& _slot;
CK_SESSION_HANDLE _session;
CK_RV _res;
Session(); // forbidden
Session(const Session&); // forbidden
Session& operator=(const Session&); // forbidden
bool check(CK_RV result, const std::string& context="") {
_res = result;
if (_slot._init->_exc && !*this)
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return _res==CKR_OK;
}
public:
//! Opens a new session.
/*! @param slot slot to open a session on */
Session(Slot& slot): _slot(slot), _session(0), _res(CKR_OK) {
//! calls @c C_OpenSession
check(_slot._init->_fn->C_OpenSession(_slot._slot, 0, 0, 0, &_session),
CRYPTOKI_FN_LOG("C_OpenSession"));
//! @todo pass parameter
}
//! Closes actual session
~Session() {
try {
//! calls @c C_CloseSession
check(_slot._init->_fn->C_CloseSession(_session),
CRYPTOKI_FN_LOG("C_CloseSession"));
} catch (...) {
if (!std::uncaught_exception()) throw;
}
}
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
handling. If you disable it, you must check after every
operation whether it was successful or not. These methods
provide all you need for that. */
//@{
/*! @return @c true if last cryptoki on this object call was successful */
operator bool() {
return _res==CKR_OK;
}
/*! @return error text of last cryptoki call */
std::string error() {
return _slot._init->error(_res);
}
//@}
/*! @name Low Level Cryptoki Functions
Direct access to the low level cryptoki API. Better use the
comfort methods. */
//@{
bool cancel() {
//! calls @c C_CancelFunction
return check(_slot._init->_fn->C_CancelFunction(_session),
CRYPTOKI_FN_LOG("C_CancelFunction"));
}
std::string decrypt(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_Decrypt
check(_slot._init->_fn->C_Decrypt
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_Decrypt"));
res.resize(size);
return res;
}
std::string decryptdigestupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptDigestUpdate
check(_slot._init->_fn->C_DecryptDigestUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate"));
res.resize(size);
return res;
}
std::string decryptfinal(std::string in) {
std::string res;
// res.resize(in.size());
// CK_ULONG size(res.size()); //! @todo check if size is ok
// //! calls @c C_DecryptFinal
// check(_slot._init->_fn->C_DecryptFinal
// (_session,
// (unsigned char*)in.begin().operator->(), in.size(),
// (unsigned char*)res.begin().operator->(), &size),
// CRYPTOKI_FN_LOG("C_DecryptFinal"));
// res.resize(size);
//! @todo check docu
return res;
}
std::string decryptupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptUpdate
check(_slot._init->_fn->C_DecryptUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_DecryptUpdate"));
res.resize(size);
return res;
}
std::string decryptverifyupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptVerifyUpdate
check(_slot._init->_fn->C_DecryptVerifyUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_DecryptVerifyUpdate"));
res.resize(size);
return res;
}
std::string digest(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_Digest
check(_slot._init->_fn->C_Digest
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_Digest"));
res.resize(size);
return res;
}
std::string digestencryptupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DigestEncryptUpdate
check(_slot._init->_fn->C_DigestEncryptUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_DigestEncryptUpdate"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool digestfinal() {
//! calls @c C_DigestFinal
return check(_slot._init->_fn->C_DigestFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_DigestFinal"));
}
@endcode */
/*! @todo Not implemented:
@code
bool digestinit() {
//! calls @c C_DigestInit
return check(_slot._init->_fn->C_DigestInit(_session, CK_MECHANISM_PTR),
CRYPTOKI_FN_LOG("C_DigestInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool digestupdate() {
//! calls @c C_DigestUpdate
return check(_slot._init->_fn->C_DigestUpdate(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_DigestUpdate"));
}
@endcode */
std::string encrypt(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_Encrypt
check(_slot._init->_fn->C_Encrypt
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_Encrypt"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool encryptfinal() {
//! calls @c C_EncryptFinal
return check(_slot._init->_fn->C_EncryptFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_EncryptFinal"));
}
@endcode */
std::string encryptupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_EncryptUpdate
check(_slot._init->_fn->C_EncryptUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_EncryptUpdate"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool finalize() {
//! calls @c C_Finalize
return check(_slot._init->_fn->C_Finalize(CK_VOID_PTR),
CRYPTOKI_FN_LOG("C_Finalize"));
}
@endcode */
/*! @todo Not implemented:
@code
bool findobjectsfinal() {
//! calls @c C_FindObjectsFinal
return check(_slot._init->_fn->C_FindObjectsFinal(_session),
CRYPTOKI_FN_LOG("C_FindObjectsFinal"));
}
@endcode */
/*! @todo Not implemented:
@code
bool findobjectsinit() {
//! calls @c C_FindObjectsInit
return check(_slot._init->_fn->C_FindObjectsInit(_session, CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_FindObjectsInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool generaterandom() {
//! calls @c C_GenerateRandom
return check(_slot._init->_fn->C_GenerateRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_GenerateRandom"));
}
@endcode */
/*! @todo Not implemented:
@code
bool getfunctionstatus() {
//! calls @c C_GetFunctionStatus
return check(_slot._init->_fn->C_GetFunctionStatus(_session),
CRYPTOKI_FN_LOG("C_GetFunctionStatus"));
}
@endcode */
/*! @todo Not implemented:
@code
bool getoperationstate() {
//! calls @c C_GetOperationState
return check(_slot._init->_fn->C_GetOperationState(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_GetOperationState"));
}
@endcode */
/*! @todo Not implemented:
@code
bool getsessioninfo() {
//! calls @c C_GetSessionInfo
return check(_slot._init->_fn->C_GetSessionInfo(_session, CK_SESSION_INFO_PTR),
CRYPTOKI_FN_LOG("C_GetSessionInfo"));
}
@endcode */
/*! @todo Not implemented:
@code
bool initpin() {
//! calls @c C_InitPIN
return check(_slot._init->_fn->C_InitPIN(_session, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_InitPIN"));
}
@endcode */
/*! @todo Not implemented:
@code
bool login() {
//! calls @c C_Login
return check(_slot._init->_fn->C_Login(_session, CK_USER_TYPE, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_Login"));
}
@endcode */
/*! @todo Not implemented:
@code
bool logout() {
//! calls @c C_Logout
return check(_slot._init->_fn->C_Logout(_session),
CRYPTOKI_FN_LOG("C_Logout"));
}
@endcode */
/*! @todo Not implemented:
@code
bool seedrandom() {
//! calls @c C_SeedRandom
return check(_slot._init->_fn->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SeedRandom"));
}
@endcode */
/*! @todo Not implemented:
@code
bool setpin() {
//! calls @c C_SetPIN
return check(_slot._init->_fn->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetPIN"));
}
@endcode */
std::string sign(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_Sign
check(_slot._init->_fn->C_Sign
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_Sign"));
res.resize(size);
return res;
}
std::string signencryptupdate(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_SignEncryptUpdate
check(_slot._init->_fn->C_SignEncryptUpdate
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_SignEncryptUpdate"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool signfinal() {
//! calls @c C_SignFinal
return check(_slot._init->_fn->C_SignFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_SignFinal"));
}
@endcode */
std::string signrecover(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_SignRecover
check(_slot._init->_fn->C_SignRecover
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_SignRecover"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool signupdate() {
//! calls @c C_SignUpdate
return check(_slot._init->_fn->C_SignUpdate(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SignUpdate"));
}
@endcode */
/*! @todo Not implemented:
@code
bool verify() {
//! calls @c C_Verify
return check(_slot._init->_fn->C_Verify(_session, CK_BYTE_PTR, CK_ULONG,
CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_Verify"));
}
@endcode */
/*! @todo Not implemented:
@code
bool verifyfinal() {
//! calls @c C_VerifyFinal
return check(_slot._init->_fn->C_VerifyFinal(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_VerifyFinal"));
}
@endcode */
std::string verifyrecover(std::string in) {
std::string res;
res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_VerifyRecover
check(_slot._init->_fn->C_VerifyRecover
(_session,
(unsigned char*)in.begin().operator->(), in.size(),
(unsigned char*)res.begin().operator->(), &size),
CRYPTOKI_FN_LOG("C_VerifyRecover"));
res.resize(size);
return res;
}
/*! @todo Not implemented:
@code
bool verifyupdate() {
//! calls @c C_VerifyUpdate
return check(_slot._init->_fn->C_VerifyUpdate(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_VerifyUpdate"));
}
@endcode */
//@}
};
class Object {
private:
friend class Session;
Session& _session;
CK_RV _res;
bool check(CK_RV result, const std::string& context="") {
_res = result;
if (_session._slot._init->_exc && !*this)
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return _res==CKR_OK;
}
Object(); //! forbidden
Object(Session& session): _session(session), _res(CKR_OK) {}
public:
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
handling. If you disable it, you must check after every
operation whether it was successful or not. These methods
provide all you need for that. */
//@{
/*! @return @c true if last cryptoki on this object call was successful */
operator bool() {
return _res==CKR_OK;
}
/*! @return error text of last cryptoki call */
std::string error() {
return _session._slot._init->error(_res);
}
//@}
/*! @todo Not implemented:
@code
bool copyobject() {
//! calls @c C_CopyObject
return check(_session._slot._init->_fn->C_CopyObject(_session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_CopyObject"));
}
@endcode */
/*! @todo Not implemented:
@code
bool createobject() {
//! calls @c C_CreateObject
return check(_session._slot._init->_fn->C_CreateObject(_session, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_CreateObject"));
}
@endcode */
/*! @todo Not implemented:
@code
bool decryptinit() {
//! calls @c C_DecryptInit
return check(_session._slot._init->_fn->C_DecryptInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_DecryptInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool derivekey() {
//! calls @c C_DeriveKey
return check(_session._slot._init->_fn->C_DeriveKey(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_DeriveKey"));
}
@endcode */
/*! @todo Not implemented:
@code
bool destroyobject() {
//! calls @c C_DestroyObject
return check(_session._slot._init->_fn->C_DestroyObject(_session, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_DestroyObject"));
}
@endcode */
/*! @todo Not implemented:
@code
bool digestkey() {
//! calls @c C_DigestKey
return check(_session._slot._init->_fn->C_DigestKey(_session, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_DigestKey"));
}
@endcode */
/*! @todo Not implemented:
@code
bool encryptinit() {
//! calls @c C_EncryptInit
return check(_session._slot._init->_fn->C_EncryptInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_EncryptInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool findobjects() {
//! calls @c C_FindObjects
return check(_session._slot._init->_fn->C_FindObjects(_session, CK_OBJECT_HANDLE_PTR, CK_ULONG,
CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_FindObjects"));
}
@endcode */
/*! @todo Not implemented:
@code
bool generatekey() {
//! calls @c C_GenerateKey
return check(_session._slot._init->_fn->C_GenerateKey(_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKey"));
}
@endcode */
/*! @todo Not implemented:
@code
bool generatekeypair() {
//! calls @c C_GenerateKeyPair
return check(_session._slot._init->_fn->C_GenerateKeyPair(_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKeyPair"));
}
@endcode */
/*! @todo Not implemented:
@code
bool getattributevalue() {
//! calls @c C_GetAttributeValue
return check(_session._slot._init->_fn->C_GetAttributeValue(_session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_GetAttributeValue"));
}
@endcode */
/*! @todo Not implemented:
@code
bool getobjectsize() {
//! calls @c C_GetObjectSize
return check(_session._slot._init->_fn->C_GetObjectSize(_session, CK_OBJECT_HANDLE, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_GetObjectSize"));
}
@endcode */
/*! @todo Not implemented:
@code
bool setattributevalue() {
//! calls @c C_SetAttributeValue
return check(_session._slot._init->_fn->C_SetAttributeValue(_session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetAttributeValue"));
}
@endcode */
/*! @todo Not implemented:
@code
bool setoperationstate() {
//! calls @c C_SetOperationState
return check(_session._slot._init->_fn->C_SetOperationState(_session, CK_BYTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SetOperationState"));
}
@endcode */
/*! @todo Not implemented:
@code
bool signinit() {
//! calls @c C_SignInit
return check(_session._slot._init->_fn->C_SignInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SignInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool signrecoverinit() {
//! calls @c C_SignRecoverInit
return check(_session._slot._init->_fn->C_SignRecoverInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SignRecoverInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool unwrapkey() {
//! calls @c C_UnwrapKey
return check(_session._slot._init->_fn->C_UnwrapKey(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_UnwrapKey"));
}
@endcode */
/*! @todo Not implemented:
@code
bool verifyinit() {
//! calls @c C_VerifyInit
return check(_session._slot._init->_fn->C_VerifyInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_VerifyInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool verifyrecoverinit() {
//! calls @c C_VerifyRecoverInit
return check(_session._slot._init->_fn->C_VerifyRecoverInit(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_VerifyRecoverInit"));
}
@endcode */
/*! @todo Not implemented:
@code
bool wrapkey() {
//! calls @c C_WrapKey
return check(_session._slot._init->_fn->C_WrapKey(_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_WrapKey"));
}
@endcode */
};
#endif
#ifdef UNDEF_CRYPTOKI_FN_LOG // cleanup if it was set in here
#undef CRYPTOKI_FN_LOG
#undef CRYPTOKI_QUOTE
#endif
}