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.
 
 
 
 

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