|
|
|
@ -29,13 +29,26 @@ |
|
|
|
|
#include <iomanip> |
|
|
|
|
#include <memory> |
|
|
|
|
|
|
|
|
|
/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API */ |
|
|
|
|
/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API
|
|
|
|
|
|
|
|
|
|
Wrapper to abstract the ugly PKCS#11 C-API with nice C++ features, |
|
|
|
|
such as exception handling, memory management, etc. |
|
|
|
|
|
|
|
|
|
The cryptoky library loads a dynamic library that is responsible |
|
|
|
|
for translating the card specific commands. The library is passed |
|
|
|
|
in the constructor of cryptoki::Library. Then method |
|
|
|
|
cryptoki::Library::slotList returns all slots found on the |
|
|
|
|
computer. */ |
|
|
|
|
//@{
|
|
|
|
|
/*! @defgroup cryptokilib Cryptoki C++ Library */ |
|
|
|
|
/*! @defgroup globaloperator Global Operator */ |
|
|
|
|
/*! @defgroup cryptokitypes Cryptoki C++ Types and Auxiliary */ |
|
|
|
|
/*! @defgroup cryptokiexceptions Cryptoki Exceptions */ |
|
|
|
|
/** @example cryptoki-demo.cxx */ |
|
|
|
|
/** @example cryptoki-sign-demo.cxx */ |
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
/// @addtogroup cryptokitypes
|
|
|
|
|
//@{
|
|
|
|
|
#ifndef CRYPTOKI_FN_LOG |
|
|
|
|
#include <iostream> |
|
|
|
|
#if __GNUC__ >= 2 |
|
|
|
@ -58,6 +71,7 @@ |
|
|
|
|
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__) |
|
|
|
|
#endif |
|
|
|
|
#endif |
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
namespace pcsc { |
|
|
|
|
std::string version(); |
|
|
|
@ -69,6 +83,11 @@ namespace cryptoki { |
|
|
|
|
//! @addtogroup cryptokitypes
|
|
|
|
|
//@{
|
|
|
|
|
|
|
|
|
|
/// Map cryptoki number to a string, care about unavailable and infinite
|
|
|
|
|
/** Cryptoky knows illegal values (unavailable information), which
|
|
|
|
|
is mapped to @c - and infinite values which are mapped to @c ∞ |
|
|
|
|
when converted to string. All other numbers just show the number |
|
|
|
|
as numeric string. */ |
|
|
|
|
inline std::string string(CK_ULONG num) { |
|
|
|
|
switch (num) { |
|
|
|
|
case CK_UNAVAILABLE_INFORMATION: return "-"; |
|
|
|
@ -81,11 +100,10 @@ namespace cryptoki { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
template <int NUM, typename TYPE> std::vector<TYPE> toVector(TYPE in[NUM]) { |
|
|
|
|
return std::vector<TYPE>(in, in+NUM); |
|
|
|
|
/// Convert any kind of array (buffer) to an std::vector.
|
|
|
|
|
template <typename TYPE> std::vector<TYPE> toVector(TYPE in[]) { |
|
|
|
|
return std::vector<TYPE>(in, in+sizeof(in)/sizeof(in[0])); |
|
|
|
|
} |
|
|
|
|
#define CRYPTOKI_TO_VECTOR(ARRAY) \ |
|
|
|
|
toVector<sizeof(ARRAY)/sizeof(ARRAY[0])>(ARRAY) |
|
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
@ -136,10 +154,9 @@ namespace cryptoki { |
|
|
|
|
class Object; |
|
|
|
|
typedef std::vector<Object> ObjectList; |
|
|
|
|
|
|
|
|
|
typedef std::set<CK_MECHANISM_TYPE> MechanismList; |
|
|
|
|
|
|
|
|
|
typedef std::vector<CK_ATTRIBUTE_TYPE> AttributeTypeList; |
|
|
|
|
|
|
|
|
|
/// Represents a cryproki attribute and maps to C++ types.
|
|
|
|
|
class Attribute { |
|
|
|
|
public: |
|
|
|
|
Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {} |
|
|
|
@ -171,6 +188,7 @@ namespace cryptoki { |
|
|
|
|
a.ulValueLen = value.size(); |
|
|
|
|
return a; |
|
|
|
|
} |
|
|
|
|
/// Textual name of the attribute.
|
|
|
|
|
std::string name() const { |
|
|
|
|
switch (type) { |
|
|
|
|
case CKA_CLASS: return "CLASS"; |
|
|
|
@ -234,30 +252,39 @@ namespace cryptoki { |
|
|
|
|
case CKA_HAS_RESET: return "HAS_RESET"; |
|
|
|
|
case CKA_VENDOR_DEFINED: return "VENDOR_DEFINED"; |
|
|
|
|
//case CKA_IBM_OPAQUE: return "IBM_OPAQUE";
|
|
|
|
|
default: return "unknown"; |
|
|
|
|
default: return "UNKNOWN"; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
std::string readableValue() const { |
|
|
|
|
/// Textual representation of the value.
|
|
|
|
|
std::string readableValue(std::string::size_type len=20, |
|
|
|
|
std::string::size_type indent=0) const { |
|
|
|
|
std::string res(indent, ' '); |
|
|
|
|
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: return "unknown"; |
|
|
|
|
} |
|
|
|
|
default: return crypto::readable(value); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
case CKO_DATA: return res+"DATA"; |
|
|
|
|
case CKO_CERTIFICATE: return res+"CERTIFICATE"; |
|
|
|
|
case CKO_PUBLIC_KEY: return res+"PUBLIC_KEY"; |
|
|
|
|
case CKO_PRIVATE_KEY: return res+"PRIVATE_KEY"; |
|
|
|
|
case CKO_SECRET_KEY: return res+"SECRET_KEY"; |
|
|
|
|
case CKO_HW_FEATURE: return res+"HW_FEATURE"; |
|
|
|
|
case CKO_DOMAIN_PARAMETERS: return res+"DOMAIN_PARAMETERS"; |
|
|
|
|
case CKO_VENDOR_DEFINED: return res+"VENDOR_DEFINED"; |
|
|
|
|
default: return res+"UNKNOWN"; |
|
|
|
|
} |
|
|
|
|
default: return crypto::readable(value, len, indent); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
/// Initialize from a given type.
|
|
|
|
|
/** To use this method, you must know what type the attribute
|
|
|
|
|
represents. */ |
|
|
|
|
template<typename TYPE> Attribute& from(const TYPE& v) { |
|
|
|
|
value = std::string((char*)&v, sizeof(TYPE)); |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
/// Convert to a given type.
|
|
|
|
|
/** To use this method, you must know what type the attribute
|
|
|
|
|
represents. */ |
|
|
|
|
template<typename TYPE> TYPE to() const { |
|
|
|
|
assert(sizeof(TYPE)==value.size()); |
|
|
|
|
return *reinterpret_cast<const TYPE*>(&value[0]); |
|
|
|
@ -268,44 +295,10 @@ namespace cryptoki { |
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
/// String with fixed length.
|
|
|
|
|
/** FixString represents a string with a fix with spaces and can be
|
|
|
|
|
converted from and to a std::string by adding and removing the |
|
|
|
|
fill-spaces. */ |
|
|
|
|
template<std::string::size_type SIZE> |
|
|
|
|
class FixString: public std::string { |
|
|
|
|
public: |
|
|
|
@ -346,13 +339,26 @@ namespace cryptoki { |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// C++ representation of mechanism information.
|
|
|
|
|
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) { |
|
|
|
|
/// Construct from type with undefined infos. Use assigment later.
|
|
|
|
|
MechanismInfo(CK_MECHANISM_TYPE type): |
|
|
|
|
minKeySize(0), maxKeySize(0), flags(0) { |
|
|
|
|
*this=type; |
|
|
|
|
} |
|
|
|
|
/// Fully construct from type and infos.
|
|
|
|
|
MechanismInfo(CK_MECHANISM_TYPE type, const CK_MECHANISM_INFO& info) { |
|
|
|
|
*this=type; |
|
|
|
|
*this=info; |
|
|
|
|
} |
|
|
|
|
/// Set name and id from CK_MECHANISM_TYPE.
|
|
|
|
|
MechanismInfo& operator=(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; |
|
|
|
@ -378,7 +384,7 @@ namespace cryptoki { |
|
|
|
|
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_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; |
|
|
|
@ -421,15 +427,15 @@ namespace cryptoki { |
|
|
|
|
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_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; |
|
|
|
@ -442,19 +448,21 @@ namespace cryptoki { |
|
|
|
|
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_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; |
|
|
|
@ -476,31 +484,34 @@ namespace cryptoki { |
|
|
|
|
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_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_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_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_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_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; |
|
|
|
@ -508,7 +519,8 @@ namespace cryptoki { |
|
|
|
|
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_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; |
|
|
|
@ -532,9 +544,9 @@ namespace cryptoki { |
|
|
|
|
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_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; |
|
|
|
@ -559,13 +571,26 @@ namespace cryptoki { |
|
|
|
|
case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break; |
|
|
|
|
default: { |
|
|
|
|
std::stringstream ss; |
|
|
|
|
ss<<"unknown mechanism: "<<id; |
|
|
|
|
throw exception(ss.str()); |
|
|
|
|
ss<<id; |
|
|
|
|
name=ss.str(); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
/// Assign information.
|
|
|
|
|
MechanismInfo& operator=(const CK_MECHANISM_INFO& info) { |
|
|
|
|
minKeySize = info.ulMinKeySize; |
|
|
|
|
maxKeySize = info.ulMaxKeySize; |
|
|
|
|
flags = info.flags; |
|
|
|
|
return *this; |
|
|
|
|
} |
|
|
|
|
bool operator<(const MechanismInfo& o) const { |
|
|
|
|
return id<o.id; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
typedef std::set<MechanismInfo> MechanismList; |
|
|
|
|
|
|
|
|
|
/// Handle slot information.
|
|
|
|
|
struct SlotInfo { |
|
|
|
|
FixString<64> slotDescription; |
|
|
|
|
FixString<32> manufacturerID; |
|
|
|
@ -589,6 +614,7 @@ namespace cryptoki { |
|
|
|
|
struct TokenInfo; // forward declaration
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti); |
|
|
|
|
|
|
|
|
|
/// Handle token information.
|
|
|
|
|
struct TokenInfo { |
|
|
|
|
FixString<32> label; |
|
|
|
|
FixString<32> manufacturerID; |
|
|
|
@ -638,6 +664,7 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/// Textual representation for token information.
|
|
|
|
|
inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti) { |
|
|
|
|
return out |
|
|
|
|
<<"label="<<ti.label<<std::endl |
|
|
|
@ -662,6 +689,7 @@ namespace cryptoki { |
|
|
|
|
<<"utcTime="<<ti.utcTime; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Handle library information.
|
|
|
|
|
struct Info { |
|
|
|
|
CK_VERSION cryptokiVersion; |
|
|
|
|
FixString<32> manufacturerID; |
|
|
|
@ -676,20 +704,22 @@ namespace cryptoki { |
|
|
|
|
//@{
|
|
|
|
|
|
|
|
|
|
/// Load Cryptoki Library for use with Smart Card.
|
|
|
|
|
/** This is your starting point when accessing tokens through
|
|
|
|
|
PKCS#11. Get an instance using Library::Library. */ |
|
|
|
|
class Library { |
|
|
|
|
|
|
|
|
|
friend class Slot; |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
//! Initialize for a given library (default cryptoki)
|
|
|
|
|
/*! Please notem, that you must not instanciate more than one
|
|
|
|
|
Init per unique function list! |
|
|
|
|
//! Initialize for a given library
|
|
|
|
|
/*! @note Do not instanciate more than one Library instance per
|
|
|
|
|
shared library. Normally you need only one instance. |
|
|
|
|
|
|
|
|
|
@param library name of the shared library that supports pkcs#11 |
|
|
|
|
@param exc wether exceptions should be thrown */ |
|
|
|
|
Library(const std::string& library, bool exc=true): |
|
|
|
|
_init(library, exc) { |
|
|
|
|
_init(new Init(library, exc)) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -699,8 +729,9 @@ namespace cryptoki { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
/// Initiatlize the library: load and unload the shared object.
|
|
|
|
|
class Init { |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
@ -726,12 +757,7 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
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 */ |
|
|
|
|
/// Called from Library::Library
|
|
|
|
|
Init(const std::string& library="opensc-pkcs11.so", bool exc=true); |
|
|
|
|
|
|
|
|
|
~Init(); |
|
|
|
@ -767,14 +793,12 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
/// Get pointer to cryptoki API functions.
|
|
|
|
|
/** Used internally, normally you shouldn't use this directly. */ |
|
|
|
|
CK_FUNCTION_LIST* operator->() { |
|
|
|
|
return _init->fn(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool exc() { |
|
|
|
|
return _init->_exc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*! @name C Like Error Handling
|
|
|
|
|
|
|
|
|
|
You are strongly recommended not to disable exception |
|
|
|
@ -783,6 +807,11 @@ namespace cryptoki { |
|
|
|
|
provide all you need for that. */ |
|
|
|
|
//@{
|
|
|
|
|
|
|
|
|
|
/// @return true if exceptions are thrown in case of error
|
|
|
|
|
bool exc() { |
|
|
|
|
return _init->_exc; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*! @return @c true if last cryptoki on this object call was successful */ |
|
|
|
|
operator bool() { |
|
|
|
|
return *_init; |
|
|
|
@ -793,12 +822,14 @@ namespace cryptoki { |
|
|
|
|
return _init->error(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Convert @c CK_RV return code to a human readable text.
|
|
|
|
|
std::string error(CK_RV res) { |
|
|
|
|
return _init->error(res); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
/// Get cryptoki library informartion.
|
|
|
|
|
Info info() { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
Info inf; |
|
|
|
@ -825,7 +856,7 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
mrw::Shared<Init> _init; |
|
|
|
|
std::shared_ptr<Init> _init; |
|
|
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
@ -843,16 +874,21 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
Slot(const Library& lib, CK_SLOT_ID slot): |
|
|
|
|
_library(lib), _slot(slot), _res(CKR_OK) { |
|
|
|
|
Slot(const Slot& o): |
|
|
|
|
_library(o._library), _slot(o._slot), _res(o._res) { |
|
|
|
|
CRYPTOLOG("ID="<<_slot); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Slot(const Slot& o): |
|
|
|
|
_library(o._library), _slot(o._slot), _res(o._res) { |
|
|
|
|
private: |
|
|
|
|
|
|
|
|
|
/// Slots are created from Library::slotList.
|
|
|
|
|
Slot(const Library& lib, CK_SLOT_ID slot): |
|
|
|
|
_library(lib), _slot(slot), _res(CKR_OK) { |
|
|
|
|
CRYPTOLOG("ID="<<_slot); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Slots are created from Library::slotList.
|
|
|
|
|
/** Empty constructor needs immediate assignment. */ |
|
|
|
|
Slot(): _slot(0), _res(-1) { |
|
|
|
|
CRYPTOLOG("ID="<<_slot); |
|
|
|
|
} |
|
|
|
@ -877,6 +913,8 @@ namespace cryptoki { |
|
|
|
|
return _res==CKR_OK; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
|
|
/*! @name C Like Error Handling
|
|
|
|
|
|
|
|
|
|
You are strongly recommended not to disable exception |
|
|
|
@ -897,23 +935,23 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
/// Access to the Library.
|
|
|
|
|
Library& library() { |
|
|
|
|
return _library; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Get the Slot's MechanismInfo given a @c CK_MECHANISM_TYPE
|
|
|
|
|
/** Used internally by mechanismlist(). */ |
|
|
|
|
MechanismInfo mechanisminfo(CK_MECHANISM_TYPE mechanism) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
MechanismInfo info(mechanism); |
|
|
|
|
CK_MECHANISM_INFO cInfo; |
|
|
|
|
CK_MECHANISM_INFO info; |
|
|
|
|
//! calls @c C_GetMechanismInfo
|
|
|
|
|
check(_library->C_GetMechanismInfo(_slot, mechanism, &cInfo), |
|
|
|
|
check(_library->C_GetMechanismInfo(_slot, mechanism, &info), |
|
|
|
|
CRYPTOKI_FN_LOG("C_GetMechanismInfo")); |
|
|
|
|
info.minKeySize = cInfo.ulMinKeySize; |
|
|
|
|
info.maxKeySize = cInfo.ulMaxKeySize; |
|
|
|
|
info.flags = cInfo.flags; |
|
|
|
|
return info; |
|
|
|
|
return MechanismInfo(mechanism, info); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/// Get a list of the Slot's mechanisms.
|
|
|
|
|
MechanismList mechanismlist() { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
MechanismList res; |
|
|
|
@ -930,7 +968,7 @@ namespace cryptoki { |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
for (CK_ULONG i(0); i<count; ++i) |
|
|
|
|
res.insert(mechanisms[i]); |
|
|
|
|
res.insert(mechanisminfo(mechanisms[i])); |
|
|
|
|
} catch (...) { |
|
|
|
|
delete[] mechanisms; |
|
|
|
|
throw; |
|
|
|
@ -961,18 +999,79 @@ namespace cryptoki { |
|
|
|
|
return TokenInfo(cInfo); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*! @bug does not compile:
|
|
|
|
|
@code |
|
|
|
|
/// Initialize a token.
|
|
|
|
|
/** If the token has not been initialized (i.e. new from the
|
|
|
|
|
factory), then the @c pin parameter becomes the initial value |
|
|
|
|
of the SO PIN. If the token is being reinitialized, the @c pin |
|
|
|
|
parameter is checked against the existing SO PIN to |
|
|
|
|
authorize the initialization operation. In both cases, the |
|
|
|
|
SO PIN is the value @c pin after the function completes |
|
|
|
|
successfully. If the SO PIN is lost, then the card must be |
|
|
|
|
reinitialized using a mechanism outside the scope of this |
|
|
|
|
standard. The CKF_TOKEN_INITIALIZED flag in the |
|
|
|
|
CK_TOKEN_INFO structure indicates the action that will |
|
|
|
|
result from calling C_InitToken. If set, the token will be |
|
|
|
|
reinitialized, and the client must supply the existing SO |
|
|
|
|
password in @c pin. |
|
|
|
|
|
|
|
|
|
When a token is initialized, all objects that can be |
|
|
|
|
destroyed are destroyed (i.e., all except for |
|
|
|
|
“indestructible” objects such as keys built into the |
|
|
|
|
token). Also, access by the normal user is disabled until |
|
|
|
|
the SO sets the normal user’s PIN. Depending on the token, |
|
|
|
|
some “default” objects may be created, and attributes of |
|
|
|
|
some objects may be set to default values. |
|
|
|
|
|
|
|
|
|
If the token has a “protected authentication path”, as |
|
|
|
|
indicated by the CKF_PROTECTED_AUTHENTICATION_PATH flag in |
|
|
|
|
its CK_TOKEN_INFO being set, then that means that there is |
|
|
|
|
some way for a user to be authenticated to the token without |
|
|
|
|
having the application send a PIN through the Cryptoki |
|
|
|
|
library. One such possibility is that the user enters a PIN |
|
|
|
|
on a PINpad on the token itself, or on the slot device. To |
|
|
|
|
initialize a token with such a protected authentication |
|
|
|
|
path, the @c pin parameter to C_InitToken should be empty. |
|
|
|
|
During the execution of C_InitToken, the SO’s PIN will be |
|
|
|
|
entered through the protected authentication path. |
|
|
|
|
|
|
|
|
|
If the token has a protected authentication path other than |
|
|
|
|
a PINpad, then it is token- dependent whether or not |
|
|
|
|
C_InitToken can be used to initialize the token. |
|
|
|
|
|
|
|
|
|
A token cannot be initialized if Cryptoki detects that any |
|
|
|
|
application has an open session with it; when a call to |
|
|
|
|
C_InitToken is made under such circumstances, the call fails |
|
|
|
|
with error CKR_SESSION_EXISTS. Unfortunately, it may happen |
|
|
|
|
when C_InitToken is called that some other application does |
|
|
|
|
have an open session with the token, but Cryptoki cannot |
|
|
|
|
detect this, because it cannot detect anything about other |
|
|
|
|
applications using the token. If this is the case, then the |
|
|
|
|
consequences of the C_InitToken call are undefined. |
|
|
|
|
|
|
|
|
|
The C_InitToken function may not be sufficient to properly |
|
|
|
|
initialize complex tokens. In these situations, an |
|
|
|
|
initialization mechanism outside the scope of Cryptoki must |
|
|
|
|
be employed. The definition of “complex token” is product |
|
|
|
|
specific. |
|
|
|
|
|
|
|
|
|
@param pin SO's initial PIN |
|
|
|
|
@param label label of the token */ |
|
|
|
|
bool inittoken(std::string pin, FixString<32> label) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
//! calls @c C_InitToken
|
|
|
|
|
if (pin.size()) |
|
|
|
|
return check(_library->C_InitToken |
|
|
|
|
(_slot, |
|
|
|
|
(unsigned char*)&pin[0], pin.size(), |
|
|
|
|
(unsigned char*)label.&fix()[0]) |
|
|
|
|
(unsigned char*)&label.fix()[0]), |
|
|
|
|
CRYPTOKI_FN_LOG("C_InitToken")); |
|
|
|
|
else |
|
|
|
|
return check(_library->C_InitToken |
|
|
|
|
(_slot, |
|
|
|
|
0, 0, // pin from external pin pad
|
|
|
|
|
(unsigned char*)&label.fix()[0]), |
|
|
|
|
CRYPTOKI_FN_LOG("C_InitToken")); |
|
|
|
|
} |
|
|
|
|
@endcode */ |
|
|
|
|
|
|
|
|
|
/*! @todo Not implemented:
|
|
|
|
|
@code |
|
|
|
@ -983,14 +1082,14 @@ namespace cryptoki { |
|
|
|
|
bool registerforslotevent(SlotEventListener&) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
//! calls @c C_WaitForSlotEvent
|
|
|
|
|
return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, CK_VOID_PTR), |
|
|
|
|
return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, 0), |
|
|
|
|
CRYPTOKI_FN_LOG("C_WaitForSlotEvent")); |
|
|
|
|
} |
|
|
|
|
@endcode */ |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
//! Session Management
|
|
|
|
|
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID);
|
|
|
|
|
/// Session Management
|
|
|
|
|
/** @note Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); */ |
|
|
|
|
class Session { |
|
|
|
|
private: |
|
|
|
|
|
|
|
|
@ -2167,14 +2266,16 @@ namespace cryptoki { |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! @groupadd globaloperator
|
|
|
|
|
//! @groupadd cryptokitypes
|
|
|
|
|
//@{
|
|
|
|
|
/// Append a cryptoki::Attribute to a cryptoki::AttributeList.
|
|
|
|
|
inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list, |
|
|
|
|
const cryptoki::Attribute& attr) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
|
list.push_back(attr); |
|
|
|
|
return list; |
|
|
|
|
} |
|
|
|
|
/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList.
|
|
|
|
|
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, |
|
|
|
|
const cryptoki::Attribute& attr) { |
|
|
|
|
CRYPTOLOG("log"); |
|
|
|
@ -2184,5 +2285,4 @@ inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, |
|
|
|
|
} |
|
|
|
|
//@}
|
|
|
|
|
|
|
|
|
|
//@}
|
|
|
|
|
#endif |
|
|
|
|