From 635d466c1c13ff09c98ca04b59428dbce1bf0fb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Thu, 27 Feb 2014 12:57:44 +0000 Subject: [PATCH] more documentation; refs #28 --- doc/doxyfile.in | 8 +- doc/examples/cryptoki-demo.cxx | 27 +- doc/examples/cryptoki-sign-demo.cxx | 6 +- doc/examples/suisse-id-demo.cxx | 13 +- src/cryptaux.hxx | 13 +- src/cryptoki.hxx | 464 +++++++++++++++++----------- src/suisseid.hxx | 46 ++- 7 files changed, 355 insertions(+), 222 deletions(-) diff --git a/doc/doxyfile.in b/doc/doxyfile.in index 1de3527..19c739b 100644 --- a/doc/doxyfile.in +++ b/doc/doxyfile.in @@ -375,7 +375,7 @@ EXTRACT_PACKAGE = NO # If the EXTRACT_STATIC tag is set to YES all static members of a file # will be included in the documentation. -EXTRACT_STATIC = NO +EXTRACT_STATIC = YES # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) # defined locally in source files will be included in the documentation. @@ -1634,7 +1634,7 @@ DOT_FONTPATH = # indirect inheritance relations. Setting this tag to YES will force the # CLASS_DIAGRAMS tag to NO. -CLASS_GRAPH = YES +CLASS_GRAPH = NO # If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen # will generate a graph for each documented class showing the direct and @@ -1688,7 +1688,7 @@ INCLUDED_BY_GRAPH = YES # the time of a run. So in most cases it will be better to enable call graphs # for selected functions only using the \callgraph command. -CALL_GRAPH = YES +CALL_GRAPH = NO # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then # doxygen will generate a caller dependency graph for every global function @@ -1696,7 +1696,7 @@ CALL_GRAPH = YES # the time of a run. So in most cases it will be better to enable caller # graphs for selected functions only using the \callergraph command. -CALLER_GRAPH = YES +CALLER_GRAPH = NO # If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen # will generate a graphical hierarchy of all classes instead of a textual one. diff --git a/doc/examples/cryptoki-demo.cxx b/doc/examples/cryptoki-demo.cxx index d090011..22f0674 100644 --- a/doc/examples/cryptoki-demo.cxx +++ b/doc/examples/cryptoki-demo.cxx @@ -9,9 +9,11 @@ template void print(const std::vector& v) { } int main(int argc, char const*const*const argv) try { -// //std::vector v(toVector<4>((int[]){1,2,3,4})); -// std::vector v(VECTOR(((int[]){1,2,3,4}))); -// print(v); + std::cout<<"Example for buffer to vector conversion:"< vec(cryptoki::toVector(buff)); + print(vec); + std::cout<mechanismlist()); - for (cryptoki::MechanismList::iterator it2(mechs.begin()); - it2!=mechs.end(); ++it2) { - cryptoki::MechanismInfo mechinfo(it->mechanisminfo(*it2)); + for (cryptoki::MechanismList::iterator mechinfo(mechs.begin()); + mechinfo!=mechs.end(); ++mechinfo) { std::cout<<"-------------------- Mechanism -----------------"<id<<'"'<name<<'"'<minKeySize<<'"'<maxKeySize<<'"'<flags<<'"'<attributes()); for (cryptoki::AttributeMap::iterator it(attrs.begin()); it!=attrs.end(); ++it) { - std::cout<<" - attribute: "<second.name()<<"=\"" - <second.value)<<'"'<second.name()<<" = "<second.value, 15, 5)< diff --git a/doc/examples/suisse-id-demo.cxx b/doc/examples/suisse-id-demo.cxx index 8d59034..aefa87a 100644 --- a/doc/examples/suisse-id-demo.cxx +++ b/doc/examples/suisse-id-demo.cxx @@ -11,15 +11,18 @@ #include #include +void show(const QStringList& sl, const std::string& p="item: ") { + for (QStringList::const_iterator s(sl.begin()); s!=sl.end(); ++s) + std::cout<toUtf8()).toStdString()<"; + return std::string(indent, ' ')+""; else if (data.find_first_not_of(VALID_CHARS) #include -/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API */ +/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API + + Wrapper to abstract the ugly PKCS#11 C-API with nice C++ features, + such as exception handling, memory management, etc. + + The cryptoky library loads a dynamic library that is responsible + for translating the card specific commands. The library is passed + in the constructor of cryptoki::Library. Then method + cryptoki::Library::slotList returns all slots found on the + computer. */ //@{ /*! @defgroup cryptokilib Cryptoki C++ Library */ -/*! @defgroup globaloperator Global Operator */ /*! @defgroup cryptokitypes Cryptoki C++ Types and Auxiliary */ /*! @defgroup cryptokiexceptions Cryptoki Exceptions */ +/** @example cryptoki-demo.cxx */ +/** @example cryptoki-sign-demo.cxx */ +//@} +/// @addtogroup cryptokitypes +//@{ #ifndef CRYPTOKI_FN_LOG #include #if __GNUC__ >= 2 @@ -58,6 +71,7 @@ " __FILE__ ":" CRYPTOKI_QUOTE(__LINE__) #endif #endif +//@} namespace pcsc { std::string version(); @@ -69,6 +83,11 @@ namespace cryptoki { //! @addtogroup cryptokitypes //@{ + /// Map cryptoki number to a string, care about unavailable and infinite + /** Cryptoky knows illegal values (unavailable information), which + is mapped to @c - and infinite values which are mapped to @c ∞ + when converted to string. All other numbers just show the number + as numeric string. */ inline std::string string(CK_ULONG num) { switch (num) { case CK_UNAVAILABLE_INFORMATION: return "-"; @@ -81,11 +100,10 @@ namespace cryptoki { } } - template std::vector toVector(TYPE in[NUM]) { - return std::vector(in, in+NUM); + /// Convert any kind of array (buffer) to an std::vector. + template std::vector toVector(TYPE in[]) { + return std::vector(in, in+sizeof(in)/sizeof(in[0])); } - #define CRYPTOKI_TO_VECTOR(ARRAY) \ - toVector(ARRAY) //@} @@ -136,10 +154,9 @@ namespace cryptoki { class Object; typedef std::vector ObjectList; - typedef std::set MechanismList; - typedef std::vector AttributeTypeList; + /// Represents a cryproki attribute and maps to C++ types. class Attribute { public: Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {} @@ -171,6 +188,7 @@ namespace cryptoki { a.ulValueLen = value.size(); return a; } + /// Textual name of the attribute. std::string name() const { switch (type) { case CKA_CLASS: return "CLASS"; @@ -234,30 +252,39 @@ namespace cryptoki { case CKA_HAS_RESET: return "HAS_RESET"; case CKA_VENDOR_DEFINED: return "VENDOR_DEFINED"; //case CKA_IBM_OPAQUE: return "IBM_OPAQUE"; - default: return "unknown"; + default: return "UNKNOWN"; } } - std::string readableValue() const { + /// Textual representation of the value. + std::string readableValue(std::string::size_type len=20, + std::string::size_type indent=0) const { + std::string res(indent, ' '); switch (type) { case CKA_CLASS: switch (*((CK_OBJECT_CLASS*)&value[0])) { - case CKO_DATA: return "DATA"; - case CKO_CERTIFICATE: return "CERTIFICATE"; - case CKO_PUBLIC_KEY: return "PUBLIC_KEY"; - case CKO_PRIVATE_KEY: return "PRIVATE_KEY"; - case CKO_SECRET_KEY: return "SECRET_KEY"; - case CKO_HW_FEATURE: return "HW_FEATURE"; - case CKO_DOMAIN_PARAMETERS: return "DOMAIN_PARAMETERS"; - case CKO_VENDOR_DEFINED: return "VENDOR_DEFINED"; - default: return "unknown"; + 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); + 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 Attribute& from(const TYPE& v) { value = std::string((char*)&v, sizeof(TYPE)); return *this; } + /// Convert to a given type. + /** To use this method, you must know what type the attribute + represents. */ template TYPE to() const { assert(sizeof(TYPE)==value.size()); return *reinterpret_cast(&value[0]); @@ -268,91 +295,70 @@ namespace cryptoki { typedef std::map AttributeMap; typedef std::vector 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 { \// -// public: typedef TYPE Type; \// -// } -// template 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 { -// public: typedef CK_KEY_TYPE Type; -// public: typedef Type Param; -// }; -// template<> class AttributeType { -// public: typedef CK_CHAR Type; -// public: typedef std::string Param; -// }; -// template<> class AttributeType { -// public: typedef CKA_BYTE Type; -// public: typedef std::string Param; -// }; -// #undef CRYPTOKI_DECLARE_ATTR - + /// String with fixed length. + /** FixString represents a string with a fix with spaces and can be + converted from and to a std::string by adding and removing the + fill-spaces. */ template 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; - } - }; + 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; - MechanismInfo(CK_MECHANISM_TYPE type): id(type) { + /// Construct from type with undefined infos. Use assigment later. + MechanismInfo(CK_MECHANISM_TYPE type): + minKeySize(0), maxKeySize(0), flags(0) { + *this=type; + } + /// Fully construct from type and infos. + MechanismInfo(CK_MECHANISM_TYPE type, const CK_MECHANISM_INFO& info) { + *this=type; + *this=info; + } + /// Set name and id from CK_MECHANISM_TYPE. + MechanismInfo& operator=(CK_MECHANISM_TYPE type) { + id=type; switch (id) { case CKM_RSA_PKCS_KEY_PAIR_GEN: name="RSA_PKCS_KEY_PAIR_GEN"; break; case CKM_RSA_PKCS: name="RSA_PKCS"; break; @@ -378,7 +384,7 @@ namespace cryptoki { case CKM_X9_42_DH_DERIVE: name="X9_42_DH_DERIVE"; break; case CKM_X9_42_DH_HYBRID_DERIVE: name="X9_42_DH_HYBRID_DERIVE"; break; case CKM_X9_42_MQV_DERIVE: name="X9_42_MQV_DERIVE"; break; - //case CKM_SHA256_RSA_PKCS: name="SHA256_RSA_PKCS"; break; + case CKM_SHA256_RSA_PKCS: name="SHA256_RSA_PKCS"; break; case CKM_RC2_KEY_GEN: name="RC2_KEY_GEN"; break; case CKM_RC2_ECB: name="RC2_ECB"; break; case CKM_RC2_CBC: name="RC2_CBC"; break; @@ -421,15 +427,15 @@ namespace cryptoki { case CKM_RIPEMD160: name="RIPEMD160"; break; case CKM_RIPEMD160_HMAC: name="RIPEMD160_HMAC"; break; case CKM_RIPEMD160_HMAC_GENERAL: name="RIPEMD160_HMAC_GENERAL"; break; - //case CKM_SHA256: name="SHA256"; break; - //case CKM_SHA256_HMAC: name="SHA256_HMAC"; break; - //case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break; - //case CKM_SHA384: name="SHA384"; break; - //case CKM_SHA384_HMAC: name="SHA384_HMAC"; break; - //case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break; - //case CKM_SHA512: name="SHA512"; break; - //case CKM_SHA512_HMAC: name="SHA512_HMAC"; break; - //case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break; + case CKM_SHA256: name="SHA256"; break; + case CKM_SHA256_HMAC: name="SHA256_HMAC"; break; + case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break; + case CKM_SHA384: name="SHA384"; break; + case CKM_SHA384_HMAC: name="SHA384_HMAC"; break; + case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break; + case CKM_SHA512: name="SHA512"; break; + case CKM_SHA512_HMAC: name="SHA512_HMAC"; break; + case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break; case CKM_CAST_KEY_GEN: name="CAST_KEY_GEN"; break; case CKM_CAST_ECB: name="CAST_ECB"; break; case CKM_CAST_CBC: name="CAST_CBC"; break; @@ -442,19 +448,21 @@ namespace cryptoki { case CKM_CAST3_MAC: name="CAST3_MAC"; break; case CKM_CAST3_MAC_GENERAL: name="CAST3_MAC_GENERAL"; break; case CKM_CAST3_CBC_PAD: name="CAST3_CBC_PAD"; break; - //case CKM_CAST5_KEY_GEN: name="CAST5_KEY_GEN"; break; - case CKM_CAST128_KEY_GEN: name="CAST5_KEY_GEN or CAST128_KEY_GEN"; break; - //case CKM_CAST5_ECB: name="CAST5_ECB"; break; - case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break; - //case CKM_CAST5_CBC: name="CAST5_CBC"; break; - case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break; - //case CKM_CAST5_MAC: name="CAST5_MAC"; break; - case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break; - //case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break; - case CKM_CAST128_MAC_GENERAL: - name="CAST5_MAC_GENERAL or CAST128_MAC_GENERAL"; break; - //case CKM_CAST5_CBC_PAD: name="CAST5_CBC_PAD"; break; - case CKM_CAST128_CBC_PAD: name="CAST5_CBC_PAD or CAST128_CBC_PAD"; break; + case CKM_CAST5_KEY_GEN: name="CAST5_KEY_GEN"; break; + //case CKM_CAST128_KEY_GEN: name="CAST5_KEY_GEN or + //CAST128_KEY_GEN"; break; + case CKM_CAST5_ECB: name="CAST5_ECB"; break; + //case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break; + case CKM_CAST5_CBC: name="CAST5_CBC"; break; + //case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break; + case CKM_CAST5_MAC: name="CAST5_MAC"; break; + //case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break; + case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break; + //case CKM_CAST128_MAC_GENERAL: name="CAST5_MAC_GENERAL or + //CAST128_MAC_GENERAL"; break; + case CKM_CAST5_CBC_PAD: name="CAST5_CBC_PAD"; break; + //case CKM_CAST128_CBC_PAD: name="CAST5_CBC_PAD or + //CAST128_CBC_PAD"; break; case CKM_RC5_KEY_GEN: name="RC5_KEY_GEN"; break; case CKM_RC5_ECB: name="RC5_ECB"; break; case CKM_RC5_CBC: name="RC5_CBC"; break; @@ -476,31 +484,34 @@ namespace cryptoki { name="CONCATENATE_DATA_AND_BASE"; break; case CKM_XOR_BASE_AND_DATA: name="XOR_BASE_AND_DATA"; break; case CKM_EXTRACT_KEY_FROM_KEY: name="EXTRACT_KEY_FROM_KEY"; break; - case CKM_SSL3_PRE_MASTER_KEY_GEN: name="SSL3_PRE_MASTER_KEY_GEN"; break; + case CKM_SSL3_PRE_MASTER_KEY_GEN: + name="SSL3_PRE_MASTER_KEY_GEN"; break; case CKM_SSL3_MASTER_KEY_DERIVE: name="SSL3_MASTER_KEY_DERIVE"; break; - case CKM_SSL3_KEY_AND_MAC_DERIVE: name="SSL3_KEY_AND_MAC_DERIVE"; break; + case CKM_SSL3_KEY_AND_MAC_DERIVE: + name="SSL3_KEY_AND_MAC_DERIVE"; break; case CKM_SSL3_MASTER_KEY_DERIVE_DH: name="SSL3_MASTER_KEY_DERIVE_DH"; break; case CKM_TLS_PRE_MASTER_KEY_GEN: name="TLS_PRE_MASTER_KEY_GEN"; break; case CKM_TLS_MASTER_KEY_DERIVE: name="TLS_MASTER_KEY_DERIVE"; break; case CKM_TLS_KEY_AND_MAC_DERIVE: name="TLS_KEY_AND_MAC_DERIVE"; break; - case CKM_TLS_MASTER_KEY_DERIVE_DH: name="TLS_MASTER_KEY_DERIVE_DH"; break; + case CKM_TLS_MASTER_KEY_DERIVE_DH: + name="TLS_MASTER_KEY_DERIVE_DH"; break; case CKM_SSL3_MD5_MAC: name="SSL3_MD5_MAC"; break; case CKM_SSL3_SHA1_MAC: name="SSL3_SHA1_MAC"; break; case CKM_MD5_KEY_DERIVATION: name="MD5_KEY_DERIVATION"; break; case CKM_MD2_KEY_DERIVATION: name="MD2_KEY_DERIVATION"; break; case CKM_SHA1_KEY_DERIVATION: name="SHA1_KEY_DERIVATION"; break; - //case CKM_SHA256_KEY_DERIVATION: name="SHA256_KEY_DERIVATION"; break; + case CKM_SHA256_KEY_DERIVATION: name="SHA256_KEY_DERIVATION"; break; case CKM_PBE_MD2_DES_CBC: name="PBE_MD2_DES_CBC"; break; case CKM_PBE_MD5_DES_CBC: name="PBE_MD5_DES_CBC"; break; case CKM_PBE_MD5_CAST_CBC: name="PBE_MD5_CAST_CBC"; break; case CKM_PBE_MD5_CAST3_CBC: name="PBE_MD5_CAST3_CBC"; break; - //case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break; - case CKM_PBE_MD5_CAST128_CBC: - name="PBE_MD5_CAST5_CBC or PBE_MD5_CAST128_CBC"; break; - //case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break; - case CKM_PBE_SHA1_CAST128_CBC: - name="PBE_SHA1_CAST5_CBC or PBE_SHA1_CAST128_CBC"; break; + case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break; + //case CKM_PBE_MD5_CAST128_CBC: name="PBE_MD5_CAST5_CBC or + //PBE_MD5_CAST128_CBC"; break; + case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break; + //case CKM_PBE_SHA1_CAST128_CBC: name="PBE_SHA1_CAST5_CBC or + //PBE_SHA1_CAST128_CBC"; break; case CKM_PBE_SHA1_RC4_128: name="PBE_SHA1_RC4_128"; break; case CKM_PBE_SHA1_RC4_40: name="PBE_SHA1_RC4_40"; break; case CKM_PBE_SHA1_DES3_EDE_CBC: name="PBE_SHA1_DES3_EDE_CBC"; break; @@ -508,7 +519,8 @@ namespace cryptoki { case CKM_PBE_SHA1_RC2_128_CBC: name="PBE_SHA1_RC2_128_CBC"; break; case CKM_PBE_SHA1_RC2_40_CBC: name="PBE_SHA1_RC2_40_CBC"; break; case CKM_PKCS5_PBKD2: name="PKCS5_PBKD2"; break; - case CKM_PBA_SHA1_WITH_SHA1_HMAC: name="PBA_SHA1_WITH_SHA1_HMAC"; break; + case CKM_PBA_SHA1_WITH_SHA1_HMAC: + name="PBA_SHA1_WITH_SHA1_HMAC"; break; case CKM_KEY_WRAP_LYNKS: name="KEY_WRAP_LYNKS"; break; case CKM_KEY_WRAP_SET_OAEP: name="KEY_WRAP_SET_OAEP"; break; case CKM_SKIPJACK_KEY_GEN: name="SKIPJACK_KEY_GEN"; break; @@ -532,9 +544,9 @@ namespace cryptoki { case CKM_BATON_COUNTER: name="BATON_COUNTER"; break; case CKM_BATON_SHUFFLE: name="BATON_SHUFFLE"; break; case CKM_BATON_WRAP: name="BATON_WRAP"; break; - //case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break; - case CKM_EC_KEY_PAIR_GEN: - name="ECDSA_KEY_PAIR_GEN or EC_KEY_PAIR_GEN"; break; + case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break; + //case CKM_EC_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN or + //EC_KEY_PAIR_GEN"; break; case CKM_ECDSA: name="ECDSA"; break; case CKM_ECDSA_SHA1: name="ECDSA_SHA1"; break; case CKM_ECDH1_DERIVE: name="ECDH1_DERIVE"; break; @@ -559,13 +571,26 @@ namespace cryptoki { case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break; default: { std::stringstream ss; - ss<<"unknown mechanism: "< MechanismList; + /// Handle slot information. struct SlotInfo { FixString<64> slotDescription; FixString<32> manufacturerID; @@ -589,6 +614,7 @@ namespace cryptoki { struct TokenInfo; // forward declaration inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti); + /// Handle token information. struct TokenInfo { FixString<32> label; FixString<32> manufacturerID; @@ -638,6 +664,7 @@ namespace cryptoki { }; + /// Textual representation for token information. inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti) { return out <<"label="<() { return _init->fn(); } - bool exc() { - return _init->_exc; - } - /*! @name C Like Error Handling You are strongly recommended not to disable exception @@ -782,6 +806,11 @@ namespace cryptoki { 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() { @@ -792,13 +821,15 @@ namespace cryptoki { 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; @@ -825,7 +856,7 @@ namespace cryptoki { private: - mrw::Shared _init; + std::shared_ptr _init; }; @@ -843,16 +874,21 @@ namespace cryptoki { public: - Slot(const Library& lib, CK_SLOT_ID slot): - _library(lib), _slot(slot), _res(CKR_OK) { + Slot(const Slot& o): + _library(o._library), _slot(o._slot), _res(o._res) { CRYPTOLOG("ID="<<_slot); } - Slot(const Slot& o): - _library(o._library), _slot(o._slot), _res(o._res) { + private: + + /// Slots are created from Library::slotList. + Slot(const Library& lib, CK_SLOT_ID slot): + _library(lib), _slot(slot), _res(CKR_OK) { CRYPTOLOG("ID="<<_slot); } + /// Slots are created from Library::slotList. + /** Empty constructor needs immediate assignment. */ Slot(): _slot(0), _res(-1) { CRYPTOLOG("ID="<<_slot); } @@ -877,6 +913,8 @@ namespace cryptoki { return _res==CKR_OK; } + public: + /*! @name C Like Error Handling You are strongly recommended not to disable exception @@ -897,23 +935,23 @@ namespace cryptoki { //@} + /// Access to the Library. Library& library() { return _library; } + /// Get the Slot's MechanismInfo given a @c CK_MECHANISM_TYPE + /** Used internally by mechanismlist(). */ MechanismInfo mechanisminfo(CK_MECHANISM_TYPE mechanism) { CRYPTOLOG("log"); - MechanismInfo info(mechanism); - CK_MECHANISM_INFO cInfo; + CK_MECHANISM_INFO info; //! calls @c C_GetMechanismInfo - check(_library->C_GetMechanismInfo(_slot, mechanism, &cInfo), + check(_library->C_GetMechanismInfo(_slot, mechanism, &info), CRYPTOKI_FN_LOG("C_GetMechanismInfo")); - info.minKeySize = cInfo.ulMinKeySize; - info.maxKeySize = cInfo.ulMaxKeySize; - info.flags = cInfo.flags; - return info; + return MechanismInfo(mechanism, info); } + /// Get a list of the Slot's mechanisms. MechanismList mechanismlist() { CRYPTOLOG("log"); MechanismList res; @@ -930,7 +968,7 @@ namespace cryptoki { return res; } for (CK_ULONG i(0); i label) { - CRYPTOLOG("log"); + CRYPTOLOG("log"); //! calls @c C_InitToken - return check(_library->C_InitToken - (_slot, - (unsigned char*)&pin[0], pin.size(), - (unsigned char*)label.&fix()[0]) - CRYPTOKI_FN_LOG("C_InitToken")); + if (pin.size()) + return check(_library->C_InitToken + (_slot, + (unsigned char*)&pin[0], pin.size(), + (unsigned char*)&label.fix()[0]), + CRYPTOKI_FN_LOG("C_InitToken")); + else + return check(_library->C_InitToken + (_slot, + 0, 0, // pin from external pin pad + (unsigned char*)&label.fix()[0]), + CRYPTOKI_FN_LOG("C_InitToken")); } - @endcode */ /*! @todo Not implemented: @code @@ -983,14 +1082,14 @@ namespace cryptoki { bool registerforslotevent(SlotEventListener&) { CRYPTOLOG("log"); //! calls @c C_WaitForSlotEvent - return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, CK_VOID_PTR), + return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, 0), CRYPTOKI_FN_LOG("C_WaitForSlotEvent")); } @endcode */ }; - //! Session Management - //! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); + /// Session Management + /** @note Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); */ class Session { private: @@ -2167,14 +2266,16 @@ namespace cryptoki { } -//! @groupadd globaloperator +//! @groupadd cryptokitypes //@{ +/// Append a cryptoki::Attribute to a cryptoki::AttributeList. inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list, const cryptoki::Attribute& attr) { CRYPTOLOG("log"); list.push_back(attr); return list; } +/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList. inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, const cryptoki::Attribute& attr) { CRYPTOLOG("log"); @@ -2184,5 +2285,4 @@ inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, } //@} -//@} #endif diff --git a/src/suisseid.hxx b/src/suisseid.hxx index 9205a43..64aef38 100644 --- a/src/suisseid.hxx +++ b/src/suisseid.hxx @@ -133,6 +133,12 @@ namespace suisseid { no_digsig() throw(): exception("no digital signature certificate found") {} }; + //---------------------------------------------------------------------------- + class slot_not_found: public exception { + public: + slot_not_found(const std::string& name) throw(): + exception("matching cryptoki slot for "+name+" not found") {} + }; //@} /*! @addtogroup suisseidtypes */ @@ -145,9 +151,12 @@ namespace suisseid { /*! @addtogroup suisseidconsts */ //@{ - const std::string NON_REP = "SwissSign_nonRep "; - const std::string DIG_SIG = "SwissSign_digSig "; - const std::string DATA_ENC = "SwissSign_dataEnc "; + /// Label of the key for digital signature certificate. + const std::string NON_REP = "SwissSign_nonRep "; + /// Label of the key for authentication certificate + const std::string DIG_SIG = "SwissSign_digSig "; + /// Label of the key required for getting the certificates + const std::string DATA_ENC = "SwissSign_dataEnc "; //@} /*! @addtogroup suisseidlib */ @@ -160,16 +169,22 @@ namespace suisseid { public: + /// Status of the card's certificates + /** @note by now, only @c MISSING and @c VALID is supported */ enum CertStatus { - MISSING, - EXPIRES_SOON, - EXPIRED, - REVOKED, - VALID + MISSING, ///< certificate is missing, needs initiatlization + EXPIRES_SOON, ///< certificate will soon expire, needs renewal + EXPIRED, ///< certificate is expired, needs new purchase + REVOKED, ///< certificate has been revoked and is invalid + VALID ///< certificate is valid }; public: - + + /// Instanciation is done within suisseid::Scanner + /** Instance requires a connenction to the reader an a cryptoky + library. This is passes automatically when this class is + instanciated through suisseid::Scanner. */ Card(mrw::Shared reader, const cryptoki::Library& cryptoki): cardos::Commands(reader), @@ -177,13 +192,17 @@ namespace suisseid { } virtual ~Card() {} + /// Find the matching cryptoki::Slot for further access + /** @throws slot_not_found if not exactly one matching slot exists */ cryptoki::Slot slot() { cryptoki::SlotList slots(_cryptoki.slotList(true, name())); if (slots.size()==1) return slots[0]; - throw std::runtime_error("matching cryptoki slot not found"); + throw slot_not_found(name()); } + /// Minimum allowed PIN length for this card. virtual unsigned int minimalPinLength() = 0; + /// Maximum allowed PIN length for this card. virtual unsigned int maximalPinLength() = 0; //! Name of the token/slot @@ -196,15 +215,17 @@ namespace suisseid { return ""; } - /// status of the certificates on the card + /// Status of the certificates on the card virtual CertStatus certStatus() { return MISSING; } + /// Starts and returns a cryptoki::Session. cryptoki::Session session() { return cryptoki::Session(slot()); } + /// Starts a cryptoki::Session and returns cryptoki::Session::Info. cryptoki::Session::Info sessionInfo() { return session().getsessioninfo(); } @@ -258,7 +279,8 @@ namespace suisseid { class Post: public Card { public: - + + /// @copydoc Card::Card Post(mrw::Shared reader, const cryptoki::Library& cryptoki): Card(reader, cryptoki), _minPinLen(0), _maxPinLen(-1) {