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.
2089 lines
76 KiB
2089 lines
76 KiB
#ifndef CRYPTOKI_HXX |
|
#define CRYPTOKI_HXX |
|
/*! @file |
|
|
|
@id $Id$ |
|
*/ |
|
// 1 2 3 4 5 6 7 8 |
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890 |
|
|
|
// interface |
|
#include <openssl.hxx> |
|
#ifndef WIN32 |
|
#include <opensc/pkcs11.h> |
|
#else |
|
#include <cryptoki.h> |
|
#endif |
|
#include <string> |
|
#include <vector> |
|
#include <map> |
|
#include <set> |
|
|
|
// for inline implementations only |
|
#include <sstream> |
|
#include <cstdlib> // malloc/free |
|
#include <cstring> // memset |
|
#include <cassert> // assert |
|
#include <iomanip> |
|
#include <memory> |
|
#include <cryptaux.hxx> |
|
|
|
/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API */ |
|
//@{ |
|
/*! @defgroup cryptokilib Cryptoki C++ Library */ |
|
/*! @defgroup globaloperator Global Operator */ |
|
/*! @defgroup cryptokitypes Cryptoki C++ Types and Auxiliary */ |
|
/*! @defgroup cryptokiexceptions Cryptoki Exceptions */ |
|
|
|
#ifndef CRYPTOKI_LOG |
|
#define CRYPTOKI_LOG(X) |
|
#endif |
|
|
|
#ifndef CRYPTOKI_FN_LOG |
|
#include <iostream> |
|
#if __GNUC__ >= 2 |
|
//! Cryptoki Error Message Formatting |
|
/*! If you want to change cryptoki error formatting, just |
|
redefine your own CRYPTOKY_FN_LOG macro before <code>#include |
|
<cryptoki.hxx></code>. |
|
#return std::String */ |
|
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \ |
|
+std::string(__PRETTY_FUNCTION__)) |
|
#else |
|
#define CRYPTOKI_QUOTE(X) #X |
|
//! Cryptoki Error Message Formatting |
|
/*! If you want to change cryptoki error formatting, just |
|
redefine your own CRYPTOKY_FN_LOG macro before <code>#include |
|
<cryptoki.hxx></code>. |
|
#return std::String */ |
|
#define CRYPTOKI_FN_LOG(X) X " failed in \ |
|
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__) |
|
#endif |
|
#endif |
|
#ifndef CRYPTOKI_LOG |
|
#include <iostream> |
|
#if __GNUC__ >= 2 |
|
//! Cryptoki Logging |
|
/*! If you want to change cryptoki logging mechanism, just |
|
redefine your own CRYPTOKI_LOG macro before <code>#include |
|
<cryptoki.hxx></code>. Define it empty for no logging at |
|
all. By default logs to <code>std::clog</code>. */ |
|
#define CRYPTOKI_LOG(X) std::clog<<X<<" @ "<<__PRETTY_FUNCTION__<<std::endl |
|
#else |
|
//! Cryptoki Logging |
|
/*! If you want to change cryptoki logging mechanism, just |
|
redefine your own CRYPTOKI_LOG macro before <code>#include |
|
<cryptoki.hxx></code>. Define it empty for no logging at |
|
all. By default logs to <code>std::clog</code>. */ |
|
#define CRYPTOKI_LOG(X) std::clog<<X<<" @ "<<__FILE__<<__LINE__<<std::endl |
|
#endif |
|
#endif |
|
|
|
//! @see gcryptoki |
|
namespace cryptoki { |
|
|
|
//! @todo copy in own library |
|
/*! Inherit from SmartResource, |
|
and overwrite free(). You must call destruct() in your destructor. */ |
|
class SmartResource { |
|
public: |
|
SmartResource(): _cnt(0), _destructed(false) { |
|
incr(); |
|
} |
|
//! must be called in copy constructor of children! |
|
SmartResource(const SmartResource& o): _cnt(o._cnt), _destructed(false) { |
|
incr(); |
|
} |
|
~SmartResource() { |
|
assert(_destructed); // child must call destruct() in destructor |
|
} |
|
//! must be called in assignment constructor of children! |
|
SmartResource& operator=(const SmartResource& o) { |
|
decr(); |
|
_cnt = o._cnt; |
|
incr(); |
|
return *this; |
|
} |
|
protected: |
|
//! Overwrite to free your resource. |
|
virtual void free() = 0; |
|
//! You must call it in your destructor! |
|
void destruct() { |
|
if (_destructed) return; // only once |
|
decr(); |
|
_destructed = true; |
|
} |
|
//! Seldom needed, mostly automatic. |
|
void incr() { |
|
if (!_cnt) _cnt = new unsigned int(0); |
|
++*_cnt; |
|
assert(_cnt); |
|
} |
|
//! Seldom needed, mostly automatic. |
|
void decr() { |
|
if (!_cnt || --*_cnt) return; |
|
delete _cnt; _cnt = 0; |
|
free(); |
|
} |
|
//! Seldom needed, mostly automatic. |
|
/*! Used in complete reassign of resource from outside. |
|
Call incr() after assignment. */ |
|
void clear() { |
|
decr(); |
|
_cnt = 0; |
|
} |
|
//! Reads the internal counter (for testing and debugging only); |
|
int cnt() { |
|
assert(_cnt); |
|
return *_cnt; |
|
} |
|
private: |
|
unsigned int *_cnt; |
|
bool _destructed; |
|
}; |
|
|
|
template <typename T> class SharedPointer: public SmartResource { |
|
public: |
|
SharedPointer(): _p(0) {} |
|
SharedPointer(const SharedPointer& o): SmartResource(o), _p(o._p) {} |
|
SharedPointer(T* p): _p(p) {} |
|
SharedPointer& operator=(const SharedPointer& o) { |
|
return reset(o); |
|
} |
|
SharedPointer& operator=(T* p) { |
|
return reset(p); |
|
} |
|
~SharedPointer() { |
|
destruct(); |
|
} |
|
T* const operator->() { |
|
return get(); |
|
} |
|
const T* const operator->() const { |
|
return get(); |
|
} |
|
const T& operator*() const { |
|
return *get(); |
|
} |
|
T& operator*() { |
|
return *get(); |
|
} |
|
SharedPointer& reset(const SharedPointer& o) { |
|
SmartResource::operator=(o); |
|
_p = o._p; |
|
return *this; |
|
} |
|
SharedPointer& reset(T* p = 0) { |
|
clear(); |
|
_p = p; |
|
incr(); |
|
return *this; |
|
} |
|
const T* const get() const { |
|
assert(_p); |
|
return _p; |
|
} |
|
T* const get() { |
|
assert(_p); |
|
return _p; |
|
} |
|
protected: |
|
void free() { |
|
delete _p; _p=0; |
|
} |
|
private: |
|
T* _p; |
|
}; |
|
|
|
//! @addtogroup cryptokitypes |
|
//@{ |
|
|
|
inline std::string string(CK_ULONG num) { |
|
switch (num) { |
|
case CK_UNAVAILABLE_INFORMATION: return "-"; |
|
case CK_EFFECTIVELY_INFINITE: return "∞"; |
|
default: { |
|
std::stringstream ss; |
|
ss<<num; |
|
return ss.str(); |
|
} |
|
} |
|
} |
|
|
|
template <int NUM, typename TYPE> std::vector<TYPE> toVector(TYPE in[NUM]) { |
|
return std::vector<TYPE>(in, in+NUM); |
|
} |
|
#define CRYPTOKI_TO_VECTOR(ARRAY) \ |
|
toVector<sizeof(ARRAY)/sizeof(ARRAY[0])>(ARRAY) |
|
|
|
//@} |
|
|
|
//============================================================================ |
|
/*! @addtogroup cryptokiexceptions */ |
|
//@{ |
|
|
|
//---------------------------------------------------------------------------- |
|
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) { |
|
} |
|
}; |
|
//@} |
|
|
|
/*! @addtogroup cryptokitypes */ |
|
//@{ |
|
|
|
class Slot; |
|
typedef std::vector<Slot> SlotList; |
|
|
|
class Object; |
|
typedef std::vector<Object> ObjectList; |
|
|
|
typedef std::set<CK_MECHANISM_TYPE> MechanismList; |
|
|
|
typedef std::vector<CK_ATTRIBUTE_TYPE> AttributeTypeList; |
|
|
|
class Attribute { |
|
public: |
|
Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {} |
|
Attribute(CK_ATTRIBUTE_TYPE t, const std::string& v): type(t), value(v) {} |
|
Attribute(CK_ATTRIBUTE& attr): |
|
type(attr.type), value((char*)attr.pValue, attr.ulValueLen) { |
|
free(attr.pValue); |
|
attr.pValue = 0; |
|
} |
|
Attribute& operator=(const std::string& v) { |
|
value = v; |
|
return *this; |
|
} |
|
bool operator==(const Attribute& o) const { |
|
return type==o.type && value==o.value; |
|
} |
|
bool operator!=(const Attribute& o) const { |
|
return type!=o.type || value!=o.value; |
|
} |
|
//! Convert to a @c CK_ATTRIBUTE. |
|
/*! @note @c pValue points to the internal buffer of this |
|
element and must therefore not be changed. Also this object |
|
must not be destructed before the returned @c |
|
CK_ATTRIBUTE. */ |
|
operator CK_ATTRIBUTE() const { |
|
CK_ATTRIBUTE a; |
|
a.type = type; |
|
a.pValue = const_cast<char*>(&value[0]); |
|
a.ulValueLen = value.size(); |
|
return a; |
|
} |
|
std::string name() const { |
|
switch (type) { |
|
case CKA_CLASS: return "CLASS"; |
|
case CKA_TOKEN: return "TOKEN"; |
|
case CKA_PRIVATE: return "PRIVATE"; |
|
case CKA_LABEL: return "LABEL"; |
|
case CKA_APPLICATION: return "APPLICATION"; |
|
case CKA_VALUE: return "VALUE"; |
|
case CKA_OBJECT_ID: return "OBJECT_ID"; |
|
case CKA_CERTIFICATE_TYPE: return "CERTIFICATE_TYPE"; |
|
case CKA_ISSUER: return "ISSUER"; |
|
case CKA_SERIAL_NUMBER: return "SERIAL_NUMBER"; |
|
case CKA_AC_ISSUER: return "AC_ISSUER"; |
|
case CKA_OWNER: return "OWNER"; |
|
case CKA_ATTR_TYPES: return "ATTR_TYPES"; |
|
case CKA_TRUSTED: return "TRUSTED"; |
|
case CKA_KEY_TYPE: return "KEY_TYPE"; |
|
case CKA_SUBJECT: return "SUBJECT"; |
|
case CKA_ID: return "ID"; |
|
case CKA_SENSITIVE: return "SENSITIVE"; |
|
case CKA_ENCRYPT: return "ENCRYPT"; |
|
case CKA_DECRYPT: return "DECRYPT"; |
|
case CKA_WRAP: return "WRAP"; |
|
case CKA_UNWRAP: return "UNWRAP"; |
|
case CKA_SIGN: return "SIGN"; |
|
case CKA_SIGN_RECOVER: return "SIGN_RECOVER"; |
|
case CKA_VERIFY: return "VERIFY"; |
|
case CKA_VERIFY_RECOVER: return "VERIFY_RECOVER"; |
|
case CKA_DERIVE: return "DERIVE"; |
|
case CKA_START_DATE: return "START_DATE"; |
|
case CKA_END_DATE: return "END_DATE"; |
|
case CKA_MODULUS: return "MODULUS"; |
|
case CKA_MODULUS_BITS: return "MODULUS_BITS"; |
|
case CKA_PUBLIC_EXPONENT: return "PUBLIC_EXPONENT"; |
|
case CKA_PRIVATE_EXPONENT: return "PRIVATE_EXPONENT"; |
|
case CKA_PRIME_1: return "PRIME_1"; |
|
case CKA_PRIME_2: return "PRIME_2"; |
|
case CKA_EXPONENT_1: return "EXPONENT_1"; |
|
case CKA_EXPONENT_2: return "EXPONENT_2"; |
|
case CKA_COEFFICIENT: return "COEFFICIENT"; |
|
case CKA_PRIME: return "PRIME"; |
|
case CKA_SUBPRIME: return "SUBPRIME"; |
|
case CKA_BASE: return "BASE"; |
|
case CKA_PRIME_BITS: return "PRIME_BITS"; |
|
//case CKA_SUBPRIME_BITS: return "SUBPRIME_BITS"; |
|
case CKA_VALUE_BITS: return "VALUE_BITS"; |
|
case CKA_VALUE_LEN: return "VALUE_LEN"; |
|
case CKA_EXTRACTABLE: return "EXTRACTABLE"; |
|
case CKA_LOCAL: return "LOCAL"; |
|
case CKA_NEVER_EXTRACTABLE: return "NEVER_EXTRACTABLE"; |
|
case CKA_ALWAYS_SENSITIVE: return "ALWAYS_SENSITIVE"; |
|
case CKA_KEY_GEN_MECHANISM: return "KEY_GEN_MECHANISM"; |
|
case CKA_MODIFIABLE: return "MODIFIABLE"; |
|
//case CKA_ECDSA_PARAMS: return "ECDSA_PARAMS"; |
|
case CKA_EC_PARAMS: return "ECDSA_PARAMS or EC_PARAMS"; |
|
case CKA_EC_POINT: return "EC_POINT"; |
|
case CKA_SECONDARY_AUTH: return "SECONDARY_AUTH"; |
|
case CKA_AUTH_PIN_FLAGS: return "AUTH_PIN_FLAGS"; |
|
case CKA_HW_FEATURE_TYPE: return "HW_FEATURE_TYPE"; |
|
case CKA_RESET_ON_INIT: return "RESET_ON_INIT"; |
|
case CKA_HAS_RESET: return "HAS_RESET"; |
|
case CKA_VENDOR_DEFINED: return "VENDOR_DEFINED"; |
|
//case CKA_IBM_OPAQUE: return "IBM_OPAQUE"; |
|
default: return "unknown"; |
|
} |
|
} |
|
std::string readableValue() const { |
|
switch (type) { |
|
case CKA_CLASS: |
|
switch (*((CK_OBJECT_CLASS*)&value[0])) { |
|
case CKO_DATA: return "DATA"; |
|
case CKO_CERTIFICATE: return "CERTIFICATE"; |
|
case CKO_PUBLIC_KEY: return "PUBLIC_KEY"; |
|
case CKO_PRIVATE_KEY: return "PRIVATE_KEY"; |
|
case CKO_SECRET_KEY: return "SECRET_KEY"; |
|
case CKO_HW_FEATURE: return "HW_FEATURE"; |
|
case CKO_DOMAIN_PARAMETERS: return "DOMAIN_PARAMETERS"; |
|
case CKO_VENDOR_DEFINED: return "VENDOR_DEFINED"; |
|
default: "unknown"; |
|
} |
|
default: return crypto::readable(value); |
|
} |
|
} |
|
template<typename TYPE> Attribute& from(const TYPE& v) { |
|
value = std::string((char*)&v, sizeof(TYPE)); |
|
return *this; |
|
} |
|
template<typename TYPE> TYPE to() const { |
|
assert(sizeof(TYPE)==value.size()); |
|
return *reinterpret_cast<const TYPE*>(&value[0]); |
|
} |
|
CK_ATTRIBUTE_TYPE type; |
|
std::string value; |
|
}; |
|
typedef std::map<CK_ATTRIBUTE_TYPE, Attribute> AttributeMap; |
|
typedef std::vector<Attribute> AttributeList; |
|
|
|
// class Class { |
|
// public: |
|
// CK_OBJECT_CLASS class; |
|
// }; |
|
|
|
//class |
|
|
|
// //! Map Attribute Class to type |
|
// /*! @todo to be completed ... */ |
|
// #define CRYPTOKI_DECLARE_ATTR(ATTR_ID, TYPE) \ |
|
// template<> class AttributeType<ATTR_ID> { \ |
|
// public: typedef TYPE Type; \ |
|
// } |
|
// template<CK_ATTRIBUTE_TYPE Attribute> class AttributeType {}; |
|
// CRYPTOKI_DECLARE_ATTR(CKA_CLASS, CK_OBJECT_CLASS); |
|
// CRYPTOKI_DECLARE_ATTR(CKA_HW_FEATURE_TYPE, CK_HW_FEATURE); |
|
// CRYPTOKI_DECLARE_ATTR(CKA_VALUE, FixString<16>); |
|
// CRYPTOKI_DECLARE_ATTR(CKA_RESET_ON_INIT, CK_BBOOL); |
|
// CRYPTOKI_DECLARE_ATTR(CKA_HAS_RESET, CK_BBOOL); |
|
// // CRYPTOKI_DECLARE_ATTR(CKA_VALUE, ); - byte array |
|
// // CRYPTOKI_DECLARE_ATTR(, ); |
|
// // CRYPTOKI_DECLARE_ATTR(, ); |
|
// // CRYPTOKI_DECLARE_ATTR(, ); |
|
// // CRYPTOKI_DECLARE_ATTR(, ); |
|
// template<> class AttributeType<CKA_KEY_TYPE> { |
|
// public: typedef CK_KEY_TYPE Type; |
|
// public: typedef Type Param; |
|
// }; |
|
// template<> class AttributeType<CKA_APPLICATION> { |
|
// public: typedef CK_CHAR Type; |
|
// public: typedef std::string Param; |
|
// }; |
|
// template<> class AttributeType<CKA_VALUE> { |
|
// public: typedef CKA_BYTE Type; |
|
// public: typedef std::string Param; |
|
// }; |
|
// #undef CRYPTOKI_DECLARE_ATTR |
|
|
|
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; |
|
} |
|
operator unsigned char*() { |
|
return (unsigned char*)begin().operator->(); |
|
} |
|
FixString fix() { |
|
FixString cpy(*this); |
|
cpy.resize(SIZE, ' '); |
|
return cpy; |
|
} |
|
}; |
|
|
|
struct MechanismInfo { |
|
CK_MECHANISM_TYPE id; |
|
std::string name; |
|
CK_ULONG minKeySize; |
|
CK_ULONG maxKeySize; |
|
CK_FLAGS flags; |
|
MechanismInfo(CK_MECHANISM_TYPE type): id(type) { |
|
switch (id) { |
|
case CKM_RSA_PKCS_KEY_PAIR_GEN: name="RSA_PKCS_KEY_PAIR_GEN"; break; |
|
case CKM_RSA_PKCS: name="RSA_PKCS"; break; |
|
case CKM_RSA_9796: name="RSA_9796"; break; |
|
case CKM_RSA_X_509: name="RSA_X_509"; break; |
|
case CKM_MD2_RSA_PKCS: name="MD2_RSA_PKCS"; break; |
|
case CKM_MD5_RSA_PKCS: name="MD5_RSA_PKCS"; break; |
|
case CKM_SHA1_RSA_PKCS: name="SHA1_RSA_PKCS"; break; |
|
case CKM_RIPEMD128_RSA_PKCS: name="RIPEMD128_RSA_PKCS"; break; |
|
case CKM_RIPEMD160_RSA_PKCS: name="RIPEMD160_RSA_PKCS"; break; |
|
case CKM_RSA_PKCS_OAEP: name="RSA_PKCS_OAEP"; break; |
|
case CKM_RSA_X9_31_KEY_PAIR_GEN: name="RSA_X9_31_KEY_PAIR_GEN"; break; |
|
case CKM_RSA_X9_31: name="RSA_X9_31"; break; |
|
case CKM_SHA1_RSA_X9_31: name="SHA1_RSA_X9_31"; break; |
|
case CKM_RSA_PKCS_PSS: name="RSA_PKCS_PSS"; break; |
|
case CKM_SHA1_RSA_PKCS_PSS: name="SHA1_RSA_PKCS_PSS"; break; |
|
case CKM_DSA_KEY_PAIR_GEN: name="DSA_KEY_PAIR_GEN"; break; |
|
case CKM_DSA: name="DSA"; break; |
|
case CKM_DSA_SHA1: name="DSA_SHA1"; break; |
|
case CKM_DH_PKCS_KEY_PAIR_GEN: name="DH_PKCS_KEY_PAIR_GEN"; break; |
|
case CKM_DH_PKCS_DERIVE: name="DH_PKCS_DERIVE"; break; |
|
case CKM_X9_42_DH_KEY_PAIR_GEN: name="X9_42_DH_KEY_PAIR_GEN"; break; |
|
case CKM_X9_42_DH_DERIVE: name="X9_42_DH_DERIVE"; break; |
|
case CKM_X9_42_DH_HYBRID_DERIVE: name="X9_42_DH_HYBRID_DERIVE"; break; |
|
case CKM_X9_42_MQV_DERIVE: name="X9_42_MQV_DERIVE"; break; |
|
//case CKM_SHA256_RSA_PKCS: name="SHA256_RSA_PKCS"; break; |
|
case CKM_RC2_KEY_GEN: name="RC2_KEY_GEN"; break; |
|
case CKM_RC2_ECB: name="RC2_ECB"; break; |
|
case CKM_RC2_CBC: name="RC2_CBC"; break; |
|
case CKM_RC2_MAC: name="RC2_MAC"; break; |
|
case CKM_RC2_MAC_GENERAL: name="RC2_MAC_GENERAL"; break; |
|
case CKM_RC2_CBC_PAD: name="RC2_CBC_PAD"; break; |
|
case CKM_RC4_KEY_GEN: name="RC4_KEY_GEN"; break; |
|
case CKM_RC4: name="RC4"; break; |
|
case CKM_DES_KEY_GEN: name="DES_KEY_GEN"; break; |
|
case CKM_DES_ECB: name="DES_ECB"; break; |
|
case CKM_DES_CBC: name="DES_CBC"; break; |
|
case CKM_DES_MAC: name="DES_MAC"; break; |
|
case CKM_DES_MAC_GENERAL: name="DES_MAC_GENERAL"; break; |
|
case CKM_DES_CBC_PAD: name="DES_CBC_PAD"; break; |
|
case CKM_DES2_KEY_GEN: name="DES2_KEY_GEN"; break; |
|
case CKM_DES3_KEY_GEN: name="DES3_KEY_GEN"; break; |
|
case CKM_DES3_ECB: name="DES3_ECB"; break; |
|
case CKM_DES3_CBC: name="DES3_CBC"; break; |
|
case CKM_DES3_MAC: name="DES3_MAC"; break; |
|
case CKM_DES3_MAC_GENERAL: name="DES3_MAC_GENERAL"; break; |
|
case CKM_DES3_CBC_PAD: name="DES3_CBC_PAD"; break; |
|
case CKM_CDMF_KEY_GEN: name="CDMF_KEY_GEN"; break; |
|
case CKM_CDMF_ECB: name="CDMF_ECB"; break; |
|
case CKM_CDMF_CBC: name="CDMF_CBC"; break; |
|
case CKM_CDMF_MAC: name="CDMF_MAC"; break; |
|
case CKM_CDMF_MAC_GENERAL: name="CDMF_MAC_GENERAL"; break; |
|
case CKM_CDMF_CBC_PAD: name="CDMF_CBC_PAD"; break; |
|
case CKM_MD2: name="MD2"; break; |
|
case CKM_MD2_HMAC: name="MD2_HMAC"; break; |
|
case CKM_MD2_HMAC_GENERAL: name="MD2_HMAC_GENERAL"; break; |
|
case CKM_MD5: name="MD5"; break; |
|
case CKM_MD5_HMAC: name="MD5_HMAC"; break; |
|
case CKM_MD5_HMAC_GENERAL: name="MD5_HMAC_GENERAL"; break; |
|
case CKM_SHA_1: name="SHA_1"; break; |
|
case CKM_SHA_1_HMAC: name="SHA_1_HMAC"; break; |
|
case CKM_SHA_1_HMAC_GENERAL: name="SHA_1_HMAC_GENERAL"; break; |
|
case CKM_RIPEMD128: name="RIPEMD128"; break; |
|
case CKM_RIPEMD128_HMAC: name="RIPEMD128_HMAC"; break; |
|
case CKM_RIPEMD128_HMAC_GENERAL: name="RIPEMD128_HMAC_GENERAL"; break; |
|
case CKM_RIPEMD160: name="RIPEMD160"; break; |
|
case CKM_RIPEMD160_HMAC: name="RIPEMD160_HMAC"; break; |
|
case CKM_RIPEMD160_HMAC_GENERAL: name="RIPEMD160_HMAC_GENERAL"; break; |
|
//case CKM_SHA256: name="SHA256"; break; |
|
//case CKM_SHA256_HMAC: name="SHA256_HMAC"; break; |
|
//case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break; |
|
//case CKM_SHA384: name="SHA384"; break; |
|
//case CKM_SHA384_HMAC: name="SHA384_HMAC"; break; |
|
//case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break; |
|
//case CKM_SHA512: name="SHA512"; break; |
|
//case CKM_SHA512_HMAC: name="SHA512_HMAC"; break; |
|
//case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break; |
|
case CKM_CAST_KEY_GEN: name="CAST_KEY_GEN"; break; |
|
case CKM_CAST_ECB: name="CAST_ECB"; break; |
|
case CKM_CAST_CBC: name="CAST_CBC"; break; |
|
case CKM_CAST_MAC: name="CAST_MAC"; break; |
|
case CKM_CAST_MAC_GENERAL: name="CAST_MAC_GENERAL"; break; |
|
case CKM_CAST_CBC_PAD: name="CAST_CBC_PAD"; break; |
|
case CKM_CAST3_KEY_GEN: name="CAST3_KEY_GEN"; break; |
|
case CKM_CAST3_ECB: name="CAST3_ECB"; break; |
|
case CKM_CAST3_CBC: name="CAST3_CBC"; break; |
|
case CKM_CAST3_MAC: name="CAST3_MAC"; break; |
|
case CKM_CAST3_MAC_GENERAL: name="CAST3_MAC_GENERAL"; break; |
|
case CKM_CAST3_CBC_PAD: name="CAST3_CBC_PAD"; break; |
|
//case CKM_CAST5_KEY_GEN: name="CAST5_KEY_GEN"; break; |
|
case CKM_CAST128_KEY_GEN: name="CAST5_KEY_GEN or CAST128_KEY_GEN"; break; |
|
//case CKM_CAST5_ECB: name="CAST5_ECB"; break; |
|
case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break; |
|
//case CKM_CAST5_CBC: name="CAST5_CBC"; break; |
|
case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break; |
|
//case CKM_CAST5_MAC: name="CAST5_MAC"; break; |
|
case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break; |
|
//case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break; |
|
case CKM_CAST128_MAC_GENERAL: |
|
name="CAST5_MAC_GENERAL or CAST128_MAC_GENERAL"; break; |
|
//case CKM_CAST5_CBC_PAD: name="CAST5_CBC_PAD"; break; |
|
case CKM_CAST128_CBC_PAD: name="CAST5_CBC_PAD or CAST128_CBC_PAD"; break; |
|
case CKM_RC5_KEY_GEN: name="RC5_KEY_GEN"; break; |
|
case CKM_RC5_ECB: name="RC5_ECB"; break; |
|
case CKM_RC5_CBC: name="RC5_CBC"; break; |
|
case CKM_RC5_MAC: name="RC5_MAC"; break; |
|
case CKM_RC5_MAC_GENERAL: name="RC5_MAC_GENERAL"; break; |
|
case CKM_RC5_CBC_PAD: name="RC5_CBC_PAD"; break; |
|
case CKM_IDEA_KEY_GEN: name="IDEA_KEY_GEN"; break; |
|
case CKM_IDEA_ECB: name="IDEA_ECB"; break; |
|
case CKM_IDEA_CBC: name="IDEA_CBC"; break; |
|
case CKM_IDEA_MAC: name="IDEA_MAC"; break; |
|
case CKM_IDEA_MAC_GENERAL: name="IDEA_MAC_GENERAL"; break; |
|
case CKM_IDEA_CBC_PAD: name="IDEA_CBC_PAD"; break; |
|
case CKM_GENERIC_SECRET_KEY_GEN: name="GENERIC_SECRET_KEY_GEN"; break; |
|
case CKM_CONCATENATE_BASE_AND_KEY: |
|
name="CONCATENATE_BASE_AND_KEY"; break; |
|
case CKM_CONCATENATE_BASE_AND_DATA: |
|
name="CONCATENATE_BASE_AND_DATA"; break; |
|
case CKM_CONCATENATE_DATA_AND_BASE: |
|
name="CONCATENATE_DATA_AND_BASE"; break; |
|
case CKM_XOR_BASE_AND_DATA: name="XOR_BASE_AND_DATA"; break; |
|
case CKM_EXTRACT_KEY_FROM_KEY: name="EXTRACT_KEY_FROM_KEY"; break; |
|
case CKM_SSL3_PRE_MASTER_KEY_GEN: name="SSL3_PRE_MASTER_KEY_GEN"; break; |
|
case CKM_SSL3_MASTER_KEY_DERIVE: name="SSL3_MASTER_KEY_DERIVE"; break; |
|
case CKM_SSL3_KEY_AND_MAC_DERIVE: name="SSL3_KEY_AND_MAC_DERIVE"; break; |
|
case CKM_SSL3_MASTER_KEY_DERIVE_DH: |
|
name="SSL3_MASTER_KEY_DERIVE_DH"; break; |
|
case CKM_TLS_PRE_MASTER_KEY_GEN: name="TLS_PRE_MASTER_KEY_GEN"; break; |
|
case CKM_TLS_MASTER_KEY_DERIVE: name="TLS_MASTER_KEY_DERIVE"; break; |
|
case CKM_TLS_KEY_AND_MAC_DERIVE: name="TLS_KEY_AND_MAC_DERIVE"; break; |
|
case CKM_TLS_MASTER_KEY_DERIVE_DH: name="TLS_MASTER_KEY_DERIVE_DH"; break; |
|
case CKM_SSL3_MD5_MAC: name="SSL3_MD5_MAC"; break; |
|
case CKM_SSL3_SHA1_MAC: name="SSL3_SHA1_MAC"; break; |
|
case CKM_MD5_KEY_DERIVATION: name="MD5_KEY_DERIVATION"; break; |
|
case CKM_MD2_KEY_DERIVATION: name="MD2_KEY_DERIVATION"; break; |
|
case CKM_SHA1_KEY_DERIVATION: name="SHA1_KEY_DERIVATION"; break; |
|
//case CKM_SHA256_KEY_DERIVATION: name="SHA256_KEY_DERIVATION"; break; |
|
case CKM_PBE_MD2_DES_CBC: name="PBE_MD2_DES_CBC"; break; |
|
case CKM_PBE_MD5_DES_CBC: name="PBE_MD5_DES_CBC"; break; |
|
case CKM_PBE_MD5_CAST_CBC: name="PBE_MD5_CAST_CBC"; break; |
|
case CKM_PBE_MD5_CAST3_CBC: name="PBE_MD5_CAST3_CBC"; break; |
|
//case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break; |
|
case CKM_PBE_MD5_CAST128_CBC: |
|
name="PBE_MD5_CAST5_CBC or PBE_MD5_CAST128_CBC"; break; |
|
//case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break; |
|
case CKM_PBE_SHA1_CAST128_CBC: |
|
name="PBE_SHA1_CAST5_CBC or PBE_SHA1_CAST128_CBC"; break; |
|
case CKM_PBE_SHA1_RC4_128: name="PBE_SHA1_RC4_128"; break; |
|
case CKM_PBE_SHA1_RC4_40: name="PBE_SHA1_RC4_40"; break; |
|
case CKM_PBE_SHA1_DES3_EDE_CBC: name="PBE_SHA1_DES3_EDE_CBC"; break; |
|
case CKM_PBE_SHA1_DES2_EDE_CBC: name="PBE_SHA1_DES2_EDE_CBC"; break; |
|
case CKM_PBE_SHA1_RC2_128_CBC: name="PBE_SHA1_RC2_128_CBC"; break; |
|
case CKM_PBE_SHA1_RC2_40_CBC: name="PBE_SHA1_RC2_40_CBC"; break; |
|
case CKM_PKCS5_PBKD2: name="PKCS5_PBKD2"; break; |
|
case CKM_PBA_SHA1_WITH_SHA1_HMAC: name="PBA_SHA1_WITH_SHA1_HMAC"; break; |
|
case CKM_KEY_WRAP_LYNKS: name="KEY_WRAP_LYNKS"; break; |
|
case CKM_KEY_WRAP_SET_OAEP: name="KEY_WRAP_SET_OAEP"; break; |
|
case CKM_SKIPJACK_KEY_GEN: name="SKIPJACK_KEY_GEN"; break; |
|
case CKM_SKIPJACK_ECB64: name="SKIPJACK_ECB64"; break; |
|
case CKM_SKIPJACK_CBC64: name="SKIPJACK_CBC64"; break; |
|
case CKM_SKIPJACK_OFB64: name="SKIPJACK_OFB64"; break; |
|
case CKM_SKIPJACK_CFB64: name="SKIPJACK_CFB64"; break; |
|
case CKM_SKIPJACK_CFB32: name="SKIPJACK_CFB32"; break; |
|
case CKM_SKIPJACK_CFB16: name="SKIPJACK_CFB16"; break; |
|
case CKM_SKIPJACK_CFB8: name="SKIPJACK_CFB8"; break; |
|
case CKM_SKIPJACK_WRAP: name="SKIPJACK_WRAP"; break; |
|
case CKM_SKIPJACK_PRIVATE_WRAP: name="SKIPJACK_PRIVATE_WRAP"; break; |
|
case CKM_SKIPJACK_RELAYX: name="SKIPJACK_RELAYX"; break; |
|
case CKM_KEA_KEY_PAIR_GEN: name="KEA_KEY_PAIR_GEN"; break; |
|
case CKM_KEA_KEY_DERIVE: name="KEA_KEY_DERIVE"; break; |
|
case CKM_FORTEZZA_TIMESTAMP: name="FORTEZZA_TIMESTAMP"; break; |
|
case CKM_BATON_KEY_GEN: name="BATON_KEY_GEN"; break; |
|
case CKM_BATON_ECB128: name="BATON_ECB128"; break; |
|
case CKM_BATON_ECB96: name="BATON_ECB96"; break; |
|
case CKM_BATON_CBC128: name="BATON_CBC128"; break; |
|
case CKM_BATON_COUNTER: name="BATON_COUNTER"; break; |
|
case CKM_BATON_SHUFFLE: name="BATON_SHUFFLE"; break; |
|
case CKM_BATON_WRAP: name="BATON_WRAP"; break; |
|
//case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break; |
|
case CKM_EC_KEY_PAIR_GEN: |
|
name="ECDSA_KEY_PAIR_GEN or EC_KEY_PAIR_GEN"; break; |
|
case CKM_ECDSA: name="ECDSA"; break; |
|
case CKM_ECDSA_SHA1: name="ECDSA_SHA1"; break; |
|
case CKM_ECDH1_DERIVE: name="ECDH1_DERIVE"; break; |
|
case CKM_ECDH1_COFACTOR_DERIVE: name="ECDH1_COFACTOR_DERIVE"; break; |
|
case CKM_ECMQV_DERIVE: name="ECMQV_DERIVE"; break; |
|
case CKM_JUNIPER_KEY_GEN: name="JUNIPER_KEY_GEN"; break; |
|
case CKM_JUNIPER_ECB128: name="JUNIPER_ECB128"; break; |
|
case CKM_JUNIPER_CBC128: name="JUNIPER_CBC128"; break; |
|
case CKM_JUNIPER_COUNTER: name="JUNIPER_COUNTER"; break; |
|
case CKM_JUNIPER_SHUFFLE: name="JUNIPER_SHUFFLE"; break; |
|
case CKM_JUNIPER_WRAP: name="JUNIPER_WRAP"; break; |
|
case CKM_FASTHASH: name="FASTHASH"; break; |
|
case CKM_AES_KEY_GEN: name="AES_KEY_GEN"; break; |
|
case CKM_AES_ECB: name="AES_ECB"; break; |
|
case CKM_AES_CBC: name="AES_CBC"; break; |
|
case CKM_AES_MAC: name="AES_MAC"; break; |
|
case CKM_AES_MAC_GENERAL: name="AES_MAC_GENERAL"; break; |
|
case CKM_AES_CBC_PAD: name="AES_CBC_PAD"; break; |
|
case CKM_DSA_PARAMETER_GEN: name="DSA_PARAMETER_GEN"; break; |
|
case CKM_DH_PKCS_PARAMETER_GEN: name="DH_PKCS_PARAMETER_GEN"; break; |
|
case CKM_X9_42_DH_PARAMETER_GEN: name="X9_42_DH_PARAMETER_GEN"; break; |
|
case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break; |
|
default: { |
|
std::stringstream ss; |
|
ss<<"unknown mechanism: "<<id; |
|
throw exception(ss.str()); |
|
} |
|
} |
|
} |
|
}; |
|
|
|
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; |
|
}; |
|
|
|
//@} |
|
|
|
/*! @addtogroup cryptokilib */ |
|
//@{ |
|
|
|
//! 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 library name of the shared library that supports pkcs#11 |
|
@param exc wether exceptions should be thrown */ |
|
Init(const std::string& library="onepin-opensc-pkcs11.so", bool exc=true); |
|
|
|
~Init() { |
|
CRYPTOKI_LOG("log"); |
|
try { |
|
//! calls @c C_Finalize |
|
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize")); |
|
} catch (...) { |
|
if (!std::uncaught_exception()) throw; |
|
} |
|
} |
|
|
|
Init& reset() { |
|
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize")); |
|
check(_fn->C_Initialize(0), CRYPTOKI_FN_LOG("C_Initialize")); |
|
return *this; |
|
} |
|
|
|
/*! @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() { |
|
CRYPTOKI_LOG("log"); |
|
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) { |
|
CRYPTOKI_LOG("log"); |
|
} |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
CRYPTOKI_LOG("log"); |
|
_res = result; |
|
if (_init->_exc && !*this) |
|
if (!context.empty()) |
|
throw access_error(context+": "+error()); |
|
else |
|
throw access_error(error()); |
|
return _res==CKR_OK; |
|
} |
|
|
|
public: |
|
|
|
//! Don't use without assignment! For standard containers only! |
|
Slot(): _init(0) { |
|
CRYPTOKI_LOG("log"); |
|
} |
|
|
|
Slot& operator=(const Slot& o) { |
|
CRYPTOKI_LOG("log"); |
|
_init = o._init; |
|
_slot = o._slot; |
|
_res = o._res; |
|
return *this; |
|
} |
|
|
|
/*! @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() { |
|
CRYPTOKI_LOG("log"); |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
CRYPTOKI_LOG("log"); |
|
return _init->error(_res); |
|
} |
|
|
|
//@} |
|
|
|
MechanismInfo mechanisminfo(CK_MECHANISM_TYPE mechanism) { |
|
CRYPTOKI_LOG("log"); |
|
MechanismInfo info(mechanism); |
|
CK_MECHANISM_INFO cInfo; |
|
//! calls @c C_GetMechanismInfo |
|
check(_init->_fn->C_GetMechanismInfo(_slot, mechanism, &cInfo), |
|
CRYPTOKI_FN_LOG("C_GetMechanismInfo")); |
|
info.minKeySize = cInfo.ulMinKeySize; |
|
info.maxKeySize = cInfo.ulMaxKeySize; |
|
info.flags = cInfo.flags; |
|
return info; |
|
} |
|
|
|
MechanismList mechanismlist() { |
|
CRYPTOKI_LOG("log"); |
|
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(mechanisms[i]); |
|
} catch (...) { |
|
delete[] mechanisms; |
|
throw; |
|
} |
|
delete[] mechanisms; |
|
return res; |
|
} |
|
|
|
SlotInfo slotinfo() { |
|
CRYPTOKI_LOG("log"); |
|
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() { |
|
CRYPTOKI_LOG("log"); |
|
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; |
|
} |
|
|
|
/*! @bug does not compile: |
|
@code |
|
bool inittoken(std::string pin, FixString<32> label) { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_InitToken |
|
return check(_init->_fn->C_InitToken |
|
(_slot, |
|
(unsigned char*)&pin[0], pin.size(), |
|
(unsigned char*)label.&fix()[0]) |
|
CRYPTOKI_FN_LOG("C_InitToken")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
class SlotEventListener { |
|
public: virtual void slotEvent() = 0; |
|
} |
|
|
|
bool registerforslotevent(SlotEventListener&) { |
|
CRYPTOKI_LOG("log"); |
|
//! 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: public SmartResource { |
|
private: |
|
|
|
friend class Login; |
|
friend class Object; |
|
|
|
CK_FUNCTION_LIST* fn() { |
|
return _slot._init->_fn; |
|
} |
|
|
|
Slot& _slot; |
|
CK_SESSION_HANDLE _session; |
|
CK_RV _res; |
|
|
|
Session(); // forbidden |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
CRYPTOKI_LOG("log"); |
|
_res = result; |
|
if (_slot._init->_exc && !*this) |
|
if (!context.empty()) |
|
throw access_error(context+": "+error()); |
|
else |
|
throw access_error(error()); |
|
return _res==CKR_OK; |
|
} |
|
|
|
void free() { |
|
CRYPTOKI_LOG("log"); |
|
try { |
|
//! closes login. |
|
_login.reset(); |
|
//! calls @c C_CloseSession |
|
check(_slot._init->_fn->C_CloseSession(_session), |
|
CRYPTOKI_FN_LOG("C_CloseSession")); |
|
} catch (...) { |
|
if (!std::uncaught_exception()) throw; |
|
} |
|
} |
|
|
|
public: |
|
|
|
//! Opens a new session. |
|
/*! @param slot slot to open a session on */ |
|
Session(Slot& slot, bool rw=false): |
|
_slot(slot), _session(0), _res(CKR_OK) { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_OpenSession |
|
check(_slot._init->_fn->C_OpenSession |
|
(_slot._slot, CKF_SERIAL_SESSION|(rw?CKF_RW_SESSION:0), |
|
0, 0, &_session), |
|
CRYPTOKI_FN_LOG("C_OpenSession")); |
|
//! @todo pass parameter |
|
} |
|
|
|
Session(const Session& o): |
|
SmartResource(o), |
|
_slot(o._slot), _session(o._session), _res(o._res) { |
|
CRYPTOKI_LOG("log"); |
|
} |
|
|
|
~Session() { |
|
CRYPTOKI_LOG("log"); |
|
destruct(); |
|
} |
|
|
|
Session& operator=(const Session& o) { |
|
CRYPTOKI_LOG("log"); |
|
SmartResource::operator=(o); |
|
_slot = o._slot; |
|
_session = o._session; |
|
_res = o._res; |
|
} |
|
|
|
/*! @name Comfortable Access |
|
|
|
Use these methods in favour of the Low Level Cryptoki |
|
Functions. They provide a higher level simpler access. */ |
|
//@{ |
|
|
|
//! Get a list of matching objects. |
|
ObjectList find(const AttributeList& attrs=AttributeList()); |
|
|
|
//! Get a list of matching objects. |
|
ObjectList find(const Attribute& a); |
|
//! Get a list of matching objects. |
|
ObjectList find(const Attribute& a1, const Attribute& a2); |
|
|
|
//! Create a new Certificate Object. |
|
Object create(const std::string& label, const openssl::X509& cert); |
|
//! Create a new PrivateKey Object. |
|
Object create(const std::string& label, const openssl::PrivateKey& key, |
|
const openssl::X509& cert); |
|
|
|
//@} |
|
|
|
/*! @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() { |
|
CRYPTOKI_LOG("log"); |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
CRYPTOKI_LOG("log"); |
|
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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_CancelFunction |
|
return check(_slot._init->_fn->C_CancelFunction(_session), |
|
CRYPTOKI_FN_LOG("C_CancelFunction")); |
|
} |
|
|
|
//! Create a new object. |
|
Object create(const AttributeList& attrs); |
|
|
|
std::string digest(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Digest")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string digestencryptupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_DigestEncryptUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool digestfinal() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_DigestUpdate |
|
return check(_slot._init->_fn->C_DigestUpdate(_session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_DigestUpdate")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool findobjectsfinal() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_FindObjectsFinal |
|
return check(_slot._init->_fn->C_FindObjectsFinal(_session), |
|
CRYPTOKI_FN_LOG("C_FindObjectsFinal")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool findobjectsinit() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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 findobjects() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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 generaterandom() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_GetFunctionStatus |
|
return check(_slot._init->_fn->C_GetFunctionStatus(_session), |
|
CRYPTOKI_FN_LOG("C_GetFunctionStatus")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool getoperationstate() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_InitPIN |
|
return check(_slot._init->_fn->C_InitPIN(_session, CK_CHAR_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_InitPIN")); |
|
} |
|
@endcode */ |
|
|
|
class Login { |
|
|
|
public: |
|
|
|
Login(Session& session, |
|
const std::string& pin, |
|
CK_USER_TYPE userType=CKU_USER): _session(session) { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_Login |
|
_session.check(_session.fn()->C_Login |
|
(_session._session, userType, |
|
(CK_CHAR*)pin.c_str(), |
|
pin.size()), |
|
CRYPTOKI_FN_LOG("C_Login")); |
|
} |
|
|
|
~Login() { |
|
try { |
|
//! calls @c C_Logout |
|
_session.check(_session.fn()->C_Logout |
|
(_session._session), |
|
CRYPTOKI_FN_LOG("C_Logout")); |
|
} catch (...) { |
|
if (!std::uncaught_exception()) throw; |
|
} |
|
} |
|
|
|
private: |
|
|
|
Session& _session; |
|
|
|
}; |
|
|
|
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) { |
|
CRYPTOKI_LOG("log"); |
|
_login = SharedPointer<Login>(new Login(*this, pin, userType)); |
|
} |
|
void logout() { |
|
CRYPTOKI_LOG("log"); |
|
_login.reset(); |
|
} |
|
SharedPointer<Login> _login; |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool seedrandom() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Sign")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string signencryptupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_SignEncryptUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool signfinal() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_SignRecover")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool signupdate() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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) { |
|
CRYPTOKI_LOG("log"); |
|
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[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_VerifyRecover")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool verifyupdate() { |
|
CRYPTOKI_LOG("log"); |
|
//! 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; |
|
|
|
CK_OBJECT_HANDLE _object; |
|
Session _session; |
|
CK_RV _res; |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
CRYPTOKI_LOG("log"); |
|
_res = result; |
|
if (_session._slot._init->_exc && !*this) |
|
if (!context.empty()) |
|
throw access_error(context+": "+error()); |
|
else |
|
throw access_error(error()); |
|
return _res==CKR_OK; |
|
} |
|
|
|
Object() { |
|
CRYPTOKI_LOG("log"); |
|
} |
|
|
|
Object(const Session& session, CK_OBJECT_HANDLE obj): |
|
_session(session), _object(obj), _res(CKR_OK) { |
|
CRYPTOKI_LOG("log"); |
|
} |
|
|
|
public: |
|
|
|
Object& operator=(Object& o) { |
|
CRYPTOKI_LOG("log"); |
|
_object = o._object; |
|
_session = o._session; |
|
_res = o._res; |
|
return *this; |
|
} |
|
|
|
/*! @name Comfortable Access |
|
|
|
Use these methods in favour of the Low Level Cryptoki |
|
Functions. They provide a higher level simpler access. */ |
|
//@{ |
|
|
|
std::string encrypt(const std::string& data, CK_MECHANISM_TYPE type, |
|
const std::string& param=std::string()) { |
|
CRYPTOKI_LOG("log"); |
|
CRYPTOKI_LOG("encryptinit"); |
|
encryptinit(type, param); |
|
CRYPTOKI_LOG("encrypt"); |
|
return encrypt(data); |
|
//! @todo don't call encryptfinal()? |
|
} |
|
|
|
std::string decrypt(const std::string& data, CK_MECHANISM_TYPE type, |
|
const std::string& param=std::string()) { |
|
CRYPTOKI_LOG("log"); |
|
CRYPTOKI_LOG("decryptinit"); |
|
decryptinit(type, param); |
|
CRYPTOKI_LOG("decrypt"); |
|
return decrypt(data); |
|
//! @todo don't call decryptfinal()? |
|
} |
|
|
|
//@} |
|
|
|
/*! @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() { |
|
CRYPTOKI_LOG("log"); |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
CRYPTOKI_LOG("log"); |
|
return _session._slot._init->error(_res); |
|
} |
|
|
|
//@} |
|
|
|
/*! @name Low Level Cryptoki Functions |
|
|
|
Direct access to the low level cryptoki API. Better use the |
|
comfort methods. */ |
|
//@{ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool copyobject() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_CopyObject |
|
return check(_session._slot._init->_fn->C_CopyObject(_session._session, CK_OBJECT_HANDLE, |
|
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), |
|
CRYPTOKI_FN_LOG("C_CopyObject")); |
|
} |
|
@endcode */ |
|
|
|
bool decryptinit(CK_MECHANISM_TYPE type, std::string param) { |
|
CRYPTOKI_LOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?¶m[0]:0, param.size() |
|
}; |
|
CRYPTOKI_LOG("decryptinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_DecryptInit |
|
return check(_session._slot._init->_fn->C_DecryptInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_DecryptInit")); |
|
} |
|
|
|
//! requires decryptinit to be called before |
|
std::string decrypt(const std::string& in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
CK_ULONG size(0); // two calls, first to get minimum buffer length |
|
CRYPTOKI_LOG("get size"); |
|
//! calls @c C_Decrypt |
|
check(_session._slot._init->_fn->C_Decrypt |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), 0, &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOKI_LOG("maximum size is "<<size<<"Bytes"); |
|
res.resize(size, 0); |
|
check(_session._slot._init->_fn->C_Decrypt |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOKI_LOG("exact size is "<<size<<"Bytes"); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string decryptdigestupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_DecryptDigestUpdate |
|
check(_session._slot._init->_fn->C_DecryptDigestUpdate |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
bool decryptfinal() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_DecryptFinal |
|
return check(_session._slot._init->_fn->C_DecryptFinal |
|
(_session._session, 0, 0), |
|
CRYPTOKI_FN_LOG("C_DecryptFinal")); |
|
//! @todo does this work? |
|
} |
|
|
|
std::string decryptupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_DecryptUpdate |
|
check(_session._slot._init->_fn->C_DecryptUpdate |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_DecryptUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string decryptverifyupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_DecryptVerifyUpdate |
|
check(_session._slot._init->_fn->C_DecryptVerifyUpdate |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_DecryptVerifyUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool derivekey() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_DeriveKey |
|
return check(_session._slot._init->_fn->C_DeriveKey(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, |
|
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), |
|
CRYPTOKI_FN_LOG("C_DeriveKey")); |
|
} |
|
@endcode */ |
|
|
|
bool destroy() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_DestroyObject |
|
return check(_session._slot._init->_fn->C_DestroyObject |
|
(_session._session, _object), |
|
CRYPTOKI_FN_LOG("C_DestroyObject")); |
|
} |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool digestkey() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_DigestKey |
|
return check(_session._slot._init->_fn->C_DigestKey(_session._session, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_DigestKey")); |
|
} |
|
@endcode */ |
|
|
|
bool encryptinit(CK_MECHANISM_TYPE type, const std::string& param) { |
|
CRYPTOKI_LOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?(void*)¶m[0]:0, param.size() |
|
}; |
|
CRYPTOKI_LOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_EncryptInit |
|
return check(_session._slot._init->_fn->C_EncryptInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_EncryptInit")); |
|
} |
|
|
|
std::string encrypt(const std::string& in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
CK_ULONG size(0); // two calls, first to get minimum buffer length |
|
CRYPTOKI_LOG("get size"); |
|
//! calls @c C_Encrypt |
|
check(_session._slot._init->_fn->C_Encrypt |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), 0, &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOKI_LOG("maximum size is "<<size<<"Bytes"); |
|
res.resize(size, 0); |
|
check(_session._slot._init->_fn->C_Encrypt |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Encrypt")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool encryptfinal() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_EncryptFinal |
|
return check(_session._slot._init->_fn->C_EncryptFinal(_session._session, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_EncryptFinal")); |
|
} |
|
@endcode */ |
|
|
|
std::string encryptupdate(std::string in) { |
|
CRYPTOKI_LOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_EncryptUpdate |
|
check(_session._slot._init->_fn->C_EncryptUpdate |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_EncryptUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool generatekey() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_GenerateKey |
|
return check(_session._slot._init->_fn->C_GenerateKey(_session._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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_GenerateKeyPair |
|
return check(_session._slot._init->_fn->C_GenerateKeyPair(_session._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 */ |
|
|
|
|
|
//! Get a Single Attribute |
|
Attribute operator[](CK_ATTRIBUTE_TYPE a) { |
|
CRYPTOKI_LOG("log"); |
|
return attribute(a); |
|
} |
|
|
|
//! Get a Single Attribute |
|
Attribute attribute(CK_ATTRIBUTE_TYPE a) { |
|
CRYPTOKI_LOG("log"); |
|
Attribute res; |
|
CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0}); |
|
//! calls @c C_GetAttributeValue |
|
if (!check(_session._slot._init->_fn->C_GetAttributeValue |
|
(_session._session, _object, &attr, 1), |
|
CRYPTOKI_FN_LOG("C_GetAttributeValue")) |
|
|| !(long)attr.ulValueLen>0l) |
|
//! Without exception handling, size and type must be checked too. |
|
return res; |
|
try { |
|
attr.pValue = malloc(attr.ulValueLen); |
|
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); |
|
if (check(_session._slot._init->_fn->C_GetAttributeValue |
|
(_session._session, _object, &attr, 1), |
|
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) |
|
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open |
|
Cryptoki. From the Specs: «In the special case |
|
of an attribute whose value is an array of |
|
attributes, for example CKA_WRAP_TEMPLATE, where |
|
it is passed in with pValue not NULL, then if |
|
the pValue of elements within the array is |
|
NULL_PTR then the ulValueLen of elements within |
|
the array will be set to the required length. If |
|
the pValue of elements within the array is not |
|
NULL_PTR, then the ulValueLen element of |
|
attributes within the array must reflect the |
|
space that the corresponding pValue points to, |
|
and pValue is filled in if there is sufficient |
|
room. Therefore it is important to initialize |
|
the contents of a buffer before calling |
|
C_GetAttributeValue to get such an array |
|
value. If any ulValueLen within the array isn't |
|
large enough, it will be set to -1 and the |
|
function will return CKR_BUFFER_TOO_SMALL, as it |
|
does if an attribute in the pTemplate argument |
|
has ulValueLen too small. Note that any |
|
attribute whose value is an array of attributes |
|
is identifiable by virtue of the attribute type |
|
having the CKF_ARRAY_ATTRIBUTE bit set.» */ |
|
res = Attribute(attr); |
|
else |
|
free(attr.pValue); |
|
} catch (...) { |
|
free(attr.pValue); |
|
throw; |
|
} |
|
return res; |
|
} |
|
|
|
//! Get a List of Attributes. |
|
/*! If @c attrs is empty, all available attributes are |
|
returned. Attributes that cannot be accessed or that are not |
|
available in this Object won't be in the result map. There |
|
is no exception in this case. */ |
|
AttributeMap attributes(AttributeTypeList attrs |
|
= AttributeTypeList()) { |
|
CRYPTOKI_LOG("log"); |
|
AttributeMap res; |
|
//! Gets all attributes, if @c attrs is empty |
|
if (attrs.empty()) { |
|
attrs.push_back(CKA_CLASS); |
|
attrs.push_back(CKA_TOKEN); |
|
attrs.push_back(CKA_PRIVATE); |
|
attrs.push_back(CKA_LABEL); |
|
attrs.push_back(CKA_APPLICATION); |
|
attrs.push_back(CKA_VALUE); |
|
attrs.push_back(CKA_OBJECT_ID); |
|
attrs.push_back(CKA_CERTIFICATE_TYPE); |
|
attrs.push_back(CKA_ISSUER); |
|
attrs.push_back(CKA_SERIAL_NUMBER); |
|
attrs.push_back(CKA_AC_ISSUER); |
|
attrs.push_back(CKA_OWNER); |
|
attrs.push_back(CKA_ATTR_TYPES); |
|
attrs.push_back(CKA_TRUSTED); |
|
attrs.push_back(CKA_KEY_TYPE); |
|
attrs.push_back(CKA_SUBJECT); |
|
attrs.push_back(CKA_ID); |
|
attrs.push_back(CKA_SENSITIVE); |
|
attrs.push_back(CKA_ENCRYPT); |
|
attrs.push_back(CKA_DECRYPT); |
|
attrs.push_back(CKA_WRAP); |
|
attrs.push_back(CKA_UNWRAP); |
|
attrs.push_back(CKA_SIGN); |
|
attrs.push_back(CKA_SIGN_RECOVER); |
|
attrs.push_back(CKA_VERIFY); |
|
attrs.push_back(CKA_VERIFY_RECOVER); |
|
attrs.push_back(CKA_DERIVE); |
|
attrs.push_back(CKA_START_DATE); |
|
attrs.push_back(CKA_END_DATE); |
|
attrs.push_back(CKA_MODULUS); |
|
attrs.push_back(CKA_MODULUS_BITS); |
|
attrs.push_back(CKA_PUBLIC_EXPONENT); |
|
attrs.push_back(CKA_PRIVATE_EXPONENT); |
|
attrs.push_back(CKA_PRIME_1); |
|
attrs.push_back(CKA_PRIME_2); |
|
attrs.push_back(CKA_EXPONENT_1); |
|
attrs.push_back(CKA_EXPONENT_2); |
|
attrs.push_back(CKA_COEFFICIENT); |
|
attrs.push_back(CKA_PRIME); |
|
attrs.push_back(CKA_SUBPRIME); |
|
attrs.push_back(CKA_BASE); |
|
attrs.push_back(CKA_PRIME_BITS); |
|
//attrs.push_back(CKA_SUBPRIME_BITS); |
|
attrs.push_back(CKA_VALUE_BITS); |
|
attrs.push_back(CKA_VALUE_LEN); |
|
attrs.push_back(CKA_EXTRACTABLE); |
|
attrs.push_back(CKA_LOCAL); |
|
attrs.push_back(CKA_NEVER_EXTRACTABLE); |
|
attrs.push_back(CKA_ALWAYS_SENSITIVE); |
|
attrs.push_back(CKA_KEY_GEN_MECHANISM); |
|
attrs.push_back(CKA_MODIFIABLE); |
|
attrs.push_back(CKA_ECDSA_PARAMS); |
|
attrs.push_back(CKA_EC_PARAMS); |
|
attrs.push_back(CKA_EC_POINT); |
|
attrs.push_back(CKA_SECONDARY_AUTH); |
|
attrs.push_back(CKA_AUTH_PIN_FLAGS); |
|
attrs.push_back(CKA_HW_FEATURE_TYPE); |
|
attrs.push_back(CKA_RESET_ON_INIT); |
|
attrs.push_back(CKA_HAS_RESET); |
|
attrs.push_back(CKA_VENDOR_DEFINED); |
|
//attrs.push_back(CKA_IBM_OPAQUE); |
|
} |
|
CK_ATTRIBUTE attr; |
|
for (AttributeTypeList::const_iterator it(attrs.begin()); |
|
it!=attrs.end(); ++it) { |
|
attr = (CK_ATTRIBUTE){*it, 0, 0}; |
|
try { |
|
//! calls @c C_GetAttributeValue |
|
if (_session._slot._init->_fn->C_GetAttributeValue |
|
(_session._session, _object, &attr, 1) |
|
== CKR_ATTRIBUTE_TYPE_INVALID |
|
|| _res == CKR_ATTRIBUTE_SENSITIVE) { |
|
continue; //! Ignores unsupported Attributes. |
|
} else { |
|
check(_res, CRYPTOKI_FN_LOG("C_GetAttributeValue")); |
|
if ((long)attr.ulValueLen>0l) { |
|
attr.pValue = malloc(attr.ulValueLen); |
|
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); |
|
if (check(_session._slot._init->_fn->C_GetAttributeValue |
|
(_session._session, _object, &attr, 1), |
|
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) |
|
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open |
|
Cryptoki. From the Specs: «In the special |
|
case of an attribute whose value is an |
|
array of attributes, for example |
|
CKA_WRAP_TEMPLATE, where it is passed in |
|
with pValue not NULL, then if the pValue |
|
of elements within the array is NULL_PTR |
|
then the ulValueLen of elements within the |
|
array will be set to the required |
|
length. If the pValue of elements within |
|
the array is not NULL_PTR, then the |
|
ulValueLen element of attributes within |
|
the array must reflect the space that the |
|
corresponding pValue points to, and pValue |
|
is filled in if there is sufficient |
|
room. Therefore it is important to |
|
initialize the contents of a buffer before |
|
calling C_GetAttributeValue to get such an |
|
array value. If any ulValueLen within the |
|
array isn't large enough, it will be set |
|
to -1 and the function will return |
|
CKR_BUFFER_TOO_SMALL, as it does if an |
|
attribute in the pTemplate argument has |
|
ulValueLen too small. Note that any |
|
attribute whose value is an array of |
|
attributes is identifiable by virtue of |
|
the attribute type having the |
|
CKF_ARRAY_ATTRIBUTE bit set.» */ |
|
res.insert(std::make_pair(attr.type, Attribute(attr))); |
|
else |
|
free(attr.pValue); |
|
} else if (*it==CKA_MODULUS && attr.ulValueLen==0) { |
|
/*! @bug This is a bug in onepin-opensc-pkcs11.so: If |
|
@c CKA_MODULUS has a size of 0 bytes, the |
|
following query to @c CKA_MODULUS_BITS ends |
|
in a segmentation fault. |
|
|
|
@note @c CKA_MODULUS @b must immediately be |
|
followed by @c CKA_MODULUS_BITS in the |
|
attribute list, because if the size of @c |
|
CKA_MODULUS is 0 Bytes, the following |
|
attribute query is skipped as a work around |
|
to this bug. */ |
|
if (++it==attrs.end()) break; |
|
} |
|
} |
|
} catch (...) { |
|
free(attr.pValue); |
|
throw; |
|
} |
|
} |
|
return res; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool getobjectsize() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_GetObjectSize |
|
return check(_session._slot._init->_fn->C_GetObjectSize(_session._session, CK_OBJECT_HANDLE, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_GetObjectSize")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool setattributevalue() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_SetAttributeValue |
|
return check(_session._slot._init->_fn->C_SetAttributeValue(_session._session, CK_OBJECT_HANDLE, |
|
CK_ATTRIBUTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_SetAttributeValue")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool setoperationstate() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_SetOperationState |
|
return check(_session._slot._init->_fn->C_SetOperationState(_session._session, CK_BYTE_PTR, CK_ULONG, |
|
CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_SetOperationState")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool signinit() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_SignInit |
|
return check(_session._slot._init->_fn->C_SignInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_SignInit")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool signrecoverinit() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_SignRecoverInit |
|
return check(_session._slot._init->_fn->C_SignRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_SignRecoverInit")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool unwrapkey() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_UnwrapKey |
|
return check(_session._slot._init->_fn->C_UnwrapKey(_session._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() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_VerifyInit |
|
return check(_session._slot._init->_fn->C_VerifyInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_VerifyInit")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool verifyrecoverinit() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_VerifyRecoverInit |
|
return check(_session._slot._init->_fn->C_VerifyRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_VerifyRecoverInit")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool wrapkey() { |
|
CRYPTOKI_LOG("log"); |
|
//! calls @c C_WrapKey |
|
return check(_session._slot._init->_fn->C_WrapKey(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, |
|
CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_WrapKey")); |
|
} |
|
@endcode */ |
|
|
|
//@} |
|
|
|
}; |
|
//@} |
|
|
|
} |
|
|
|
//! @groupadd globaloperator |
|
//@{ |
|
inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list, |
|
const cryptoki::Attribute& attr) { |
|
CRYPTOKI_LOG("log"); |
|
list.push_back(attr); |
|
return list; |
|
} |
|
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, |
|
const cryptoki::Attribute& attr) { |
|
CRYPTOKI_LOG("log"); |
|
cryptoki::AttributeList res(list); |
|
res.push_back(attr); |
|
return res; |
|
} |
|
//@} |
|
|
|
//@} |
|
#endif
|
|
|