more documentation; refs #28

master
Marc Wäckerlin 11 years ago
parent 1e45bea4d4
commit 635d466c1c
  1. 8
      doc/doxyfile.in
  2. 27
      doc/examples/cryptoki-demo.cxx
  3. 6
      doc/examples/cryptoki-sign-demo.cxx
  4. 13
      doc/examples/suisse-id-demo.cxx
  5. 13
      src/cryptaux.hxx
  6. 454
      src/cryptoki.hxx
  7. 42
      src/suisseid.hxx

@ -375,7 +375,7 @@ EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES all static members of a file # If the EXTRACT_STATIC tag is set to YES all static members of a file
# will be included in the documentation. # 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) # If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
# defined locally in source files will be included in the documentation. # 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 # indirect inheritance relations. Setting this tag to YES will force the
# CLASS_DIAGRAMS tag to NO. # 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 # 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 # 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 # 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. # 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 # If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
# doxygen will generate a caller dependency graph for every global function # 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 # 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. # 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 # 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. # will generate a graphical hierarchy of all classes instead of a textual one.

@ -9,9 +9,11 @@ template <typename Array> void print(const std::vector<Array>& v) {
} }
int main(int argc, char const*const*const argv) try { int main(int argc, char const*const*const argv) try {
// //std::vector<int> v(toVector<4>((int[]){1,2,3,4})); std::cout<<"Example for buffer to vector conversion:"<<std::endl;
// std::vector<int> v(VECTOR(((int[]){1,2,3,4}))); int buff[] = {1, 2, 3, 4};
// print(v); std::vector<int> vec(cryptoki::toVector(buff));
print(vec);
std::cout<<std::endl;
cryptoki::Library cryptoki(argc==2?argv[1]:"onepin-opensc-pkcs11.so"); cryptoki::Library cryptoki(argc==2?argv[1]:"onepin-opensc-pkcs11.so");
cryptoki::Info inf(cryptoki.info()); cryptoki::Info inf(cryptoki.info());
std::cout<<"Library-Version: "<<pcsc::version()<<std::endl; std::cout<<"Library-Version: "<<pcsc::version()<<std::endl;
@ -61,15 +63,14 @@ int main(int argc, char const*const*const argv) try {
<<"utcTime: \""<<crypto::readable(info.utcTime) <<"utcTime: \""<<crypto::readable(info.utcTime)
<<'"'<<std::endl; <<'"'<<std::endl;
cryptoki::MechanismList mechs(it->mechanismlist()); cryptoki::MechanismList mechs(it->mechanismlist());
for (cryptoki::MechanismList::iterator it2(mechs.begin()); for (cryptoki::MechanismList::iterator mechinfo(mechs.begin());
it2!=mechs.end(); ++it2) { mechinfo!=mechs.end(); ++mechinfo) {
cryptoki::MechanismInfo mechinfo(it->mechanisminfo(*it2));
std::cout<<"-------------------- Mechanism -----------------"<<std::endl std::cout<<"-------------------- Mechanism -----------------"<<std::endl
<<"id: \""<<mechinfo.id<<'"'<<std::endl <<"id: \""<<mechinfo->id<<'"'<<std::endl
<<"name: \""<<mechinfo.name<<'"'<<std::endl <<"name: \""<<mechinfo->name<<'"'<<std::endl
<<"minKeySize: \""<<mechinfo.minKeySize<<'"'<<std::endl <<"minKeySize: \""<<mechinfo->minKeySize<<'"'<<std::endl
<<"maxKeySize: \""<<mechinfo.maxKeySize<<'"'<<std::endl <<"maxKeySize: \""<<mechinfo->maxKeySize<<'"'<<std::endl
<<"flags: \""<<mechinfo.flags<<'"'<<std::endl; <<"flags: \""<<mechinfo->flags<<'"'<<std::endl;
} }
cryptoki::Session session(*it); cryptoki::Session session(*it);
cryptoki::ObjectList objs(session.find()); cryptoki::ObjectList objs(session.find());
@ -80,8 +81,8 @@ int main(int argc, char const*const*const argv) try {
cryptoki::AttributeMap attrs(it->attributes()); cryptoki::AttributeMap attrs(it->attributes());
for (cryptoki::AttributeMap::iterator it(attrs.begin()); for (cryptoki::AttributeMap::iterator it(attrs.begin());
it!=attrs.end(); ++it) { it!=attrs.end(); ++it) {
std::cout<<" - attribute: "<<it->second.name()<<"=\"" std::cout<<" - attribute: "<<it->second.name()<<" = "<<std::endl
<<crypto::readable(it->second.value)<<'"'<<std::endl; <<crypto::readable(it->second.value, 15, 5)<<std::endl;
} }
} }
std::cout<<"**** Success"<<std::endl; std::cout<<"**** Success"<<std::endl;

@ -99,7 +99,11 @@ int main(int argc, char** argv) try {
auto start = std::chrono::system_clock::now(); auto start = std::chrono::system_clock::now();
#endif #endif
for (int i(0); i<r; ++i) for (int i(0); i<r; ++i)
keys[0].sign(txt, CKM_RSA_PKCS); std::cout<<"Text:"<<std::endl
<<crypto::readable(txt)<<std::endl
<<"Signature:"<<std::endl
<<crypto::readable(keys[0].sign(txt, CKM_RSA_PKCS))
<<std::endl;
#ifndef MRW__OLD_PRE11_COMPILER #ifndef MRW__OLD_PRE11_COMPILER
auto end = std::chrono::system_clock::now(); auto end = std::chrono::system_clock::now();
auto elapsed(std::chrono::duration_cast<std::chrono::milliseconds> auto elapsed(std::chrono::duration_cast<std::chrono::milliseconds>

@ -11,15 +11,18 @@
#include <QtNetwork/QSslCertificate> #include <QtNetwork/QSslCertificate>
#include <QtCore/QDateTime> #include <QtCore/QDateTime>
void show(const QStringList& sl, const std::string& p="item: ") {
for (QStringList::const_iterator s(sl.begin()); s!=sl.end(); ++s)
std::cout<<p<<QString(s->toUtf8()).toStdString()<<std::endl;
}
// show certificate information // show certificate information
void show(const suisseid::Certificate& cert) { void show(const suisseid::Certificate& cert) {
// makes use of qt library's certificate class // makes use of qt library's certificate class
QSslCertificate c(QByteArray(cert.data(), cert.size()), QSsl::Der); QSslCertificate c(QByteArray(cert.data(), cert.size()), QSsl::Der);
std::cout<<"Certificate info: CN=" std::cout<<"Certificate info:";
<<QString(c.subjectInfo(QSslCertificate::CommonName) show(c.subjectInfo(QSslCertificate::CommonName), " CN=");
.toUtf8()).toStdString() std::cout<<" Valid until: "
<<std::endl
<<" Valid until: "
<<QString(c.expiryDate().toString().toUtf8()).toStdString() <<QString(c.expiryDate().toString().toUtf8()).toStdString()
<<std::endl; <<std::endl;
} }

@ -96,10 +96,12 @@ namespace crypto {
} }
inline std::string hexTxt(const std::string& data, inline std::string hexTxt(const std::string& data,
std::string::size_type len=20) { std::string::size_type len=20,
std::string::size_type indent=0) {
std::stringstream res; std::stringstream res;
std::string::size_type pos(0); std::string::size_type pos(0);
for (std::string::const_iterator it(data.begin()); it!=data.end(); ++it) { for (std::string::const_iterator it(data.begin()); it!=data.end(); ++it) {
if (pos%len==0) res<<std::string(indent, ' ');
res<<std::hex<<std::setfill('0')<<std::setw(2) res<<std::hex<<std::setfill('0')<<std::setw(2)
<<(unsigned int)(unsigned char)*it; <<(unsigned int)(unsigned char)*it;
++pos; ++pos;
@ -114,13 +116,14 @@ namespace crypto {
} }
inline std::string readable(const std::string& data, inline std::string readable(const std::string& data,
std::string::size_type len=20) { std::string::size_type len=20,
std::string::size_type indent=0) {
if (!data.size()) if (!data.size())
return "<empty>"; return std::string(indent, ' ')+"<empty>";
else if (data.find_first_not_of(VALID_CHARS)<data.size()) else if (data.find_first_not_of(VALID_CHARS)<data.size())
return hexTxt(data, len); return hexTxt(data, len, indent);
else else
return "\""+data+"\""; return std::string(indent, ' ')+"\""+data+"\"";
} }
//! Convert binary to readable hexadecimal //! Convert binary to readable hexadecimal

@ -29,13 +29,26 @@
#include <iomanip> #include <iomanip>
#include <memory> #include <memory>
/*! @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 cryptokilib Cryptoki C++ Library */
/*! @defgroup globaloperator Global Operator */
/*! @defgroup cryptokitypes Cryptoki C++ Types and Auxiliary */ /*! @defgroup cryptokitypes Cryptoki C++ Types and Auxiliary */
/*! @defgroup cryptokiexceptions Cryptoki Exceptions */ /*! @defgroup cryptokiexceptions Cryptoki Exceptions */
/** @example cryptoki-demo.cxx */
/** @example cryptoki-sign-demo.cxx */
//@}
/// @addtogroup cryptokitypes
//@{
#ifndef CRYPTOKI_FN_LOG #ifndef CRYPTOKI_FN_LOG
#include <iostream> #include <iostream>
#if __GNUC__ >= 2 #if __GNUC__ >= 2
@ -58,6 +71,7 @@
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__) " __FILE__ ":" CRYPTOKI_QUOTE(__LINE__)
#endif #endif
#endif #endif
//@}
namespace pcsc { namespace pcsc {
std::string version(); std::string version();
@ -69,6 +83,11 @@ namespace cryptoki {
//! @addtogroup cryptokitypes //! @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) { inline std::string string(CK_ULONG num) {
switch (num) { switch (num) {
case CK_UNAVAILABLE_INFORMATION: return "-"; case CK_UNAVAILABLE_INFORMATION: return "-";
@ -81,11 +100,10 @@ namespace cryptoki {
} }
} }
template <int NUM, typename TYPE> std::vector<TYPE> toVector(TYPE in[NUM]) { /// Convert any kind of array (buffer) to an std::vector.
return std::vector<TYPE>(in, in+NUM); template <typename TYPE> std::vector<TYPE> toVector(TYPE in[]) {
return std::vector<TYPE>(in, in+sizeof(in)/sizeof(in[0]));
} }
#define CRYPTOKI_TO_VECTOR(ARRAY) \
toVector<sizeof(ARRAY)/sizeof(ARRAY[0])>(ARRAY)
//@} //@}
@ -136,10 +154,9 @@ namespace cryptoki {
class Object; class Object;
typedef std::vector<Object> ObjectList; typedef std::vector<Object> ObjectList;
typedef std::set<CK_MECHANISM_TYPE> MechanismList;
typedef std::vector<CK_ATTRIBUTE_TYPE> AttributeTypeList; typedef std::vector<CK_ATTRIBUTE_TYPE> AttributeTypeList;
/// Represents a cryproki attribute and maps to C++ types.
class Attribute { class Attribute {
public: public:
Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {} Attribute(CK_ATTRIBUTE_TYPE t = -1): type(t) {}
@ -171,6 +188,7 @@ namespace cryptoki {
a.ulValueLen = value.size(); a.ulValueLen = value.size();
return a; return a;
} }
/// Textual name of the attribute.
std::string name() const { std::string name() const {
switch (type) { switch (type) {
case CKA_CLASS: return "CLASS"; case CKA_CLASS: return "CLASS";
@ -234,30 +252,39 @@ namespace cryptoki {
case CKA_HAS_RESET: return "HAS_RESET"; case CKA_HAS_RESET: return "HAS_RESET";
case CKA_VENDOR_DEFINED: return "VENDOR_DEFINED"; case CKA_VENDOR_DEFINED: return "VENDOR_DEFINED";
//case CKA_IBM_OPAQUE: return "IBM_OPAQUE"; //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) { switch (type) {
case CKA_CLASS: case CKA_CLASS:
switch (*((CK_OBJECT_CLASS*)&value[0])) { switch (*((CK_OBJECT_CLASS*)&value[0])) {
case CKO_DATA: return "DATA"; case CKO_DATA: return res+"DATA";
case CKO_CERTIFICATE: return "CERTIFICATE"; case CKO_CERTIFICATE: return res+"CERTIFICATE";
case CKO_PUBLIC_KEY: return "PUBLIC_KEY"; case CKO_PUBLIC_KEY: return res+"PUBLIC_KEY";
case CKO_PRIVATE_KEY: return "PRIVATE_KEY"; case CKO_PRIVATE_KEY: return res+"PRIVATE_KEY";
case CKO_SECRET_KEY: return "SECRET_KEY"; case CKO_SECRET_KEY: return res+"SECRET_KEY";
case CKO_HW_FEATURE: return "HW_FEATURE"; case CKO_HW_FEATURE: return res+"HW_FEATURE";
case CKO_DOMAIN_PARAMETERS: return "DOMAIN_PARAMETERS"; case CKO_DOMAIN_PARAMETERS: return res+"DOMAIN_PARAMETERS";
case CKO_VENDOR_DEFINED: return "VENDOR_DEFINED"; case CKO_VENDOR_DEFINED: return res+"VENDOR_DEFINED";
default: return "unknown"; 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<typename TYPE> Attribute& from(const TYPE& v) { template<typename TYPE> Attribute& from(const TYPE& v) {
value = std::string((char*)&v, sizeof(TYPE)); value = std::string((char*)&v, sizeof(TYPE));
return *this; return *this;
} }
/// Convert to a given type.
/** To use this method, you must know what type the attribute
represents. */
template<typename TYPE> TYPE to() const { template<typename TYPE> TYPE to() const {
assert(sizeof(TYPE)==value.size()); assert(sizeof(TYPE)==value.size());
return *reinterpret_cast<const TYPE*>(&value[0]); return *reinterpret_cast<const TYPE*>(&value[0]);
@ -268,91 +295,70 @@ namespace cryptoki {
typedef std::map<CK_ATTRIBUTE_TYPE, Attribute> AttributeMap; typedef std::map<CK_ATTRIBUTE_TYPE, Attribute> AttributeMap;
typedef std::vector<Attribute> AttributeList; typedef std::vector<Attribute> AttributeList;
// class Class { /// String with fixed length.
// public: /** FixString represents a string with a fix with spaces and can be
// CK_OBJECT_CLASS class; converted from and to a std::string by adding and removing the
// }; fill-spaces. */
//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> template<std::string::size_type SIZE>
class FixString: public std::string { class FixString: public std::string {
public: public:
FixString() {} FixString() {}
FixString(const char* const cStr) { FixString(const char* const cStr) {
*this = std::string(cStr, SIZE); *this = std::string(cStr, SIZE);
size_type pos(find_last_not_of(" ")); size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0); if (pos!=npos) resize(pos+1); else resize(0);
} }
FixString(const unsigned char* const cStr) { FixString(const unsigned char* const cStr) {
*this = std::string((const char*)cStr, SIZE); *this = std::string((const char*)cStr, SIZE);
size_type pos(find_last_not_of(" ")); size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0); if (pos!=npos) resize(pos+1); else resize(0);
} }
FixString& operator=(const std::string& other) { FixString& operator=(const std::string& other) {
std::string::operator=(other); std::string::operator=(other);
return *this; return *this;
} }
FixString& operator=(const char* const cStr) { FixString& operator=(const char* const cStr) {
*this = std::string(cStr, SIZE); *this = std::string(cStr, SIZE);
size_type pos(find_last_not_of(" ")); size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0); if (pos!=npos) resize(pos+1); else resize(0);
return *this; return *this;
} }
FixString& operator=(const unsigned char* const cStr) { FixString& operator=(const unsigned char* const cStr) {
*this = std::string((const char*)cStr, SIZE); *this = std::string((const char*)cStr, SIZE);
size_type pos(find_last_not_of(" ")); size_type pos(find_last_not_of(" "));
if (pos!=npos) resize(pos+1); else resize(0); if (pos!=npos) resize(pos+1); else resize(0);
return *this; return *this;
} }
operator unsigned char*() { operator unsigned char*() {
return (unsigned char*)begin().operator->(); return (unsigned char*)begin().operator->();
} }
FixString fix() { FixString fix() {
FixString cpy(*this); FixString cpy(*this);
cpy.resize(SIZE, ' '); cpy.resize(SIZE, ' ');
return cpy; return cpy;
} }
}; };
/// C++ representation of mechanism information.
struct MechanismInfo { struct MechanismInfo {
CK_MECHANISM_TYPE id; CK_MECHANISM_TYPE id;
std::string name; std::string name;
CK_ULONG minKeySize; CK_ULONG minKeySize;
CK_ULONG maxKeySize; CK_ULONG maxKeySize;
CK_FLAGS flags; 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) { switch (id) {
case CKM_RSA_PKCS_KEY_PAIR_GEN: name="RSA_PKCS_KEY_PAIR_GEN"; break; 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_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_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_DH_HYBRID_DERIVE: name="X9_42_DH_HYBRID_DERIVE"; break;
case CKM_X9_42_MQV_DERIVE: name="X9_42_MQV_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_KEY_GEN: name="RC2_KEY_GEN"; break;
case CKM_RC2_ECB: name="RC2_ECB"; break; case CKM_RC2_ECB: name="RC2_ECB"; break;
case CKM_RC2_CBC: name="RC2_CBC"; break; case CKM_RC2_CBC: name="RC2_CBC"; break;
@ -421,15 +427,15 @@ namespace cryptoki {
case CKM_RIPEMD160: name="RIPEMD160"; break; case CKM_RIPEMD160: name="RIPEMD160"; break;
case CKM_RIPEMD160_HMAC: name="RIPEMD160_HMAC"; break; case CKM_RIPEMD160_HMAC: name="RIPEMD160_HMAC"; break;
case CKM_RIPEMD160_HMAC_GENERAL: name="RIPEMD160_HMAC_GENERAL"; break; case CKM_RIPEMD160_HMAC_GENERAL: name="RIPEMD160_HMAC_GENERAL"; break;
//case CKM_SHA256: name="SHA256"; break; case CKM_SHA256: name="SHA256"; break;
//case CKM_SHA256_HMAC: name="SHA256_HMAC"; break; case CKM_SHA256_HMAC: name="SHA256_HMAC"; break;
//case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break; case CKM_SHA256_HMAC_GENERAL: name="SHA256_HMAC_GENERAL"; break;
//case CKM_SHA384: name="SHA384"; break; case CKM_SHA384: name="SHA384"; break;
//case CKM_SHA384_HMAC: name="SHA384_HMAC"; break; case CKM_SHA384_HMAC: name="SHA384_HMAC"; break;
//case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break; case CKM_SHA384_HMAC_GENERAL: name="SHA384_HMAC_GENERAL"; break;
//case CKM_SHA512: name="SHA512"; break; case CKM_SHA512: name="SHA512"; break;
//case CKM_SHA512_HMAC: name="SHA512_HMAC"; break; case CKM_SHA512_HMAC: name="SHA512_HMAC"; break;
//case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break; case CKM_SHA512_HMAC_GENERAL: name="SHA512_HMAC_GENERAL"; break;
case CKM_CAST_KEY_GEN: name="CAST_KEY_GEN"; break; case CKM_CAST_KEY_GEN: name="CAST_KEY_GEN"; break;
case CKM_CAST_ECB: name="CAST_ECB"; break; case CKM_CAST_ECB: name="CAST_ECB"; break;
case CKM_CAST_CBC: name="CAST_CBC"; 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: name="CAST3_MAC"; break;
case CKM_CAST3_MAC_GENERAL: name="CAST3_MAC_GENERAL"; break; case CKM_CAST3_MAC_GENERAL: name="CAST3_MAC_GENERAL"; break;
case CKM_CAST3_CBC_PAD: name="CAST3_CBC_PAD"; break; case CKM_CAST3_CBC_PAD: name="CAST3_CBC_PAD"; break;
//case CKM_CAST5_KEY_GEN: name="CAST5_KEY_GEN"; 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_CAST128_KEY_GEN: name="CAST5_KEY_GEN or
//case CKM_CAST5_ECB: name="CAST5_ECB"; break; //CAST128_KEY_GEN"; break;
case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break; case CKM_CAST5_ECB: name="CAST5_ECB"; break;
//case CKM_CAST5_CBC: name="CAST5_CBC"; break; //case CKM_CAST128_ECB: name="CAST5_ECB or CAST128_ECB"; break;
case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break; case CKM_CAST5_CBC: name="CAST5_CBC"; break;
//case CKM_CAST5_MAC: name="CAST5_MAC"; break; //case CKM_CAST128_CBC: name="CAST5_CBC or CAST128_CBC"; break;
case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break; case CKM_CAST5_MAC: name="CAST5_MAC"; break;
//case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break; //case CKM_CAST128_MAC: name="CAST5_MAC or CAST128_MAC"; break;
case CKM_CAST128_MAC_GENERAL: case CKM_CAST5_MAC_GENERAL: name="CAST5_MAC_GENERAL"; break;
name="CAST5_MAC_GENERAL or CAST128_MAC_GENERAL"; break; //case CKM_CAST128_MAC_GENERAL: name="CAST5_MAC_GENERAL or
//case CKM_CAST5_CBC_PAD: name="CAST5_CBC_PAD"; break; //CAST128_MAC_GENERAL"; break;
case CKM_CAST128_CBC_PAD: name="CAST5_CBC_PAD or CAST128_CBC_PAD"; 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_KEY_GEN: name="RC5_KEY_GEN"; break;
case CKM_RC5_ECB: name="RC5_ECB"; break; case CKM_RC5_ECB: name="RC5_ECB"; break;
case CKM_RC5_CBC: name="RC5_CBC"; break; case CKM_RC5_CBC: name="RC5_CBC"; break;
@ -476,31 +484,34 @@ namespace cryptoki {
name="CONCATENATE_DATA_AND_BASE"; break; name="CONCATENATE_DATA_AND_BASE"; break;
case CKM_XOR_BASE_AND_DATA: name="XOR_BASE_AND_DATA"; 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_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_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: case CKM_SSL3_MASTER_KEY_DERIVE_DH:
name="SSL3_MASTER_KEY_DERIVE_DH"; break; name="SSL3_MASTER_KEY_DERIVE_DH"; break;
case CKM_TLS_PRE_MASTER_KEY_GEN: name="TLS_PRE_MASTER_KEY_GEN"; 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_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_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_MD5_MAC: name="SSL3_MD5_MAC"; break;
case CKM_SSL3_SHA1_MAC: name="SSL3_SHA1_MAC"; break; case CKM_SSL3_SHA1_MAC: name="SSL3_SHA1_MAC"; break;
case CKM_MD5_KEY_DERIVATION: name="MD5_KEY_DERIVATION"; break; case CKM_MD5_KEY_DERIVATION: name="MD5_KEY_DERIVATION"; break;
case CKM_MD2_KEY_DERIVATION: name="MD2_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_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_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_DES_CBC: name="PBE_MD5_DES_CBC"; break;
case CKM_PBE_MD5_CAST_CBC: name="PBE_MD5_CAST_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_CAST3_CBC: name="PBE_MD5_CAST3_CBC"; break;
//case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break; case CKM_PBE_MD5_CAST5_CBC: name="PBE_MD5_CAST5_CBC"; break;
case CKM_PBE_MD5_CAST128_CBC: //case CKM_PBE_MD5_CAST128_CBC: name="PBE_MD5_CAST5_CBC or
name="PBE_MD5_CAST5_CBC or PBE_MD5_CAST128_CBC"; break; //PBE_MD5_CAST128_CBC"; break;
//case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break; case CKM_PBE_SHA1_CAST5_CBC: name="PBE_SHA1_CAST5_CBC"; break;
case CKM_PBE_SHA1_CAST128_CBC: //case CKM_PBE_SHA1_CAST128_CBC: name="PBE_SHA1_CAST5_CBC or
name="PBE_SHA1_CAST5_CBC or PBE_SHA1_CAST128_CBC"; break; //PBE_SHA1_CAST128_CBC"; break;
case CKM_PBE_SHA1_RC4_128: name="PBE_SHA1_RC4_128"; 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_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_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_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_PBE_SHA1_RC2_40_CBC: name="PBE_SHA1_RC2_40_CBC"; break;
case CKM_PKCS5_PBKD2: name="PKCS5_PBKD2"; 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_LYNKS: name="KEY_WRAP_LYNKS"; break;
case CKM_KEY_WRAP_SET_OAEP: name="KEY_WRAP_SET_OAEP"; 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_KEY_GEN: name="SKIPJACK_KEY_GEN"; break;
@ -532,9 +544,9 @@ namespace cryptoki {
case CKM_BATON_COUNTER: name="BATON_COUNTER"; break; case CKM_BATON_COUNTER: name="BATON_COUNTER"; break;
case CKM_BATON_SHUFFLE: name="BATON_SHUFFLE"; break; case CKM_BATON_SHUFFLE: name="BATON_SHUFFLE"; break;
case CKM_BATON_WRAP: name="BATON_WRAP"; break; case CKM_BATON_WRAP: name="BATON_WRAP"; break;
//case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break; case CKM_ECDSA_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN"; break;
case CKM_EC_KEY_PAIR_GEN: //case CKM_EC_KEY_PAIR_GEN: name="ECDSA_KEY_PAIR_GEN or
name="ECDSA_KEY_PAIR_GEN or EC_KEY_PAIR_GEN"; break; //EC_KEY_PAIR_GEN"; break;
case CKM_ECDSA: name="ECDSA"; break; case CKM_ECDSA: name="ECDSA"; break;
case CKM_ECDSA_SHA1: name="ECDSA_SHA1"; break; case CKM_ECDSA_SHA1: name="ECDSA_SHA1"; break;
case CKM_ECDH1_DERIVE: name="ECDH1_DERIVE"; break; case CKM_ECDH1_DERIVE: name="ECDH1_DERIVE"; break;
@ -559,13 +571,26 @@ namespace cryptoki {
case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break; case CKM_VENDOR_DEFINED: name="VENDOR_DEFINED"; break;
default: { default: {
std::stringstream ss; std::stringstream ss;
ss<<"unknown mechanism: "<<id; ss<<id;
throw exception(ss.str()); name=ss.str();
} }
} }
return *this;
}
/// Assign information.
MechanismInfo& operator=(const CK_MECHANISM_INFO& info) {
minKeySize = info.ulMinKeySize;
maxKeySize = info.ulMaxKeySize;
flags = info.flags;
return *this;
}
bool operator<(const MechanismInfo& o) const {
return id<o.id;
} }
}; };
typedef std::set<MechanismInfo> MechanismList;
/// Handle slot information.
struct SlotInfo { struct SlotInfo {
FixString<64> slotDescription; FixString<64> slotDescription;
FixString<32> manufacturerID; FixString<32> manufacturerID;
@ -589,6 +614,7 @@ namespace cryptoki {
struct TokenInfo; // forward declaration struct TokenInfo; // forward declaration
inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti); inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti);
/// Handle token information.
struct TokenInfo { struct TokenInfo {
FixString<32> label; FixString<32> label;
FixString<32> manufacturerID; FixString<32> manufacturerID;
@ -638,6 +664,7 @@ namespace cryptoki {
}; };
/// Textual representation for token information.
inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti) { inline std::ostream& operator<<(std::ostream& out, const TokenInfo& ti) {
return out return out
<<"label="<<ti.label<<std::endl <<"label="<<ti.label<<std::endl
@ -662,6 +689,7 @@ namespace cryptoki {
<<"utcTime="<<ti.utcTime; <<"utcTime="<<ti.utcTime;
} }
/// Handle library information.
struct Info { struct Info {
CK_VERSION cryptokiVersion; CK_VERSION cryptokiVersion;
FixString<32> manufacturerID; FixString<32> manufacturerID;
@ -676,20 +704,22 @@ namespace cryptoki {
//@{ //@{
/// Load Cryptoki Library for use with Smart Card. /// Load Cryptoki Library for use with Smart Card.
/** This is your starting point when accessing tokens through
PKCS#11. Get an instance using Library::Library. */
class Library { class Library {
friend class Slot; friend class Slot;
public: public:
//! Initialize for a given library (default cryptoki) //! Initialize for a given library
/*! Please notem, that you must not instanciate more than one /*! @note Do not instanciate more than one Library instance per
Init per unique function list! shared library. Normally you need only one instance.
@param library name of the shared library that supports pkcs#11 @param library name of the shared library that supports pkcs#11
@param exc wether exceptions should be thrown */ @param exc wether exceptions should be thrown */
Library(const std::string& library, bool exc=true): Library(const std::string& library, bool exc=true):
_init(library, exc) { _init(new Init(library, exc)) {
CRYPTOLOG("log"); CRYPTOLOG("log");
} }
@ -699,8 +729,9 @@ namespace cryptoki {
CRYPTOLOG("log"); CRYPTOLOG("log");
} }
public: private:
/// Initiatlize the library: load and unload the shared object.
class Init { class Init {
private: private:
@ -726,12 +757,7 @@ namespace cryptoki {
public: public:
//! Initialize for a given library (default cryptoki) /// Called from Library::Library
/*! 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(const std::string& library="opensc-pkcs11.so", bool exc=true);
~Init(); ~Init();
@ -767,14 +793,12 @@ namespace cryptoki {
public: public:
/// Get pointer to cryptoki API functions.
/** Used internally, normally you shouldn't use this directly. */
CK_FUNCTION_LIST* operator->() { CK_FUNCTION_LIST* operator->() {
return _init->fn(); return _init->fn();
} }
bool exc() {
return _init->_exc;
}
/*! @name C Like Error Handling /*! @name C Like Error Handling
You are strongly recommended not to disable exception You are strongly recommended not to disable exception
@ -783,6 +807,11 @@ namespace cryptoki {
provide all you need for that. */ 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 */ /*! @return @c true if last cryptoki on this object call was successful */
operator bool() { operator bool() {
return *_init; return *_init;
@ -793,12 +822,14 @@ namespace cryptoki {
return _init->error(); return _init->error();
} }
/// Convert @c CK_RV return code to a human readable text.
std::string error(CK_RV res) { std::string error(CK_RV res) {
return _init->error(res); return _init->error(res);
} }
//@} //@}
/// Get cryptoki library informartion.
Info info() { Info info() {
CRYPTOLOG("log"); CRYPTOLOG("log");
Info inf; Info inf;
@ -825,7 +856,7 @@ namespace cryptoki {
private: private:
mrw::Shared<Init> _init; std::shared_ptr<Init> _init;
}; };
@ -843,16 +874,21 @@ namespace cryptoki {
public: public:
Slot(const Library& lib, CK_SLOT_ID slot): Slot(const Slot& o):
_library(lib), _slot(slot), _res(CKR_OK) { _library(o._library), _slot(o._slot), _res(o._res) {
CRYPTOLOG("ID="<<_slot); CRYPTOLOG("ID="<<_slot);
} }
Slot(const Slot& o): private:
_library(o._library), _slot(o._slot), _res(o._res) {
/// Slots are created from Library::slotList.
Slot(const Library& lib, CK_SLOT_ID slot):
_library(lib), _slot(slot), _res(CKR_OK) {
CRYPTOLOG("ID="<<_slot); CRYPTOLOG("ID="<<_slot);
} }
/// Slots are created from Library::slotList.
/** Empty constructor needs immediate assignment. */
Slot(): _slot(0), _res(-1) { Slot(): _slot(0), _res(-1) {
CRYPTOLOG("ID="<<_slot); CRYPTOLOG("ID="<<_slot);
} }
@ -877,6 +913,8 @@ namespace cryptoki {
return _res==CKR_OK; return _res==CKR_OK;
} }
public:
/*! @name C Like Error Handling /*! @name C Like Error Handling
You are strongly recommended not to disable exception You are strongly recommended not to disable exception
@ -897,23 +935,23 @@ namespace cryptoki {
//@} //@}
/// Access to the Library.
Library& library() { Library& library() {
return _library; return _library;
} }
/// Get the Slot's MechanismInfo given a @c CK_MECHANISM_TYPE
/** Used internally by mechanismlist(). */
MechanismInfo mechanisminfo(CK_MECHANISM_TYPE mechanism) { MechanismInfo mechanisminfo(CK_MECHANISM_TYPE mechanism) {
CRYPTOLOG("log"); CRYPTOLOG("log");
MechanismInfo info(mechanism); CK_MECHANISM_INFO info;
CK_MECHANISM_INFO cInfo;
//! calls @c C_GetMechanismInfo //! calls @c C_GetMechanismInfo
check(_library->C_GetMechanismInfo(_slot, mechanism, &cInfo), check(_library->C_GetMechanismInfo(_slot, mechanism, &info),
CRYPTOKI_FN_LOG("C_GetMechanismInfo")); CRYPTOKI_FN_LOG("C_GetMechanismInfo"));
info.minKeySize = cInfo.ulMinKeySize; return MechanismInfo(mechanism, info);
info.maxKeySize = cInfo.ulMaxKeySize;
info.flags = cInfo.flags;
return info;
} }
/// Get a list of the Slot's mechanisms.
MechanismList mechanismlist() { MechanismList mechanismlist() {
CRYPTOLOG("log"); CRYPTOLOG("log");
MechanismList res; MechanismList res;
@ -930,7 +968,7 @@ namespace cryptoki {
return res; return res;
} }
for (CK_ULONG i(0); i<count; ++i) for (CK_ULONG i(0); i<count; ++i)
res.insert(mechanisms[i]); res.insert(mechanisminfo(mechanisms[i]));
} catch (...) { } catch (...) {
delete[] mechanisms; delete[] mechanisms;
throw; throw;
@ -961,18 +999,79 @@ namespace cryptoki {
return TokenInfo(cInfo); return TokenInfo(cInfo);
} }
/*! @bug does not compile: /// Initialize a token.
@code /** If the token has not been initialized (i.e. new from the
factory), then the @c pin parameter becomes the initial value
of the SO PIN. If the token is being reinitialized, the @c pin
parameter is checked against the existing SO PIN to
authorize the initialization operation. In both cases, the
SO PIN is the value @c pin after the function completes
successfully. If the SO PIN is lost, then the card must be
reinitialized using a mechanism outside the scope of this
standard. The CKF_TOKEN_INITIALIZED flag in the
CK_TOKEN_INFO structure indicates the action that will
result from calling C_InitToken. If set, the token will be
reinitialized, and the client must supply the existing SO
password in @c pin.
When a token is initialized, all objects that can be
destroyed are destroyed (i.e., all except for
indestructible objects such as keys built into the
token). Also, access by the normal user is disabled until
the SO sets the normal users PIN. Depending on the token,
some default objects may be created, and attributes of
some objects may be set to default values.
If the token has a protected authentication path, as
indicated by the CKF_PROTECTED_AUTHENTICATION_PATH flag in
its CK_TOKEN_INFO being set, then that means that there is
some way for a user to be authenticated to the token without
having the application send a PIN through the Cryptoki
library. One such possibility is that the user enters a PIN
on a PINpad on the token itself, or on the slot device. To
initialize a token with such a protected authentication
path, the @c pin parameter to C_InitToken should be empty.
During the execution of C_InitToken, the SOs PIN will be
entered through the protected authentication path.
If the token has a protected authentication path other than
a PINpad, then it is token- dependent whether or not
C_InitToken can be used to initialize the token.
A token cannot be initialized if Cryptoki detects that any
application has an open session with it; when a call to
C_InitToken is made under such circumstances, the call fails
with error CKR_SESSION_EXISTS. Unfortunately, it may happen
when C_InitToken is called that some other application does
have an open session with the token, but Cryptoki cannot
detect this, because it cannot detect anything about other
applications using the token. If this is the case, then the
consequences of the C_InitToken call are undefined.
The C_InitToken function may not be sufficient to properly
initialize complex tokens. In these situations, an
initialization mechanism outside the scope of Cryptoki must
be employed. The definition of complex token is product
specific.
@param pin SO's initial PIN
@param label label of the token */
bool inittoken(std::string pin, FixString<32> label) { bool inittoken(std::string pin, FixString<32> label) {
CRYPTOLOG("log"); CRYPTOLOG("log");
//! calls @c C_InitToken //! calls @c C_InitToken
return check(_library->C_InitToken if (pin.size())
(_slot, return check(_library->C_InitToken
(unsigned char*)&pin[0], pin.size(), (_slot,
(unsigned char*)label.&fix()[0]) (unsigned char*)&pin[0], pin.size(),
CRYPTOKI_FN_LOG("C_InitToken")); (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: /*! @todo Not implemented:
@code @code
@ -983,14 +1082,14 @@ namespace cryptoki {
bool registerforslotevent(SlotEventListener&) { bool registerforslotevent(SlotEventListener&) {
CRYPTOLOG("log"); CRYPTOLOG("log");
//! calls @c C_WaitForSlotEvent //! 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")); CRYPTOKI_FN_LOG("C_WaitForSlotEvent"));
} }
@endcode */ @endcode */
}; };
//! Session Management /// Session Management
//! Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); /** @note Not implemented: CK_RV C_CloseAllSessions(CK_SLOT_ID); */
class Session { class Session {
private: 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, inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
const cryptoki::Attribute& attr) { const cryptoki::Attribute& attr) {
CRYPTOLOG("log"); CRYPTOLOG("log");
list.push_back(attr); list.push_back(attr);
return list; return list;
} }
/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList.
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list, inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
const cryptoki::Attribute& attr) { const cryptoki::Attribute& attr) {
CRYPTOLOG("log"); CRYPTOLOG("log");
@ -2184,5 +2285,4 @@ inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
} }
//@} //@}
//@}
#endif #endif

@ -133,6 +133,12 @@ namespace suisseid {
no_digsig() throw(): no_digsig() throw():
exception("no digital signature certificate found") {} 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 */ /*! @addtogroup suisseidtypes */
@ -145,9 +151,12 @@ namespace suisseid {
/*! @addtogroup suisseidconsts */ /*! @addtogroup suisseidconsts */
//@{ //@{
const std::string NON_REP = "SwissSign_nonRep "; /// Label of the key for digital signature certificate.
const std::string DIG_SIG = "SwissSign_digSig "; const std::string NON_REP = "SwissSign_nonRep ";
const std::string DATA_ENC = "SwissSign_dataEnc "; /// 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 */ /*! @addtogroup suisseidlib */
@ -160,16 +169,22 @@ namespace suisseid {
public: public:
/// Status of the card's certificates
/** @note by now, only @c MISSING and @c VALID is supported */
enum CertStatus { enum CertStatus {
MISSING, MISSING, ///< certificate is missing, needs initiatlization
EXPIRES_SOON, EXPIRES_SOON, ///< certificate will soon expire, needs renewal
EXPIRED, EXPIRED, ///< certificate is expired, needs new purchase
REVOKED, REVOKED, ///< certificate has been revoked and is invalid
VALID VALID ///< certificate is valid
}; };
public: 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<pcsc::Connection::Reader> reader, Card(mrw::Shared<pcsc::Connection::Reader> reader,
const cryptoki::Library& cryptoki): const cryptoki::Library& cryptoki):
cardos::Commands(reader), cardos::Commands(reader),
@ -177,13 +192,17 @@ namespace suisseid {
} }
virtual ~Card() {} 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::Slot slot() {
cryptoki::SlotList slots(_cryptoki.slotList(true, name())); cryptoki::SlotList slots(_cryptoki.slotList(true, name()));
if (slots.size()==1) return slots[0]; 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; virtual unsigned int minimalPinLength() = 0;
/// Maximum allowed PIN length for this card.
virtual unsigned int maximalPinLength() = 0; virtual unsigned int maximalPinLength() = 0;
//! Name of the token/slot //! Name of the token/slot
@ -196,15 +215,17 @@ namespace suisseid {
return "<unknown>"; return "<unknown>";
} }
/// status of the certificates on the card /// Status of the certificates on the card
virtual CertStatus certStatus() { virtual CertStatus certStatus() {
return MISSING; return MISSING;
} }
/// Starts and returns a cryptoki::Session.
cryptoki::Session session() { cryptoki::Session session() {
return cryptoki::Session(slot()); return cryptoki::Session(slot());
} }
/// Starts a cryptoki::Session and returns cryptoki::Session::Info.
cryptoki::Session::Info sessionInfo() { cryptoki::Session::Info sessionInfo() {
return session().getsessioninfo(); return session().getsessioninfo();
} }
@ -259,6 +280,7 @@ namespace suisseid {
public: public:
/// @copydoc Card::Card
Post(mrw::Shared<pcsc::Connection::Reader> reader, Post(mrw::Shared<pcsc::Connection::Reader> reader,
const cryptoki::Library& cryptoki): const cryptoki::Library& cryptoki):
Card(reader, cryptoki), _minPinLen(0), _maxPinLen(-1) { Card(reader, cryptoki), _minPinLen(0), _maxPinLen(-1) {

Loading…
Cancel
Save