# 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
& 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) 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
& lt ; cryptoki . hxx & gt ; < / 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
_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 " ) ) ;
}
~ 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 ( ) ? & param [ 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 * ) & param [ 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 ( ) ? & param [ 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 ( ) ? & param [ 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