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.
2707 lines
92 KiB
2707 lines
92 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 <pkcs11.h> |
|
#else |
|
#include <cryptoki.h> |
|
#endif |
|
#include <string> |
|
#include <vector> |
|
#include <map> |
|
#include <set> |
|
#include <mrw/checkcxx11.hxx> |
|
#include <memory> |
|
|
|
// for inline implementations only |
|
#include <cryptaux.hxx> |
|
#include <sstream> |
|
#include <cstdlib> // malloc/free |
|
#include <cstring> // memset |
|
#include <cassert> // assert |
|
#include <iomanip> |
|
|
|
/*! @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 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 |
|
//! 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) CRYPTOKI_QUOTE2(X) |
|
#define CRYPTOKI_QUOTE2(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 string */ |
|
#define CRYPTOKI_FN_LOG(X) X " failed in \ |
|
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__) |
|
#endif |
|
#endif |
|
//@} |
|
|
|
//! @ref gcryptoki @copydoc gcryptoki |
|
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 "-"; |
|
case CK_EFFECTIVELY_INFINITE: return "∞"; |
|
default: { |
|
std::stringstream ss; |
|
ss<<num; |
|
return ss.str(); |
|
} |
|
} |
|
} |
|
|
|
/// 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])); |
|
} |
|
|
|
//@} |
|
|
|
//============================================================================ |
|
/*! @addtogroup cryptokiexceptions */ |
|
//@{ |
|
|
|
//---------------------------------------------------------------------------- |
|
class exception: public std::exception { |
|
public: |
|
exception(const std::string& reason) throw(): |
|
_what("cryptoki: "+reason) { |
|
CRYPTOLOG("ERROR: "<<what()); |
|
} |
|
~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: "+reason) {} |
|
}; |
|
//---------------------------------------------------------------------------- |
|
class access_error: public exception { |
|
public: |
|
access_error(const std::string& reason) throw(): |
|
exception("smardcard access error: "+reason) {} |
|
}; |
|
//---------------------------------------------------------------------------- |
|
class wrong_pin: public access_error { |
|
public: |
|
wrong_pin(const std::string& reason) throw(): |
|
access_error("wrong pin: "+reason) {} |
|
}; |
|
//@} |
|
|
|
/*! @addtogroup cryptokitypes */ |
|
//@{ |
|
|
|
class Slot; |
|
typedef std::vector<Slot> SlotList; |
|
|
|
class Object; |
|
typedef std::vector<Object> ObjectList; |
|
|
|
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) {} |
|
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; |
|
} |
|
/// Textual name of the attribute. |
|
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"; |
|
} |
|
} |
|
/// 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 (*((const CK_OBJECT_CLASS*)&value[0])) { |
|
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((const 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]); |
|
} |
|
CK_ATTRIBUTE_TYPE type; |
|
std::string value; |
|
}; |
|
typedef std::map<CK_ATTRIBUTE_TYPE, Attribute> AttributeMap; |
|
typedef std::vector<Attribute> AttributeList; |
|
|
|
/// 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: |
|
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; |
|
} |
|
}; |
|
|
|
/// C++ representation of mechanism information. |
|
struct MechanismInfo { |
|
CK_MECHANISM_TYPE id; |
|
std::string name; |
|
CK_ULONG minKeySize; |
|
CK_ULONG maxKeySize; |
|
CK_FLAGS flags; |
|
/// 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) { |
|
#ifdef CKM_RSA_PKCS_KEY_PAIR_GEN |
|
case CKM_RSA_PKCS_KEY_PAIR_GEN: name="RSA_PKCS_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_RSA_PKCS |
|
case CKM_RSA_PKCS: name="RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_RSA_9796 |
|
case CKM_RSA_9796: name="RSA_9796"; break; |
|
#endif |
|
#ifdef CKM_RSA_X_509 |
|
case CKM_RSA_X_509: name="RSA_X_509"; break; |
|
#endif |
|
#ifdef CKM_MD2_RSA_PKCS |
|
case CKM_MD2_RSA_PKCS: name="MD2_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_MD5_RSA_PKCS |
|
case CKM_MD5_RSA_PKCS: name="MD5_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_SHA1_RSA_PKCS |
|
case CKM_SHA1_RSA_PKCS: name="SHA1_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD128_RSA_PKCS |
|
case CKM_RIPEMD128_RSA_PKCS: name="RIPEMD128_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD160_RSA_PKCS |
|
case CKM_RIPEMD160_RSA_PKCS: name="RIPEMD160_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_RSA_PKCS_OAEP |
|
case CKM_RSA_PKCS_OAEP: name="RSA_PKCS_OAEP"; break; |
|
#endif |
|
#ifdef CKM_RSA_X9_31_KEY_PAIR_GEN |
|
case CKM_RSA_X9_31_KEY_PAIR_GEN: name="RSA_X9_31_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_RSA_X9_31 |
|
case CKM_RSA_X9_31: name="RSA_X9_31"; break; |
|
#endif |
|
#ifdef CKM_SHA1_RSA_X9_31 |
|
case CKM_SHA1_RSA_X9_31: name="SHA1_RSA_X9_31"; break; |
|
#endif |
|
#ifdef CKM_RSA_PKCS_PSS |
|
case CKM_RSA_PKCS_PSS: name="RSA_PKCS_PSS"; break; |
|
#endif |
|
#ifdef CKM_SHA1_RSA_PKCS_PSS |
|
case CKM_SHA1_RSA_PKCS_PSS: name="SHA1_RSA_PKCS_PSS"; break; |
|
#endif |
|
#ifdef CKM_DSA_KEY_PAIR_GEN |
|
case CKM_DSA_KEY_PAIR_GEN: name="DSA_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_DSA |
|
case CKM_DSA: name="DSA"; break; |
|
#endif |
|
#ifdef CKM_DSA_SHA1 |
|
case CKM_DSA_SHA1: name="DSA_SHA1"; break; |
|
#endif |
|
#ifdef CKM_DH_PKCS_KEY_PAIR_GEN |
|
case CKM_DH_PKCS_KEY_PAIR_GEN: name="DH_PKCS_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_DH_PKCS_DERIVE |
|
case CKM_DH_PKCS_DERIVE: name="DH_PKCS_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_X9_42_DH_KEY_PAIR_GEN |
|
case CKM_X9_42_DH_KEY_PAIR_GEN: name="X9_42_DH_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_X9_42_DH_DERIVE |
|
case CKM_X9_42_DH_DERIVE: name="X9_42_DH_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_X9_42_DH_HYBRID_DERIVE |
|
case CKM_X9_42_DH_HYBRID_DERIVE: name="X9_42_DH_HYBRID_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_X9_42_MQV_DERIVE |
|
case CKM_X9_42_MQV_DERIVE: name="X9_42_MQV_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_SHA256_RSA_PKCS |
|
case CKM_SHA256_RSA_PKCS: name="SHA256_RSA_PKCS"; break; |
|
#endif |
|
#ifdef CKM_RC2_KEY_GEN |
|
case CKM_RC2_KEY_GEN: name="RC2_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_RC2_ECB |
|
case CKM_RC2_ECB: name="RC2_ECB"; break; |
|
#endif |
|
#ifdef CKM_RC2_CBC |
|
case CKM_RC2_CBC: name="RC2_CBC"; break; |
|
#endif |
|
#ifdef CKM_RC2_MAC |
|
case CKM_RC2_MAC: name="RC2_MAC"; break; |
|
#endif |
|
#ifdef CKM_RC2_MAC_GENERAL |
|
case CKM_RC2_MAC_GENERAL: name="RC2_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_RC2_CBC_PAD |
|
case CKM_RC2_CBC_PAD: name="RC2_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_RC4_KEY_GEN |
|
case CKM_RC4_KEY_GEN: name="RC4_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_RC4 |
|
case CKM_RC4: name="RC4"; break; |
|
#endif |
|
#ifdef CKM_DES_KEY_GEN |
|
case CKM_DES_KEY_GEN: name="DES_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_DES_ECB |
|
case CKM_DES_ECB: name="DES_ECB"; break; |
|
#endif |
|
#ifdef CKM_DES_CBC |
|
case CKM_DES_CBC: name="DES_CBC"; break; |
|
#endif |
|
#ifdef CKM_DES_MAC |
|
case CKM_DES_MAC: name="DES_MAC"; break; |
|
#endif |
|
#ifdef CKM_DES_MAC_GENERAL |
|
case CKM_DES_MAC_GENERAL: name="DES_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_DES_CBC_PAD |
|
case CKM_DES_CBC_PAD: name="DES_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_DES2_KEY_GEN |
|
case CKM_DES2_KEY_GEN: name="DES2_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_DES3_KEY_GEN |
|
case CKM_DES3_KEY_GEN: name="DES3_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_DES3_ECB |
|
case CKM_DES3_ECB: name="DES3_ECB"; break; |
|
#endif |
|
#ifdef CKM_DES3_CBC |
|
case CKM_DES3_CBC: name="DES3_CBC"; break; |
|
#endif |
|
#ifdef CKM_DES3_MAC |
|
case CKM_DES3_MAC: name="DES3_MAC"; break; |
|
#endif |
|
#ifdef CKM_DES3_MAC_GENERAL |
|
case CKM_DES3_MAC_GENERAL: name="DES3_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_DES3_CBC_PAD |
|
case CKM_DES3_CBC_PAD: name="DES3_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_CDMF_KEY_GEN |
|
case CKM_CDMF_KEY_GEN: name="CDMF_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CDMF_ECB |
|
case CKM_CDMF_ECB: name="CDMF_ECB"; break; |
|
#endif |
|
#ifdef CKM_CDMF_CBC |
|
case CKM_CDMF_CBC: name="CDMF_CBC"; break; |
|
#endif |
|
#ifdef CKM_CDMF_MAC |
|
case CKM_CDMF_MAC: name="CDMF_MAC"; break; |
|
#endif |
|
#ifdef CKM_CDMF_MAC_GENERAL |
|
case CKM_CDMF_MAC_GENERAL: name="CDMF_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CDMF_CBC_PAD |
|
case CKM_CDMF_CBC_PAD: name="CDMF_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_MD2 |
|
case CKM_MD2: name="MD2"; break; |
|
#endif |
|
#ifdef CKM_MD2_HMAC |
|
case CKM_MD2_HMAC: name="MD2_HMAC"; break; |
|
#endif |
|
#ifdef CKM_MD2_HMAC_GENERAL |
|
case CKM_MD2_HMAC_GENERAL: name="MD2_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_MD5 |
|
case CKM_MD5: name="MD5"; break; |
|
#endif |
|
#ifdef CKM_MD5_HMAC |
|
case CKM_MD5_HMAC: name="MD5_HMAC"; break; |
|
#endif |
|
#ifdef CKM_MD5_HMAC_GENERAL |
|
case CKM_MD5_HMAC_GENERAL: name="MD5_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_SHA_1 |
|
case CKM_SHA_1: name="SHA_1"; break; |
|
#endif |
|
#ifdef CKM_SHA_1_HMAC |
|
case CKM_SHA_1_HMAC: name="SHA_1_HMAC"; break; |
|
#endif |
|
#ifdef CKM_SHA_1_HMAC_GENERAL |
|
case CKM_SHA_1_HMAC_GENERAL: name="SHA_1_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD128 |
|
case CKM_RIPEMD128: name="RIPEMD128"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD128_HMAC |
|
case CKM_RIPEMD128_HMAC: name="RIPEMD128_HMAC"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD128_HMAC_GENERAL |
|
case CKM_RIPEMD128_HMAC_GENERAL: name="RIPEMD128_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD160 |
|
case CKM_RIPEMD160: name="RIPEMD160"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD160_HMAC |
|
case CKM_RIPEMD160_HMAC: name="RIPEMD160_HMAC"; break; |
|
#endif |
|
#ifdef CKM_RIPEMD160_HMAC_GENERAL |
|
case CKM_RIPEMD160_HMAC_GENERAL: name="RIPEMD160_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_SHA256 |
|
case CKM_SHA256: name="SHA256"; break; |
|
#endif |
|
#ifdef CKM_SHA256_HMAC |
|
case CKM_SHA256_HMAC: name="SHA256_HMAC"; break; |
|
#endif |
|
#ifdef CKM_SHA256_HMAC_GENERAL |
|
case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_SHA384 |
|
case CKM_SHA384: name="SHA384"; break; |
|
#endif |
|
#ifdef CKM_SHA384_HMAC |
|
case CKM_SHA384_HMAC: name="SHA384_HMAC"; break; |
|
#endif |
|
#ifdef CKM_SHA384_HMAC_GENERAL |
|
case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_SHA512 |
|
case CKM_SHA512: name="SHA512"; break; |
|
#endif |
|
#ifdef CKM_SHA512_HMAC |
|
case CKM_SHA512_HMAC: name="SHA512_HMAC"; break; |
|
#endif |
|
#ifdef CKM_SHA512_HMAC_GENERAL |
|
case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CAST_KEY_GEN |
|
case CKM_CAST_KEY_GEN: name="CAST_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CAST_ECB |
|
case CKM_CAST_ECB: name="CAST_ECB"; break; |
|
#endif |
|
#ifdef CKM_CAST_CBC |
|
case CKM_CAST_CBC: name="CAST_CBC"; break; |
|
#endif |
|
#ifdef CKM_CAST_MAC |
|
case CKM_CAST_MAC: name="CAST_MAC"; break; |
|
#endif |
|
#ifdef CKM_CAST_MAC_GENERAL |
|
case CKM_CAST_MAC_GENERAL: name="CAST_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CAST_CBC_PAD |
|
case CKM_CAST_CBC_PAD: name="CAST_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_CAST3_KEY_GEN |
|
case CKM_CAST3_KEY_GEN: name="CAST3_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CAST3_ECB |
|
case CKM_CAST3_ECB: name="CAST3_ECB"; break; |
|
#endif |
|
#ifdef CKM_CAST3_CBC |
|
case CKM_CAST3_CBC: name="CAST3_CBC"; break; |
|
#endif |
|
#ifdef CKM_CAST3_MAC |
|
case CKM_CAST3_MAC: name="CAST3_MAC"; break; |
|
#endif |
|
#ifdef CKM_CAST3_MAC_GENERAL |
|
case CKM_CAST3_MAC_GENERAL: name="CAST3_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CAST3_CBC_PAD |
|
case CKM_CAST3_CBC_PAD: name="CAST3_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_CAST5_KEY_GEN |
|
case CKM_CAST5_KEY_GEN: name="CAST5_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CAST128_KEY_GEN |
|
//case CKM_CAST128_KEY_GEN: name="CAST5_KEY_GEN or |
|
//CAST128_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CAST5_ECB |
|
case CKM_CAST5_ECB: name="CAST5_ECB"; break; |
|
#endif |
|
#ifdef CKM_CAST128_ECB |
|
//case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break; |
|
#endif |
|
#ifdef CKM_CAST5_CBC |
|
case CKM_CAST5_CBC: name="CAST5_CBC"; break; |
|
#endif |
|
#ifdef CKM_CAST128_CBC |
|
//case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break; |
|
#endif |
|
#ifdef CKM_CAST5_MAC |
|
case CKM_CAST5_MAC: name="CAST5_MAC"; break; |
|
#endif |
|
#ifdef CKM_CAST128_MAC |
|
//case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break; |
|
#endif |
|
#ifdef CKM_CAST5_MAC_GENERAL |
|
case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CAST128_MAC_GENERAL |
|
//case CKM_CAST128_MAC_GENERAL: name="CAST5_MAC_GENERAL or |
|
//CAST128_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_CAST5_CBC_PAD |
|
case CKM_CAST5_CBC_PAD: name="CAST5_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_CAST128_CBC_PAD |
|
//case CKM_CAST128_CBC_PAD: name="CAST5_CBC_PAD or |
|
//CAST128_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_RC5_KEY_GEN |
|
case CKM_RC5_KEY_GEN: name="RC5_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_RC5_ECB |
|
case CKM_RC5_ECB: name="RC5_ECB"; break; |
|
#endif |
|
#ifdef CKM_RC5_CBC |
|
case CKM_RC5_CBC: name="RC5_CBC"; break; |
|
#endif |
|
#ifdef CKM_RC5_MAC |
|
case CKM_RC5_MAC: name="RC5_MAC"; break; |
|
#endif |
|
#ifdef CKM_RC5_MAC_GENERAL |
|
case CKM_RC5_MAC_GENERAL: name="RC5_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_RC5_CBC_PAD |
|
case CKM_RC5_CBC_PAD: name="RC5_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_IDEA_KEY_GEN |
|
case CKM_IDEA_KEY_GEN: name="IDEA_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_IDEA_ECB |
|
case CKM_IDEA_ECB: name="IDEA_ECB"; break; |
|
#endif |
|
#ifdef CKM_IDEA_CBC |
|
case CKM_IDEA_CBC: name="IDEA_CBC"; break; |
|
#endif |
|
#ifdef CKM_IDEA_MAC |
|
case CKM_IDEA_MAC: name="IDEA_MAC"; break; |
|
#endif |
|
#ifdef CKM_IDEA_MAC_GENERAL |
|
case CKM_IDEA_MAC_GENERAL: name="IDEA_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_IDEA_CBC_PAD |
|
case CKM_IDEA_CBC_PAD: name="IDEA_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_GENERIC_SECRET_KEY_GEN |
|
case CKM_GENERIC_SECRET_KEY_GEN: name="GENERIC_SECRET_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_CONCATENATE_BASE_AND_KEY |
|
case CKM_CONCATENATE_BASE_AND_KEY: |
|
name="CONCATENATE_BASE_AND_KEY"; break; |
|
#endif |
|
#ifdef CKM_CONCATENATE_BASE_AND_DATA |
|
case CKM_CONCATENATE_BASE_AND_DATA: |
|
name="CONCATENATE_BASE_AND_DATA"; break; |
|
#endif |
|
#ifdef CKM_CONCATENATE_DATA_AND_BASE |
|
case CKM_CONCATENATE_DATA_AND_BASE: |
|
name="CONCATENATE_DATA_AND_BASE"; break; |
|
#endif |
|
#ifdef CKM_XOR_BASE_AND_DATA |
|
case CKM_XOR_BASE_AND_DATA: name="XOR_BASE_AND_DATA"; break; |
|
#endif |
|
#ifdef CKM_EXTRACT_KEY_FROM_KEY |
|
case CKM_EXTRACT_KEY_FROM_KEY: name="EXTRACT_KEY_FROM_KEY"; break; |
|
#endif |
|
#ifdef CKM_SSL3_PRE_MASTER_KEY_GEN |
|
case CKM_SSL3_PRE_MASTER_KEY_GEN: |
|
name="SSL3_PRE_MASTER_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_SSL3_MASTER_KEY_DERIVE |
|
case CKM_SSL3_MASTER_KEY_DERIVE: name="SSL3_MASTER_KEY_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_SSL3_KEY_AND_MAC_DERIVE |
|
case CKM_SSL3_KEY_AND_MAC_DERIVE: |
|
name="SSL3_KEY_AND_MAC_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_SSL3_MASTER_KEY_DERIVE_DH |
|
case CKM_SSL3_MASTER_KEY_DERIVE_DH: |
|
name="SSL3_MASTER_KEY_DERIVE_DH"; break; |
|
#endif |
|
#ifdef CKM_TLS_PRE_MASTER_KEY_GEN |
|
case CKM_TLS_PRE_MASTER_KEY_GEN: name="TLS_PRE_MASTER_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_TLS_MASTER_KEY_DERIVE |
|
case CKM_TLS_MASTER_KEY_DERIVE: name="TLS_MASTER_KEY_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_TLS_KEY_AND_MAC_DERIVE |
|
case CKM_TLS_KEY_AND_MAC_DERIVE: name="TLS_KEY_AND_MAC_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_TLS_MASTER_KEY_DERIVE_DH |
|
case CKM_TLS_MASTER_KEY_DERIVE_DH: |
|
name="TLS_MASTER_KEY_DERIVE_DH"; break; |
|
#endif |
|
#ifdef CKM_SSL3_MD5_MAC |
|
case CKM_SSL3_MD5_MAC: name="SSL3_MD5_MAC"; break; |
|
#endif |
|
#ifdef CKM_SSL3_SHA1_MAC |
|
case CKM_SSL3_SHA1_MAC: name="SSL3_SHA1_MAC"; break; |
|
#endif |
|
#ifdef CKM_MD5_KEY_DERIVATION |
|
case CKM_MD5_KEY_DERIVATION: name="MD5_KEY_DERIVATION"; break; |
|
#endif |
|
#ifdef CKM_MD2_KEY_DERIVATION |
|
case CKM_MD2_KEY_DERIVATION: name="MD2_KEY_DERIVATION"; break; |
|
#endif |
|
#ifdef CKM_SHA1_KEY_DERIVATION |
|
case CKM_SHA1_KEY_DERIVATION: name="SHA1_KEY_DERIVATION"; break; |
|
#endif |
|
#ifdef CKM_SHA256_KEY_DERIVATION |
|
case CKM_SHA256_KEY_DERIVATION: name="SHA256_KEY_DERIVATION"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD2_DES_CBC |
|
case CKM_PBE_MD2_DES_CBC: name="PBE_MD2_DES_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD5_DES_CBC |
|
case CKM_PBE_MD5_DES_CBC: name="PBE_MD5_DES_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD5_CAST_CBC |
|
case CKM_PBE_MD5_CAST_CBC: name="PBE_MD5_CAST_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD5_CAST3_CBC |
|
case CKM_PBE_MD5_CAST3_CBC: name="PBE_MD5_CAST3_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD5_CAST5_CBC |
|
case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_MD5_CAST128_CBC |
|
//case CKM_PBE_MD5_CAST128_CBC: name="PBE_MD5_CAST5_CBC or |
|
//PBE_MD5_CAST128_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_CAST5_CBC |
|
case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_CAST128_CBC |
|
//case CKM_PBE_SHA1_CAST128_CBC: name="PBE_SHA1_CAST5_CBC or |
|
//PBE_SHA1_CAST128_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_RC4_128 |
|
case CKM_PBE_SHA1_RC4_128: name="PBE_SHA1_RC4_128"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_RC4_40 |
|
case CKM_PBE_SHA1_RC4_40: name="PBE_SHA1_RC4_40"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_DES3_EDE_CBC |
|
case CKM_PBE_SHA1_DES3_EDE_CBC: name="PBE_SHA1_DES3_EDE_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_DES2_EDE_CBC |
|
case CKM_PBE_SHA1_DES2_EDE_CBC: name="PBE_SHA1_DES2_EDE_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_RC2_128_CBC |
|
case CKM_PBE_SHA1_RC2_128_CBC: name="PBE_SHA1_RC2_128_CBC"; break; |
|
#endif |
|
#ifdef CKM_PBE_SHA1_RC2_40_CBC |
|
case CKM_PBE_SHA1_RC2_40_CBC: name="PBE_SHA1_RC2_40_CBC"; break; |
|
#endif |
|
#ifdef CKM_PKCS5_PBKD2 |
|
case CKM_PKCS5_PBKD2: name="PKCS5_PBKD2"; break; |
|
#endif |
|
#ifdef CKM_PBA_SHA1_WITH_SHA1_HMAC |
|
case CKM_PBA_SHA1_WITH_SHA1_HMAC: |
|
name="PBA_SHA1_WITH_SHA1_HMAC"; break; |
|
#endif |
|
#ifdef CKM_KEY_WRAP_LYNKS |
|
case CKM_KEY_WRAP_LYNKS: name="KEY_WRAP_LYNKS"; break; |
|
#endif |
|
#ifdef CKM_KEY_WRAP_SET_OAEP |
|
case CKM_KEY_WRAP_SET_OAEP: name="KEY_WRAP_SET_OAEP"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_KEY_GEN |
|
case CKM_SKIPJACK_KEY_GEN: name="SKIPJACK_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_ECB64 |
|
case CKM_SKIPJACK_ECB64: name="SKIPJACK_ECB64"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_CBC64 |
|
case CKM_SKIPJACK_CBC64: name="SKIPJACK_CBC64"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_OFB64 |
|
case CKM_SKIPJACK_OFB64: name="SKIPJACK_OFB64"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_CFB64 |
|
case CKM_SKIPJACK_CFB64: name="SKIPJACK_CFB64"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_CFB32 |
|
case CKM_SKIPJACK_CFB32: name="SKIPJACK_CFB32"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_CFB16 |
|
case CKM_SKIPJACK_CFB16: name="SKIPJACK_CFB16"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_CFB8 |
|
case CKM_SKIPJACK_CFB8: name="SKIPJACK_CFB8"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_WRAP |
|
case CKM_SKIPJACK_WRAP: name="SKIPJACK_WRAP"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_PRIVATE_WRAP |
|
case CKM_SKIPJACK_PRIVATE_WRAP: name="SKIPJACK_PRIVATE_WRAP"; break; |
|
#endif |
|
#ifdef CKM_SKIPJACK_RELAYX |
|
case CKM_SKIPJACK_RELAYX: name="SKIPJACK_RELAYX"; break; |
|
#endif |
|
#ifdef CKM_KEA_KEY_PAIR_GEN |
|
case CKM_KEA_KEY_PAIR_GEN: name="KEA_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_KEA_KEY_DERIVE |
|
case CKM_KEA_KEY_DERIVE: name="KEA_KEY_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_FORTEZZA_TIMESTAMP |
|
case CKM_FORTEZZA_TIMESTAMP: name="FORTEZZA_TIMESTAMP"; break; |
|
#endif |
|
#ifdef CKM_BATON_KEY_GEN |
|
case CKM_BATON_KEY_GEN: name="BATON_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_BATON_ECB128 |
|
case CKM_BATON_ECB128: name="BATON_ECB128"; break; |
|
#endif |
|
#ifdef CKM_BATON_ECB96 |
|
case CKM_BATON_ECB96: name="BATON_ECB96"; break; |
|
#endif |
|
#ifdef CKM_BATON_CBC128 |
|
case CKM_BATON_CBC128: name="BATON_CBC128"; break; |
|
#endif |
|
#ifdef CKM_BATON_COUNTER |
|
case CKM_BATON_COUNTER: name="BATON_COUNTER"; break; |
|
#endif |
|
#ifdef CKM_BATON_SHUFFLE |
|
case CKM_BATON_SHUFFLE: name="BATON_SHUFFLE"; break; |
|
#endif |
|
#ifdef CKM_BATON_WRAP |
|
case CKM_BATON_WRAP: name="BATON_WRAP"; break; |
|
#endif |
|
#ifdef CKM_ECDSA_KEY_PAIR_GEN |
|
case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_EC_KEY_PAIR_GEN |
|
//case CKM_EC_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN or |
|
//EC_KEY_PAIR_GEN"; break; |
|
#endif |
|
#ifdef CKM_ECDSA |
|
case CKM_ECDSA: name="ECDSA"; break; |
|
#endif |
|
#ifdef CKM_ECDSA_SHA1 |
|
case CKM_ECDSA_SHA1: name="ECDSA_SHA1"; break; |
|
#endif |
|
#ifdef CKM_ECDH1_DERIVE |
|
case CKM_ECDH1_DERIVE: name="ECDH1_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_ECDH1_COFACTOR_DERIVE |
|
case CKM_ECDH1_COFACTOR_DERIVE: name="ECDH1_COFACTOR_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_ECMQV_DERIVE |
|
case CKM_ECMQV_DERIVE: name="ECMQV_DERIVE"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_KEY_GEN |
|
case CKM_JUNIPER_KEY_GEN: name="JUNIPER_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_ECB128 |
|
case CKM_JUNIPER_ECB128: name="JUNIPER_ECB128"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_CBC128 |
|
case CKM_JUNIPER_CBC128: name="JUNIPER_CBC128"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_COUNTER |
|
case CKM_JUNIPER_COUNTER: name="JUNIPER_COUNTER"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_SHUFFLE |
|
case CKM_JUNIPER_SHUFFLE: name="JUNIPER_SHUFFLE"; break; |
|
#endif |
|
#ifdef CKM_JUNIPER_WRAP |
|
case CKM_JUNIPER_WRAP: name="JUNIPER_WRAP"; break; |
|
#endif |
|
#ifdef CKM_FASTHASH |
|
case CKM_FASTHASH: name="FASTHASH"; break; |
|
#endif |
|
#ifdef CKM_AES_KEY_GEN |
|
case CKM_AES_KEY_GEN: name="AES_KEY_GEN"; break; |
|
#endif |
|
#ifdef CKM_AES_ECB |
|
case CKM_AES_ECB: name="AES_ECB"; break; |
|
#endif |
|
#ifdef CKM_AES_CBC |
|
case CKM_AES_CBC: name="AES_CBC"; break; |
|
#endif |
|
#ifdef CKM_AES_MAC |
|
case CKM_AES_MAC: name="AES_MAC"; break; |
|
#endif |
|
#ifdef CKM_AES_MAC_GENERAL |
|
case CKM_AES_MAC_GENERAL: name="AES_MAC_GENERAL"; break; |
|
#endif |
|
#ifdef CKM_AES_CBC_PAD |
|
case CKM_AES_CBC_PAD: name="AES_CBC_PAD"; break; |
|
#endif |
|
#ifdef CKM_DSA_PARAMETER_GEN |
|
case CKM_DSA_PARAMETER_GEN: name="DSA_PARAMETER_GEN"; break; |
|
#endif |
|
#ifdef CKM_DH_PKCS_PARAMETER_GEN |
|
case CKM_DH_PKCS_PARAMETER_GEN: name="DH_PKCS_PARAMETER_GEN"; break; |
|
#endif |
|
#ifdef CKM_X9_42_DH_PARAMETER_GEN |
|
case CKM_X9_42_DH_PARAMETER_GEN: name="X9_42_DH_PARAMETER_GEN"; break; |
|
#endif |
|
#ifdef CKM_VENDOR_DEFINED |
|
case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break; |
|
#endif |
|
default: { |
|
std::stringstream ss; |
|
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; |
|
CK_FLAGS flags; |
|
CK_VERSION hardwareVersion; |
|
CK_VERSION firmwareVersion; |
|
|
|
SlotInfo() { |
|
} |
|
|
|
//! Convert C-Structure of Slot Information Into C++ |
|
SlotInfo(const CK_SLOT_INFO& cInfo): |
|
slotDescription(cInfo.slotDescription), |
|
manufacturerID(cInfo.manufacturerID), |
|
flags(cInfo.flags), |
|
hardwareVersion(cInfo.hardwareVersion), |
|
firmwareVersion(cInfo.firmwareVersion) { |
|
} |
|
}; |
|
|
|
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; |
|
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; |
|
|
|
TokenInfo() { |
|
CRYPTOLOG("log"); |
|
} |
|
|
|
//! Convert C-Structure of Token Information Into C++ |
|
TokenInfo(const CK_TOKEN_INFO& cInfo): |
|
label(cInfo.label), |
|
manufacturerID(cInfo.manufacturerID), |
|
model(cInfo.model), |
|
serialNumber(cInfo.serialNumber), |
|
flags(cInfo.flags), |
|
maxSessionCount(cInfo.ulMaxSessionCount), |
|
sessionCount(cInfo.ulSessionCount), |
|
maxRwSessionCount(cInfo.ulMaxRwSessionCount), |
|
rwSessionCount(cInfo.ulRwSessionCount), |
|
maxPinLen(cInfo.ulMaxPinLen), |
|
minPinLen(cInfo.ulMinPinLen), |
|
totalPublicMemory(cInfo.ulTotalPublicMemory), |
|
freePublicMemory(cInfo.ulFreePublicMemory), |
|
totalPrivateMemory(cInfo.ulTotalPrivateMemory), |
|
freePrivateMemory(cInfo.ulFreePrivateMemory), |
|
hardwareVersion(cInfo.hardwareVersion), |
|
firmwareVersion(cInfo.firmwareVersion), |
|
utcTime(cInfo.utcTime) { |
|
CRYPTOLOG("log *this={"<<*this<<'}'); |
|
} |
|
|
|
}; |
|
|
|
/// Textual representation for token information. |
|
inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti) { |
|
return out |
|
<<"label="<<ti.label<<std::endl |
|
<<"manufacturerID="<<ti.manufacturerID<<std::endl |
|
<<"model="<<ti.model<<std::endl |
|
<<"serialNumber="<<ti.serialNumber<<std::endl |
|
<<"flags="<<ti.flags<<std::endl |
|
<<"maxSessionCount="<<ti.maxSessionCount<<std::endl |
|
<<"sessionCount="<<ti.sessionCount<<std::endl |
|
<<"maxRwSessionCount="<<ti.maxRwSessionCount<<std::endl |
|
<<"rwSessionCount="<<ti.rwSessionCount<<std::endl |
|
<<"maxPinLen="<<ti.maxPinLen<<std::endl |
|
<<"minPinLen="<<ti.minPinLen<<std::endl |
|
<<"totalPublicMemory="<<ti.totalPublicMemory<<std::endl |
|
<<"freePublicMemory="<<ti.freePublicMemory<<std::endl |
|
<<"totalPrivateMemory="<<ti.totalPrivateMemory<<std::endl |
|
<<"freePrivateMemory="<<ti.freePrivateMemory<<std::endl |
|
<<"hardwareVersion="<<ti.hardwareVersion.major<<'.' |
|
<<ti.hardwareVersion.minor<<std::endl |
|
<<"firmwareVersion="<<ti.firmwareVersion.major<<'.' |
|
<<ti.firmwareVersion.minor<<std::endl |
|
<<"utcTime="<<ti.utcTime; |
|
} |
|
|
|
/// Handle library information. |
|
struct Info { |
|
CK_VERSION cryptokiVersion; |
|
FixString<32> manufacturerID; |
|
CK_FLAGS flags; |
|
FixString<32> libraryDescription; |
|
CK_VERSION libraryVersion; |
|
}; |
|
|
|
//@} |
|
|
|
/*! @addtogroup cryptokilib */ |
|
//@{ |
|
|
|
/// 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 |
|
/*! @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 exceptions whether exceptions should be thrown */ |
|
Library(const std::string& library, bool exceptions=true): |
|
_init(new Init(library, exceptions)) { |
|
CRYPTOLOG("log"); |
|
} |
|
|
|
protected: |
|
|
|
Library() { |
|
CRYPTOLOG("log"); |
|
} |
|
|
|
private: |
|
|
|
/// Initiatlize the library: load and unload the shared object. |
|
class Init { |
|
|
|
private: |
|
|
|
friend class Library; |
|
|
|
bool _exc; |
|
CK_RV _res; |
|
CK_FUNCTION_LIST* _fn; |
|
#ifndef WIN32 |
|
void* _lib; |
|
#else |
|
HINSTANCE _lib; |
|
#endif |
|
|
|
//! 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: |
|
|
|
/// Called from Library::Library |
|
Init(const std::string& library="opensc-pkcs11.so", bool exc=true); |
|
|
|
~Init(); |
|
|
|
Init& reset() { |
|
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize")); |
|
check(_fn->C_Initialize(0), CRYPTOKI_FN_LOG("C_Initialize")); |
|
return *this; |
|
} |
|
|
|
CK_FUNCTION_LIST* fn() { |
|
return _fn; |
|
} |
|
|
|
/*! @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(); |
|
|
|
//@} |
|
|
|
}; |
|
|
|
public: |
|
|
|
/// Get pointer to cryptoki API functions. |
|
/** Used internally, normally you shouldn't use this directly. */ |
|
CK_FUNCTION_LIST* operator->() { |
|
return _init->fn(); |
|
} |
|
|
|
/*! @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 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; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
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; |
|
CK_INFO cInf; |
|
//! calls @c C_GetInfo |
|
if (!_init->check(_init->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 |
|
@param name if given, only return slots with a given name |
|
@return list of matching slots */ |
|
SlotList slotList(bool tokenPresent=true, |
|
std::string name=std::string()); |
|
|
|
private: |
|
|
|
std::shared_ptr<Init> _init; |
|
|
|
}; |
|
|
|
//! Slot and Token Management |
|
class Slot { |
|
private: |
|
|
|
friend class Library; |
|
friend class Session; |
|
friend class Object; |
|
|
|
Library _library; |
|
CK_SLOT_ID _slot; |
|
CK_RV _res; |
|
|
|
public: |
|
|
|
Slot(const Slot& o): |
|
_library(o._library), _slot(o._slot), _res(o._res) { |
|
CRYPTOLOG("ID="<<_slot); |
|
} |
|
|
|
/// Slots are created from Library::slotList. |
|
/** @note Empty constructor needs immediate assignment. This |
|
constructor is public only to be inserted to STL |
|
containers. */ |
|
Slot(): _slot(0), _res(-1) { |
|
CRYPTOLOG("ID="<<_slot); |
|
} |
|
|
|
Slot& operator=(const Slot& o) { |
|
_library = o._library; |
|
_slot = o._slot; |
|
_res = o._res; |
|
CRYPTOLOG("ID="<<_slot); |
|
return *this; |
|
} |
|
|
|
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); |
|
} |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
_res = result; |
|
if (_library.exc() && !*this) { |
|
if (!context.empty()) { |
|
throw access_error(context+": "+error()); |
|
} else { |
|
throw access_error(error()); |
|
} |
|
} |
|
return _res==CKR_OK; |
|
} |
|
|
|
public: |
|
|
|
/*! @name C Like Error Handling |
|
|
|
You are strongly recommended not to disable exception |
|
handling. If you disable it, you must check after every |
|
operation whether it was successful or not. These methods |
|
provide all you need for that. */ |
|
//@{ |
|
|
|
/*! @return @c true if last cryptoki on this object call was successful */ |
|
operator bool() { |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
return _library.error(_res); |
|
} |
|
|
|
//@} |
|
|
|
/// 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"); |
|
CK_MECHANISM_INFO info; |
|
//! calls @c C_GetMechanismInfo |
|
check(_library->C_GetMechanismInfo(_slot, mechanism, &info), |
|
CRYPTOKI_FN_LOG("C_GetMechanismInfo")); |
|
return MechanismInfo(mechanism, info); |
|
} |
|
|
|
/// Get a list of the Slot's mechanisms. |
|
MechanismList mechanismlist() { |
|
CRYPTOLOG("log"); |
|
MechanismList res; |
|
CK_ULONG count(0); |
|
//! calls @c C_GetMechanismList |
|
if (!check(_library->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(_library->C_GetMechanismList(_slot, mechanisms, &count), |
|
CRYPTOKI_FN_LOG("C_GetMechanismList"))) { |
|
delete[] mechanisms; |
|
return res; |
|
} |
|
for (CK_ULONG i(0); i<count; ++i) |
|
res.insert(mechanisminfo(mechanisms[i])); |
|
} catch (...) { |
|
delete[] mechanisms; |
|
throw; |
|
} |
|
delete[] mechanisms; |
|
return res; |
|
} |
|
|
|
//! Read Slot Information |
|
SlotInfo slotinfo() { |
|
CRYPTOLOG("log"); |
|
CK_SLOT_INFO cInfo; |
|
//! calls @c C_GetSlotInfo |
|
if (!check(_library->C_GetSlotInfo(_slot, &cInfo), |
|
CRYPTOKI_FN_LOG("C_GetSlotInfo"))) |
|
return SlotInfo(); |
|
return SlotInfo(cInfo); |
|
} |
|
|
|
//! Read Token Information |
|
TokenInfo tokeninfo() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GetTokenInfo |
|
CK_TOKEN_INFO cInfo; |
|
if (!check(_library->C_GetTokenInfo(_slot, &cInfo), |
|
CRYPTOKI_FN_LOG("C_GetTokenInfo"))) |
|
return TokenInfo(); |
|
return TokenInfo(cInfo); |
|
} |
|
|
|
/// 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 |
|
std::string in(label); |
|
in.resize(32, ' '); |
|
if (pin.size()) |
|
return check(_library->C_InitToken |
|
(_slot, |
|
(unsigned char*)&pin[0], pin.size(), |
|
(unsigned char*)&in[0]), |
|
CRYPTOKI_FN_LOG("C_InitToken")); |
|
else |
|
return check(_library->C_InitToken |
|
(_slot, |
|
0, 0, // pin from external pin pad |
|
(unsigned char*)&in[0]), |
|
CRYPTOKI_FN_LOG("C_InitToken")); |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
class SlotEventListener { |
|
public: virtual void slotEvent() = 0; |
|
} |
|
|
|
bool registerforslotevent(SlotEventListener&) { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_WaitForSlotEvent |
|
return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, 0), |
|
CRYPTOKI_FN_LOG("C_WaitForSlotEvent")); |
|
} |
|
@endcode */ |
|
}; |
|
|
|
/// Session Management |
|
/** @note Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); */ |
|
class Session { |
|
private: |
|
|
|
friend class Login; |
|
friend class Object; |
|
|
|
typedef std::multimap<CK_SLOT_ID, CK_SESSION_HANDLE> Slots; |
|
|
|
Slot _slot; |
|
CK_SESSION_HANDLE _session; |
|
CK_RV _res; |
|
|
|
static Slots& slots() { |
|
static Slots _slots; |
|
return _slots; |
|
} |
|
|
|
Session(); // forbidden |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
_res = result; |
|
if (_slot.library().exc() && !*this) { |
|
if (!context.empty()) { |
|
throw access_error(context+": "+error()); |
|
} else { |
|
throw access_error(error()); |
|
} |
|
} |
|
return _res==CKR_OK; |
|
} |
|
|
|
//! calls @c C_OpenSession if it's the first session |
|
void open(bool rw=false) { |
|
CRYPTOLOG("references: "<<slots().count(_slot._slot)); |
|
if (slots().count(_slot._slot)==0) { |
|
check(_slot.library()->C_OpenSession |
|
(_slot._slot, CKF_SERIAL_SESSION|(rw?CKF_RW_SESSION:0), |
|
0, 0, &_session), |
|
CRYPTOKI_FN_LOG("C_OpenSession")); |
|
} else { |
|
_session = slots().find(_slot._slot)->second; |
|
} |
|
slots().insert(std::make_pair(_slot._slot, _session)); |
|
} |
|
|
|
//! calls @c C_CloseSession if it's the last session |
|
void close() { |
|
CRYPTOLOG("references: "<<slots().count(_slot._slot)); |
|
if (slots().count(_slot._slot)==1) { |
|
slots().erase(slots().find(_slot._slot)); |
|
check(_slot.library()->C_CloseSession(_session), |
|
CRYPTOKI_FN_LOG("C_CloseSession")); |
|
} else { |
|
slots().erase(slots().find(_slot._slot)); |
|
} |
|
_session=0; |
|
} |
|
|
|
public: |
|
|
|
//! Opens a new session. |
|
/*! @param slot slot to open a session on |
|
@param rw whether session is read/write or read only*/ |
|
Session(const Slot& slot, bool rw=false): |
|
_slot(slot), _session(0), _res(CKR_OK) { |
|
CRYPTOLOG("log"); |
|
open(rw); |
|
//! @todo pass parameter |
|
} |
|
|
|
//! Copy session. |
|
Session(const Session& o): |
|
_slot(o._slot), _session(o._session), _res(CKR_OK) { |
|
CRYPTOLOG("log"); |
|
slots().insert(std::make_pair(_slot._slot, _session)); |
|
//! @todo pass parameter |
|
} |
|
|
|
~Session() try { |
|
CRYPTOLOG("log "<<(std::uncaught_exception()?"IN EXCEPTION":"")); |
|
try { |
|
logout(); |
|
} catch (const std::exception& x) { |
|
CRYPTOLOG("caught: "<<x.what()); |
|
close(); |
|
if (!std::uncaught_exception()) throw; |
|
} catch (...) { |
|
CRYPTOLOG("caught"); |
|
close(); |
|
if (!std::uncaught_exception()) throw; |
|
} |
|
close(); |
|
} catch (const std::exception& x) { |
|
CRYPTOLOG("caught: "<<x.what()); |
|
if (!std::uncaught_exception()) throw; |
|
} catch (...) { |
|
CRYPTOLOG("caught"); |
|
if (!std::uncaught_exception()) throw; |
|
} |
|
|
|
/*! @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() { |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
return _slot.library().error(_res); |
|
} |
|
|
|
//@} |
|
|
|
/*! @name Low Level Cryptoki Functions |
|
|
|
Direct access to the low level cryptoki API. Better use the |
|
comfort methods. */ |
|
//@{ |
|
|
|
bool cancel() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_CancelFunction |
|
return check(_slot.library()->C_CancelFunction(_session), |
|
CRYPTOKI_FN_LOG("C_CancelFunction")); |
|
} |
|
|
|
//! Create a new object. |
|
Object create(const AttributeList& attrs); |
|
|
|
std::string digest(std::string in) { |
|
CRYPTOLOG("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.library()->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) { |
|
CRYPTOLOG("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.library()->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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DigestFinal |
|
return check(_slot.library()->C_DigestFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_DigestFinal")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool digestinit() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DigestInit |
|
return check(_slot.library()->C_DigestInit(_session, CK_MECHANISM_PTR), |
|
CRYPTOKI_FN_LOG("C_DigestInit")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool digestupdate() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DigestUpdate |
|
return check(_slot.library()->C_DigestUpdate(_session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_DigestUpdate")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool findobjectsfinal() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_FindObjectsFinal |
|
return check(_slot.library()->C_FindObjectsFinal(_session), |
|
CRYPTOKI_FN_LOG("C_FindObjectsFinal")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool findobjectsinit() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_FindObjectsInit |
|
return check(_slot.library()->C_FindObjectsInit(_session, CK_ATTRIBUTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_FindObjectsInit")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool findobjects() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_FindObjects |
|
return check(_session->_slot.library()->C_FindObjects(_session, CK_OBJECT_HANDLE_PTR, CK_ULONG, |
|
CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_FindObjects")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool generaterandom() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GenerateRandom |
|
return check(_slot.library()->C_GenerateRandom(_session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_GenerateRandom")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool getfunctionstatus() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GetFunctionStatus |
|
return check(_slot.library()->C_GetFunctionStatus(_session), |
|
CRYPTOKI_FN_LOG("C_GetFunctionStatus")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool getoperationstate() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GetOperationState |
|
return check(_slot.library()->C_GetOperationState(_session, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_GetOperationState")); |
|
} |
|
@endcode */ |
|
|
|
/** definition of session info: |
|
|
|
@code |
|
struct CK_SESSION_INFO { |
|
CK_SLOT_ID slotID; |
|
CK_STATE state; |
|
CK_FLAGS flags; |
|
CK_ULONG ulDeviceError; |
|
}; |
|
@endcode |
|
|
|
where: |
|
- @c slotID ID of the slot that interfaces with the token |
|
- @c state The state of the session |
|
- @c 0 @c CKS_RO_PUBLIC_SESSION |
|
- @c 1 @c CKS_RO_USER_FUNCTIONS |
|
- @c 2 @c CKS_RW_PUBLIC_SESSION |
|
- @c 3 @c CKS_RW_USER_FUNCTIONS |
|
- @c 4 @c CKS_RW_SO_FUNCTIONS |
|
- @c flags Bit flags that define the type of session; the |
|
flags are defined as: |
|
- @c CKF_RW_SESSION |
|
- True if the session is read/write. |
|
- False if the session is read only. |
|
- @c CKF_SERIAL_SESSION Deprecated, always true. |
|
- @c ulDeviceError An error code defined by the |
|
cryptographic device. Used for errors not covered by |
|
Cryptoki. */ |
|
struct Info: public CK_SESSION_INFO { |
|
Info(const CK_SESSION_INFO& si): CK_SESSION_INFO(si) { |
|
} |
|
bool readonly() { |
|
return !readwrite(); |
|
} |
|
bool readwrite() { |
|
return flags|CKF_RW_SESSION; |
|
} |
|
std::string stateString() { |
|
switch (state) { |
|
case 0: return "CKS_RO_PUBLIC_SESSION"; |
|
case 1: return "CKS_RO_USER_FUNCTIONS"; |
|
case 2: return "CKS_RW_PUBLIC_SESSION "; |
|
case 3: return "CKS_RW_USER_FUNCTIONS"; |
|
case 4: return "CKS_RW_SO_FUNCTIONS"; |
|
default: return "<UNKNOWN>"; |
|
} |
|
} |
|
}; |
|
|
|
|
|
/** @return session information */ |
|
Info getsessioninfo() { |
|
CRYPTOLOG("log"); |
|
CK_SESSION_INFO info; |
|
//! calls @c C_GetSessionInfo |
|
check(_slot.library()->C_GetSessionInfo(_session, &info), |
|
CRYPTOKI_FN_LOG("C_GetSessionInfo")); |
|
return info; |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool seedrandom() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SeedRandom |
|
return check(_slot.library()->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_SeedRandom")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool setpin() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SetPIN |
|
return check(_slot.library()->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_SetPIN")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool initpin() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_InitPIN |
|
return check(_slot.library()->C_InitPIN(_session, CK_CHAR_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_InitPIN")); |
|
} |
|
@endcode */ |
|
|
|
//@} |
|
|
|
/** @name login with pin |
|
|
|
Unlock access with pin (login) and unlock after use (logout). */ |
|
//@{ |
|
|
|
private: |
|
|
|
class Login { |
|
|
|
public: |
|
|
|
Login(Session& session, |
|
const std::string& pin, |
|
CK_USER_TYPE userType=CKU_USER): _session(session) { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_Login |
|
try { |
|
_session.check(_session._slot.library()->C_Login |
|
(_session._session, userType, |
|
const_cast<CK_CHAR*>((const CK_CHAR*)pin.c_str()), |
|
(int)pin.size()), |
|
CRYPTOKI_FN_LOG("C_Login")); |
|
} catch (std::exception& x) { |
|
throw wrong_pin(x.what()); |
|
} |
|
} |
|
|
|
~Login() { |
|
try { |
|
//! calls @c C_Logout |
|
_session.check(_session._slot.library()->C_Logout |
|
(_session._session), |
|
CRYPTOKI_FN_LOG("C_Logout")); |
|
} catch (const std::exception& x) { |
|
if (!std::uncaught_exception()) throw; |
|
CRYPTOLOG("ERROR during error cleanup: "<<x.what()); |
|
} catch (...) { |
|
if (!std::uncaught_exception()) throw; |
|
CRYPTOLOG("ERROR during error cleanup."); |
|
} |
|
} |
|
|
|
private: |
|
|
|
Session& _session; |
|
|
|
}; |
|
|
|
public: |
|
|
|
/// Login to card |
|
/** @param pin to unlock card |
|
@param userType user type */ |
|
void login(const std::string& pin, |
|
CK_USER_TYPE userType=CKU_USER) { |
|
CRYPTOLOG("log"); |
|
_login = std::shared_ptr<Login>(new Login(*this, pin, userType)); |
|
} |
|
|
|
/// Logout from card |
|
/** Undo the last login. */ |
|
void logout() { |
|
CRYPTOLOG("log"); |
|
_login.reset(); |
|
} |
|
|
|
std::shared_ptr<Login> _login; |
|
|
|
//@} |
|
|
|
}; |
|
|
|
class Object { |
|
|
|
private: |
|
|
|
friend class Session; |
|
|
|
CK_OBJECT_HANDLE _object; |
|
Session _session; |
|
CK_RV _res; |
|
|
|
bool check(CK_RV result, const std::string& context="") { |
|
_res = result; |
|
if (_session._slot.library().exc() && !*this) { |
|
if (!context.empty()) { |
|
throw access_error(context+": "+error()); |
|
} else { |
|
throw access_error(error()); |
|
} |
|
} |
|
return _res==CKR_OK; |
|
} |
|
|
|
Object(); // forbidden |
|
|
|
Object(const Session& session, CK_OBJECT_HANDLE obj): |
|
_object(obj), _session(session), _res(CKR_OK) { |
|
CRYPTOLOG("log"); |
|
} |
|
|
|
public: |
|
|
|
/*! @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()) { |
|
CRYPTOLOG("log"); |
|
CRYPTOLOG("encryptinit"); |
|
encryptinit(type, param); |
|
CRYPTOLOG("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()) { |
|
CRYPTOLOG("log"); |
|
CRYPTOLOG("decryptinit"); |
|
decryptinit(type, param); |
|
CRYPTOLOG("decrypt"); |
|
return decrypt(data); |
|
//! @todo don't call decryptfinal()? |
|
} |
|
|
|
std::string sign(const std::string& data, CK_MECHANISM_TYPE type, |
|
const std::string& param=std::string()) { |
|
CRYPTOLOG("log"); |
|
CRYPTOLOG("signinit"); |
|
signinit(type, param); |
|
CRYPTOLOG("sign"); |
|
return sign(data); |
|
//! @todo don't call signfinal()? |
|
} |
|
|
|
bool verify(const std::string& data, const std::string& signature, |
|
CK_MECHANISM_TYPE type, |
|
const std::string& param=std::string()) { |
|
CRYPTOLOG("log"); |
|
CRYPTOLOG("verifyinit"); |
|
verifyinit(type, param); |
|
CRYPTOLOG("verify"); |
|
return verify(data, signature); |
|
//! @todo don't call verifyfinal()? |
|
} |
|
|
|
bool destroy() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DestroyObject |
|
return check(_session._slot.library()->C_DestroyObject |
|
(_session._session, _object), |
|
CRYPTOKI_FN_LOG("C_DestroyObject")); |
|
} |
|
|
|
//! Get a Single Attribute |
|
Attribute operator[](CK_ATTRIBUTE_TYPE a) { |
|
CRYPTOLOG("log"); |
|
return attribute(a); |
|
} |
|
|
|
//! Get a Single Attribute |
|
Attribute attribute(CK_ATTRIBUTE_TYPE a) { |
|
CRYPTOLOG("log"); |
|
Attribute res; |
|
CK_ATTRIBUTE attr; |
|
attr.type = a; |
|
attr.pValue = 0; |
|
attr.ulValueLen = 0; |
|
//! calls @c C_GetAttributeValue |
|
if (!check(_session._slot.library()->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.library()->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()) { |
|
CRYPTOLOG("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); |
|
} |
|
for (AttributeTypeList::const_iterator it(attrs.begin()); |
|
it!=attrs.end(); ++it) { |
|
CK_ATTRIBUTE attr; |
|
attr.type = *it; |
|
attr.pValue = 0; |
|
attr.ulValueLen = 0; |
|
try { |
|
//! calls @c C_GetAttributeValue |
|
if (_session._slot.library()->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.library()->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 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; |
|
} |
|
|
|
//@} |
|
|
|
/*! @name C Like Error Handling |
|
|
|
You are strongly recommended not to disable exception |
|
handling. If you disable it, you must check after every |
|
operation whether it was successful or not. These methods |
|
provide all you need for that. */ |
|
//@{ |
|
|
|
/*! @return @c true if last cryptoki on this object call was successful */ |
|
operator bool() { |
|
return _res==CKR_OK; |
|
} |
|
|
|
/*! @return error text of last cryptoki call */ |
|
std::string error() { |
|
return _session._slot.library().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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_CopyObject |
|
return check(_session._slot.library()->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) { |
|
CRYPTOLOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?¶m[0]:0, (CK_ULONG)param.size() |
|
}; |
|
CRYPTOLOG("decryptinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_DecryptInit |
|
return check(_session._slot.library()->C_DecryptInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_DecryptInit")); |
|
} |
|
|
|
//! requires decryptinit to be called before |
|
std::string decrypt(const std::string& in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
CK_ULONG size(0); // two calls, first to get minimum buffer length |
|
CRYPTOLOG("get size"); |
|
//! calls @c C_Decrypt |
|
check(_session._slot.library()->C_Decrypt |
|
(_session._session, |
|
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), |
|
in.size(), 0, &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOLOG("maximum size is "<<size<<"Bytes"); |
|
res.resize(size, 0); |
|
check(_session._slot.library()->C_Decrypt |
|
(_session._session, |
|
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), |
|
in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOLOG("exact size is "<<size<<"Bytes"); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string decryptdigestupdate(std::string in) { |
|
CRYPTOLOG("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.library()->C_DecryptDigestUpdate |
|
(_session._session, |
|
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate")); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
bool decryptfinal() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DecryptFinal |
|
return check(_session._slot.library()->C_DecryptFinal |
|
(_session._session, 0, 0), |
|
CRYPTOKI_FN_LOG("C_DecryptFinal")); |
|
//! @todo does this work? |
|
} |
|
|
|
std::string decryptupdate(std::string in) { |
|
CRYPTOLOG("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.library()->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) { |
|
CRYPTOLOG("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.library()->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; |
|
} |
|
|
|
|
|
std::string sign(std::string in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
CK_ULONG size(0); |
|
check(_session._slot.library()->C_Sign |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(),0, &size), |
|
CRYPTOKI_FN_LOG("C_Sign")); |
|
CRYPTOLOG("maximum size is "<<size<<"Bytes"); |
|
res.resize(size, 0); |
|
//! calls @c C_Sign |
|
check(_session._slot.library()->C_Sign |
|
(_session._session, |
|
(unsigned char*)&in[0], in.size(), |
|
(unsigned char*)&res[0], &size), |
|
CRYPTOKI_FN_LOG("C_Sign")); |
|
CRYPTOLOG("exact size is "<<size<<"Bytes"); |
|
res.resize(size); |
|
return res; |
|
} |
|
|
|
std::string signencryptupdate(std::string in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_SignEncryptUpdate |
|
check(_session._slot.library()->C_SignEncryptUpdate |
|
(_session._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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SignFinal |
|
return check(_slot.library()->C_SignFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_SignFinal")); |
|
} |
|
@endcode */ |
|
|
|
std::string signrecover(std::string in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_SignRecover |
|
check(_session._slot.library()->C_SignRecover |
|
(_session._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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SignUpdate |
|
return check(_session._slot.library()->C_SignUpdate(_session._session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_SignUpdate")); |
|
} |
|
@endcode */ |
|
|
|
bool verify(std::string data, std::string signature) { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_Verify |
|
return check(_session._slot.library()->C_Verify |
|
(_session._session, |
|
(unsigned char*)&data[0], data.size(), |
|
(unsigned char*)&signature[0], signature.size()), |
|
CRYPTOKI_FN_LOG("C_Verify")); |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool verifyfinal() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_VerifyFinal |
|
return check(_session._slot.library()->C_VerifyFinal(_session._session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_VerifyFinal")); |
|
} |
|
@endcode */ |
|
|
|
std::string verifyrecover(std::string in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
res.resize(in.size()); |
|
CK_ULONG size(res.size()); //! @todo check if size is ok |
|
//! calls @c C_VerifyRecover |
|
check(_session._slot.library()->C_VerifyRecover |
|
(_session._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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_VerifyUpdate |
|
return check(_session._slot.library()->C_VerifyUpdate(_session._session, CK_BYTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_VerifyUpdate")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool derivekey() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DeriveKey |
|
return check(_session._slot.library()->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 */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool digestkey() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_DigestKey |
|
return check(_session._slot.library()->C_DigestKey(_session._session, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_DigestKey")); |
|
} |
|
@endcode */ |
|
|
|
bool encryptinit(CK_MECHANISM_TYPE type, const std::string& param) { |
|
CRYPTOLOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?const_cast<CK_VOID_PTR>((const void*)¶m[0]):0, |
|
(CK_ULONG)param.size() |
|
}; |
|
CRYPTOLOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_EncryptInit |
|
return check(_session._slot.library()->C_EncryptInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_EncryptInit")); |
|
} |
|
|
|
std::string encrypt(const std::string& in) { |
|
CRYPTOLOG("log"); |
|
std::string res; |
|
CK_ULONG size(0); // two calls, first to get minimum buffer length |
|
CRYPTOLOG("get size"); |
|
//! calls @c C_Encrypt |
|
check(_session._slot.library()->C_Encrypt |
|
(_session._session, |
|
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), |
|
in.size(), 0, &size), |
|
CRYPTOKI_FN_LOG("C_Decrypt")); |
|
CRYPTOLOG("maximum size is "<<size<<"Bytes"); |
|
res.resize(size, 0); |
|
check(_session._slot.library()->C_Encrypt |
|
(_session._session, |
|
const_cast<CK_BYTE_PTR>((const 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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_EncryptFinal |
|
return check(_session._slot.library()->C_EncryptFinal(_session._session, CK_BYTE_PTR, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_EncryptFinal")); |
|
} |
|
@endcode */ |
|
|
|
std::string encryptupdate(std::string in) { |
|
CRYPTOLOG("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.library()->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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GenerateKey |
|
return check(_session._slot.library()->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() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GenerateKeyPair |
|
return check(_session._slot.library()->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 */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool getobjectsize() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_GetObjectSize |
|
return check(_session._slot.library()->C_GetObjectSize(_session._session, CK_OBJECT_HANDLE, CK_ULONG_PTR), |
|
CRYPTOKI_FN_LOG("C_GetObjectSize")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool setattributevalue() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SetAttributeValue |
|
return check(_session._slot.library()->C_SetAttributeValue(_session._session, CK_OBJECT_HANDLE, |
|
CK_ATTRIBUTE_PTR, CK_ULONG), |
|
CRYPTOKI_FN_LOG("C_SetAttributeValue")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool setoperationstate() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SetOperationState |
|
return check(_session._slot.library()->C_SetOperationState(_session._session, CK_BYTE_PTR, CK_ULONG, |
|
CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_SetOperationState")); |
|
} |
|
@endcode */ |
|
|
|
bool signinit(CK_MECHANISM_TYPE type, std::string param) { |
|
CRYPTOLOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?¶m[0]:0, (CK_ULONG)param.size() |
|
}; |
|
CRYPTOLOG("signinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_SignInit |
|
return check(_session._slot.library()->C_SignInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_SignInit")); |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool signrecoverinit() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_SignRecoverInit |
|
return check(_session._slot.library()->C_SignRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_SignRecoverInit")); |
|
} |
|
@endcode */ |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool unwrapkey() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_UnwrapKey |
|
return check(_session._slot.library()->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 */ |
|
|
|
bool verifyinit(CK_MECHANISM_TYPE type, std::string param) { |
|
CRYPTOLOG("log"); |
|
CK_MECHANISM mech = { |
|
type, param.size()?¶m[0]:0, (CK_ULONG)param.size() |
|
}; |
|
CRYPTOLOG("verifyinit: type="<<type<<"; mech=("<<mech.mechanism |
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); |
|
//! calls @c C_VerifyInit |
|
return check(_session._slot.library()->C_VerifyInit |
|
(_session._session, &mech, _object), |
|
CRYPTOKI_FN_LOG("C_VerifyInit")); |
|
} |
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool verifyrecoverinit() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_VerifyRecoverInit |
|
return check(_session._slot.library()->C_VerifyRecoverInit(_session._session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), |
|
CRYPTOKI_FN_LOG("C_VerifyRecoverInit")); |
|
} |
|
@endcode */ |
|
|
|
|
|
/*! @todo Not implemented: |
|
@code |
|
bool wrapkey() { |
|
CRYPTOLOG("log"); |
|
//! calls @c C_WrapKey |
|
return check(_session._slot.library()->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 */ |
|
|
|
//@} |
|
|
|
}; |
|
//@} |
|
|
|
} |
|
|
|
//! @addtogroup 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"); |
|
cryptoki::AttributeList res(list); |
|
res.push_back(attr); |
|
return res; |
|
} |
|
|
|
//@} |
|
|
|
#endif
|
|
|