# 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 : return " 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 */
} ;
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 ) :
_object ( obj ) , _session ( & session ) , _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()?
}
std : : string sign ( const std : : string & data , CK_MECHANISM_TYPE type ,
const std : : string & param = std : : string ( ) ) {
CRYPTOKI_LOG ( " log " ) ;
CRYPTOKI_LOG ( " signinit " ) ;
signinit ( type , param ) ;
CRYPTOKI_LOG ( " 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 ( ) ) {
CRYPTOKI_LOG ( " log " ) ;
CRYPTOKI_LOG ( " verifyinit " ) ;
verifyinit ( type , param ) ;
CRYPTOKI_LOG ( " verify " ) ;
return verify ( data , signature ) ;
//! @todo don't call verifyfinal()?
}
//@}
/*! @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 ;
}
std : : string sign ( std : : string in ) {
CRYPTOKI_LOG ( " log " ) ;
std : : string res ;
CK_ULONG size ( 0 ) ;
check ( _session - > _slot . _init - > _fn - > C_Sign
( _session - > _session ,
( unsigned char * ) & in [ 0 ] , in . size ( ) , 0 , & size ) ,
CRYPTOKI_FN_LOG ( " C_Sign " ) ) ;
CRYPTOKI_LOG ( " maximum size is " < < size < < " Bytes " ) ;
res . resize ( size , 0 ) ;
//! calls @c C_Sign
check ( _session - > _slot . _init - > _fn - > C_Sign
( _session - > _session ,
( unsigned char * ) & in [ 0 ] , in . size ( ) ,
( unsigned char * ) & res [ 0 ] , & size ) ,
CRYPTOKI_FN_LOG ( " C_Sign " ) ) ;
CRYPTOKI_LOG ( " exact size is " < < size < < " Bytes " ) ;
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 ( _session - > _slot . _init - > _fn - > 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 ( ) {
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 ( _session - > _slot . _init - > _fn - > 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 ( ) {
CRYPTOKI_LOG ( " log " ) ;
//! calls @c C_SignUpdate
return check ( _session - > _slot . _init - > _fn - > C_SignUpdate ( _session - > _session , CK_BYTE_PTR , CK_ULONG ) ,
CRYPTOKI_FN_LOG ( " C_SignUpdate " ) ) ;
}
@ endcode */
bool verify ( std : : string data , std : : string signature ) {
CRYPTOKI_LOG ( " log " ) ;
//! calls @c C_Verify
return check ( _session - > _slot . _init - > _fn - > 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 ( ) {
CRYPTOKI_LOG ( " log " ) ;
//! calls @c C_VerifyFinal
return check ( _session - > _slot . _init - > _fn - > C_VerifyFinal ( _session - > _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 ( _session - > _slot . _init - > _fn - > 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 ( ) {
CRYPTOKI_LOG ( " log " ) ;
//! calls @c C_VerifyUpdate
return check ( _session - > _slot . _init - > _fn - > C_VerifyUpdate ( _session - > _session , CK_BYTE_PTR , CK_ULONG ) ,
CRYPTOKI_FN_LOG ( " C_VerifyUpdate " ) ) ;
}
@ endcode */
//@}
/*! @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 */
bool signinit ( CK_MECHANISM_TYPE type , std : : string param ) {
CRYPTOKI_LOG ( " log " ) ;
CK_MECHANISM mech = {
type , param . size ( ) ? & param [ 0 ] : 0 , param . size ( )
} ;
CRYPTOKI_LOG ( " signinit: type= " < < type < < " ; mech=( " < < mech . mechanism
< < " , " < < mech . pParameter < < " , " < < mech . ulParameterLen < < ' ) ' ) ;
//! calls @c C_SignInit
return check ( _session - > _slot . _init - > _fn - > C_SignInit
( _session - > _session , & mech , _object ) ,
CRYPTOKI_FN_LOG ( " C_SignInit " ) ) ;
}
/*! @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 */
bool verifyinit ( CK_MECHANISM_TYPE type , std : : string param ) {
CRYPTOKI_LOG ( " log " ) ;
CK_MECHANISM mech = {
type , param . size ( ) ? & param [ 0 ] : 0 , param . size ( )
} ;
CRYPTOKI_LOG ( " verifyinit: type= " < < type < < " ; mech=( " < < mech . mechanism
< < " , " < < mech . pParameter < < " , " < < mech . ulParameterLen < < ' ) ' ) ;
//! calls @c C_VerifyInit
return check ( _session - > _slot . _init - > _fn - > C_VerifyInit
( _session - > _session , & mech , _object ) ,
CRYPTOKI_FN_LOG ( " C_VerifyInit " ) ) ;
}
/*! @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