added draft lib for suisseid - by now: detect Post SuisseID; refs #28

master
Marc Wäckerlin 11 years ago
parent 91b075d61b
commit 1de9676582
  1. 2
      configure.in
  2. 6
      doc/examples/cryptoki-demo.cxx
  3. 2
      doc/examples/cryptoki-sign-demo.cxx
  4. 2
      doc/examples/pcsc-demo.cxx
  5. 96
      doc/examples/suisse-id-demo.cxx
  6. 97
      src/cryptoki.cxx
  7. 356
      src/cryptoki.hxx
  8. 628
      src/pcsc.hxx

@ -21,7 +21,7 @@ TST_DIR=
DOC_DIR=doc DOC_DIR=doc
m4_define(x_packagename, libpcscxx) m4_define(x_packagename, libpcscxx)
m4_define(x_major, 1) m4_define(x_major, 2)
m4_define(x_minor, 0) m4_define(x_minor, 0)
PACKAGENAME=x_packagename PACKAGENAME=x_packagename
MAJOR=x_major MAJOR=x_major

@ -12,8 +12,8 @@ int main(int argc, char const*const*const argv) try {
// //std::vector<int> v(toVector<4>((int[]){1,2,3,4})); // //std::vector<int> v(toVector<4>((int[]){1,2,3,4}));
// std::vector<int> v(VECTOR(((int[]){1,2,3,4}))); // std::vector<int> v(VECTOR(((int[]){1,2,3,4})));
// print(v); // print(v);
cryptoki::Init init(argc==2?argv[1]:"onepin-opensc-pkcs11.so"); cryptoki::Library cryptoki(argc==2?argv[1]:"onepin-opensc-pkcs11.so");
cryptoki::Info inf(init.info()); cryptoki::Info inf(cryptoki.info());
std::cout<<"Library-Version: "<<pcsc::version()<<std::endl; std::cout<<"Library-Version: "<<pcsc::version()<<std::endl;
std::cout<<"##################### INFO #####################"<<std::endl std::cout<<"##################### INFO #####################"<<std::endl
<<"cryptokiVersion: \""<<(int)inf.cryptokiVersion.major <<"cryptokiVersion: \""<<(int)inf.cryptokiVersion.major
@ -23,7 +23,7 @@ int main(int argc, char const*const*const argv) try {
<<"libraryDescription: \""<<inf.libraryDescription<<'"'<<std::endl <<"libraryDescription: \""<<inf.libraryDescription<<'"'<<std::endl
<<"libraryVersion: \""<<(int)inf.libraryVersion.major <<"libraryVersion: \""<<(int)inf.libraryVersion.major
<<'.'<<(int)inf.libraryVersion.minor<<'"'<<std::endl; <<'.'<<(int)inf.libraryVersion.minor<<'"'<<std::endl;
cryptoki::SlotList slots(init.slotList()); cryptoki::SlotList slots(cryptoki.slotList());
for (cryptoki::SlotList::iterator it(slots.begin()); it!=slots.end(); ++it) for (cryptoki::SlotList::iterator it(slots.begin()); it!=slots.end(); ++it)
try { try {
cryptoki::SlotInfo slotInfo(it->slotinfo()); cryptoki::SlotInfo slotInfo(it->slotinfo());

@ -58,7 +58,7 @@ int main(int argc, char** argv) try {
<<"-----------------------------------------------------"<<std::endl <<"-----------------------------------------------------"<<std::endl
<<txt<<std::endl <<txt<<std::endl
<<"-----------------------------------------------------"<<std::endl; <<"-----------------------------------------------------"<<std::endl;
cryptoki::Init c(lib); cryptoki::Library c(lib);
cryptoki::SlotList sl(c.slotList()); cryptoki::SlotList sl(c.slotList());
for (cryptoki::SlotList::iterator s(sl.begin()); s!=sl.end(); ++s) { for (cryptoki::SlotList::iterator s(sl.begin()); s!=sl.end(); ++s) {
cryptoki::SlotInfo si(s->slotinfo()); cryptoki::SlotInfo si(s->slotinfo());

@ -11,7 +11,7 @@ int main(int, char const*const*const argv) try {
for (pcsc::Connection::Strings::const_iterator it(reader.begin()); for (pcsc::Connection::Strings::const_iterator it(reader.begin());
it!=reader.end(); ++it) { it!=reader.end(); ++it) {
std::cout<<"Reader: "<<*it<<std::endl; std::cout<<"Reader: "<<*it<<std::endl;
pcsc::Connection::Reader::Status s(c.reader(*it).status()); pcsc::Connection::Reader::Status s(c.reader(*it)->status());
std::cout<<"Status = "<<s.state<<std::endl; std::cout<<"Status = "<<s.state<<std::endl;
std::cout<<"ATR = "<<crypto::hex(s.atr)<<std::endl; std::cout<<"ATR = "<<crypto::hex(s.atr)<<std::endl;
} }

@ -9,10 +9,87 @@
#include <pcsc.hxx> #include <pcsc.hxx>
#include <mrw/args.hxx> #include <mrw/args.hxx>
#include <mrw/vector.hxx> #include <mrw/vector.hxx>
#include <mrw/shared.hxx>
#include <stdexcept> #include <stdexcept>
#include <iostream> #include <iostream>
namespace suisseid {
class Card {
public:
Card(mrw::Shared<pcsc::Connection::Reader> reader,
mrw::Shared<cryptoki::Slot> slot):
_reader(reader),
_slot(slot) {
}
virtual ~Card() {}
const std::string& name() {
return _reader->name;
}
private:
mrw::Shared<pcsc::Connection::Reader> _reader;
mrw::Shared<cryptoki::Slot> _slot;
};
class PostSuisseID: public Card {
public:
PostSuisseID(mrw::Shared<pcsc::Connection::Reader> reader,
mrw::Shared<cryptoki::Slot> slot):
Card(reader, slot) {
}
};
class Manager {
public:
Manager(const std::string& lib="libcvP11.so"):
_cryptoki(lib) {
}
Manager(const pcsc::Connection& pcsc,
const std::string& lib="libcvP11.so"):
_pcsc(pcsc),
_cryptoki(lib) {
}
Manager(const cryptoki::Library& cryptoki):
_cryptoki(cryptoki) {
}
Manager(const pcsc::Connection& pcsc,
const cryptoki::Library& cryptoki):
_pcsc(pcsc),
_cryptoki(cryptoki) {
}
typedef std::vector<mrw::Shared<Card> > Cards;
Cards scan() {
Cards res;
// By now, scan only for PostSuisseID; in future use factory pattern
pcsc::Connection::Strings readers
(_pcsc.getReadersWithAtr("4b53776973735369676e"));
for (pcsc::Connection::Strings::iterator reader(readers.begin());
reader!=readers.end(); ++reader) {
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
if (slots.size()==1)
res.push_back(dynamic_cast<Card*>
(new PostSuisseID(_pcsc.reader(*reader), slots[0])));
}
return res;
}
private:
pcsc::Connection _pcsc;
cryptoki::Library _cryptoki;
};
}
int main(int argc, char** argv) try { int main(int argc, char** argv) try {
std::string lib("libcvP11.so"); std::string lib("libcvP11.so");
@ -28,20 +105,11 @@ int main(int argc, char** argv) try {
mrw::args::decl::param_list() mrw::args::decl::param_list()
<<mrw::args::param(lib, "lib"))); <<mrw::args::param(lib, "lib")));
pcsc::Connection pcsc; suisseid::Manager suisseid;
cryptoki::Init cryptoki(lib); suisseid::Manager::Cards cards(suisseid.scan());
for (suisseid::Manager::Cards::iterator card(cards.begin());
// Scan for a Post SuisseID card!=cards.end(); ++card)
pcsc::Connection::Strings readers std::cout<<"Found SuisseID: "<<(*card)->name()<<std::endl;
(pcsc.getReadersWithAtr("4b53776973735369676e"));
std::cout<<"found "<<readers.size()<<" readers"<<std::endl;
for (pcsc::Connection::Strings::iterator reader(readers.begin());
reader!=readers.end(); ++reader) {
std::cout<<"Found SuisseID in reader: "<<*reader<<std::endl;
// Each PCSC reader has exactly one corresponding Cryptoki slot; find it
cryptoki::SlotList slots(cryptoki.slotList(true, *reader));
if (slots.size()!=1) throw std::runtime_error("error scanning cryptoki");
}
return 0; return 0;
} catch (std::exception& x) { } catch (std::exception& x) {
std::cerr<<"**** ERROR in "<<*argv<<": "<<x.what()<<std::endl; std::cerr<<"**** ERROR in "<<*argv<<": "<<x.what()<<std::endl;

@ -23,21 +23,21 @@ typedef CK_RV (*CK_C_GetFunctionList)
namespace cryptoki { namespace cryptoki {
bool Init::functionList(const std::string& library) { bool Library::Init::functionList(const std::string& library) {
CRYPTOKI_LOG("try to load: "<<library); CRYPTOKI_LOG("try to load: "<<library);
#ifndef WIN32 #ifndef WIN32
void* lib(dlopen(library.c_str(), RTLD_NOW)); _lib = dlopen(library.c_str(), RTLD_NOW);
#else #else
HINSTANCE lib(LoadLibrary(library.c_str())); _lib = LoadLibrary(library.c_str());
#endif #endif
if (!lib) throw exception("open of library failed: "+library); if (!_lib) throw exception("open of library failed: "+library);
CRYPTOKI_LOG("loaded: "<<library); CRYPTOKI_LOG("loaded: "<<library);
#ifndef WIN32 #ifndef WIN32
CK_C_GetFunctionList fn CK_C_GetFunctionList fn
((CK_C_GetFunctionList)dlsym(lib, "C_GetFunctionList")); ((CK_C_GetFunctionList)dlsym(_lib, "C_GetFunctionList"));
#else #else
CK_C_GetFunctionList fn CK_C_GetFunctionList fn
((CK_C_GetFunctionList)GetProcAddress(lib, "C_GetFunctionList")); ((CK_C_GetFunctionList)GetProcAddress(_lib, "C_GetFunctionList"));
#endif #endif
if (!fn) if (!fn)
throw exception("required library symbol C_GetFunctionList not found in " throw exception("required library symbol C_GetFunctionList not found in "
@ -47,7 +47,7 @@ namespace cryptoki {
return check(fn(&_fn), CRYPTOKI_FN_LOG("C_GetFunctionList")); return check(fn(&_fn), CRYPTOKI_FN_LOG("C_GetFunctionList"));
} }
bool Init::check(CK_RV result, const std::string& context) { bool Library::Init::check(CK_RV result, const std::string& context) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
_res = result; _res = result;
if (_exc && !*this) if (_exc && !*this)
@ -58,7 +58,7 @@ namespace cryptoki {
return _res==CKR_OK; return _res==CKR_OK;
} }
std::string Init::error(CK_RV res) { std::string Library::Init::error(CK_RV res) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
switch (res) { switch (res) {
case CKR_OK: return "CKR_OK"; case CKR_OK: return "CKR_OK";
@ -166,56 +166,75 @@ namespace cryptoki {
} }
} }
Init::Init(const std::string& library, bool exc) try: Library::Init::Init(const std::string& library, bool exc) try:
_exc(exc), _res(CKR_OK), _fn(0) { _exc(exc), _res(CKR_OK), _fn(0) {
CRYPTOKI_LOG("library: "<<library); CRYPTOKI_LOG("library: "<<library);
//! calls @c functionList //! calls @c functionList
if (!functionList(library)) return; if (!functionList(library)) return;
CRYPTOKI_LOG("now initialize "<<library); CRYPTOKI_LOG("now initialize "<<library);
assert(_fn); assert(_fn);
//! calls @c C_Initialize //! calls @c C_Initialize
check(_fn->C_Initialize(0), //! @todo add optional argument check(_fn->C_Initialize(0), //! @todo add optional argument
CRYPTOKI_FN_LOG("C_Initialize")); CRYPTOKI_FN_LOG("C_Initialize"));
} catch (...) { } catch (...) {
throw access_error(CRYPTOKI_FN_LOG("C_Initialize") throw access_error(CRYPTOKI_FN_LOG("C_Initialize")
+": Error in initialization of library "+library); +": Error in initialization of library "+library);
} }
Init::operator bool() { Library::Init::~Init() {
CRYPTOKI_LOG("log");
try {
//! calls @c C_Finalize
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize"));
#ifndef WIN32
if (_lib) dlclose(_lib);
_lib = 0;
#else
FreeLibrary(_lib);
_lib = 0;
#endif
_fn = 0;
} catch (...) {
if (!std::uncaught_exception()) throw;
}
}
Library::Init::operator bool() {
CRYPTOKI_LOG("log "<<(_res==CKR_OK?"success":"failed")); CRYPTOKI_LOG("log "<<(_res==CKR_OK?"success":"failed"));
return _res==CKR_OK; return _res==CKR_OK;
} }
std::string Init::error() { std::string Library::Init::error() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
return error(_res); return error(_res);
} }
/*! @todo Not implemented: /*! @todo Not implemented:
@code @code
bool Init::getinfo() { bool Library::Init::getinfo() {
//! calls @c C_GetInfo //! calls @c C_GetInfo
return check(_init._fn->C_GetInfo(CK_INFO_PTR), return check(_init._fn->C_GetInfo(CK_INFO_PTR),
CRYPTOKI_FN_LOG("C_GetInfo")); CRYPTOKI_FN_LOG("C_GetInfo"));
} }
@endcode */ @endcode */
SlotList Init::slotList(bool tokenPresent, std::string name) { SlotList Library::slotList(bool tokenPresent, std::string name) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
SlotList res; SlotList res;
CK_ULONG count(0); CK_ULONG count(0);
//! calls @c C_GetSlotList //! calls @c C_GetSlotList
check(_fn->C_GetSlotList(tokenPresent?TRUE:FALSE, 0, &count), _init->check(_init->_fn->C_GetSlotList(tokenPresent?TRUE:FALSE, 0, &count),
CRYPTOKI_FN_LOG("C_GetSlotList")); CRYPTOKI_FN_LOG("C_GetSlotList"));
if (!count || !*this) return res; if (!count || !*this) return res;
CK_SLOT_ID* slots = 0; CK_SLOT_ID* slots = 0;
try { try {
CK_RV r(0);
do { do {
delete[] slots; delete[] slots;
slots = new CK_SLOT_ID[count]; slots = new CK_SLOT_ID[count];
_res = _fn->C_GetSlotList(tokenPresent?TRUE:FALSE, slots, &count); r = _init->_fn->C_GetSlotList(tokenPresent?TRUE:FALSE, slots, &count);
} while (_res==CKR_BUFFER_TOO_SMALL); } while (r==CKR_BUFFER_TOO_SMALL);
check(_res, CRYPTOKI_FN_LOG("C_GetSlotList")); _init->check(r, CRYPTOKI_FN_LOG("C_GetSlotList"));
if (!*this) return res; if (!*this) return res;
for (CK_ULONG i(0); i<count; ++i) { for (CK_ULONG i(0); i<count; ++i) {
Slot s(*this, slots[i]); Slot s(*this, slots[i]);
@ -243,19 +262,19 @@ namespace cryptoki {
a[i] = attrs[i]; a[i] = attrs[i];
} }
//! calls @c C_FindObjectsInit //! calls @c C_FindObjectsInit
if (check(_slot._init->_fn->C_FindObjectsInit if (check(_slot->_library->C_FindObjectsInit
(_session, a, attrs.size()), (_session, a, attrs.size()),
CRYPTOKI_FN_LOG("C_FindObjectsInit"))) { CRYPTOKI_FN_LOG("C_FindObjectsInit"))) {
CK_OBJECT_HANDLE obj; CK_OBJECT_HANDLE obj;
//! calls @c C_FindObjects //! calls @c C_FindObjects
for (CK_ULONG objs(0); for (CK_ULONG objs(0);
check(_slot._init->_fn->C_FindObjects check(_slot->_library->C_FindObjects
(_session, &obj, 1, &objs), (_session, &obj, 1, &objs),
CRYPTOKI_FN_LOG("C_FindObjects")) && objs; CRYPTOKI_FN_LOG("C_FindObjects")) && objs;
res.push_back(Object(*this, obj))); res.push_back(Object(*this, obj)));
} }
//! calls @c C_FindObjectsFinal //! calls @c C_FindObjectsFinal
check(_slot._init->_fn->C_FindObjectsFinal(_session), check(_slot->_library->C_FindObjectsFinal(_session),
CRYPTOKI_FN_LOG("C_FindObjectsFinal")); CRYPTOKI_FN_LOG("C_FindObjectsFinal"));
delete[] a; delete[] a;
return res; return res;
@ -362,7 +381,7 @@ namespace cryptoki {
}; };
CK_OBJECT_HANDLE object; CK_OBJECT_HANDLE object;
//! calls @c C_CreateObject //! calls @c C_CreateObject
check(_slot._init->_fn->C_CreateObject check(_slot->_library->C_CreateObject
(_session, a, attrs.size(), &object), (_session, a, attrs.size(), &object),
CRYPTOKI_FN_LOG("C_CreateObject")); CRYPTOKI_FN_LOG("C_CreateObject"));
delete[] a; delete[] a;

@ -18,15 +18,16 @@
#include <vector> #include <vector>
#include <map> #include <map>
#include <set> #include <set>
#include <mrw/shared.hxx>
// for inline implementations only // for inline implementations only
#include <cryptaux.hxx>
#include <sstream> #include <sstream>
#include <cstdlib> // malloc/free #include <cstdlib> // malloc/free
#include <cstring> // memset #include <cstring> // memset
#include <cassert> // assert #include <cassert> // assert
#include <iomanip> #include <iomanip>
#include <memory> #include <memory>
#include <cryptaux.hxx>
/*! @defgroup gcryptoki C++ Wrapper around Cryptoki API */ /*! @defgroup gcryptoki C++ Wrapper around Cryptoki API */
//@{ //@{
@ -624,77 +625,127 @@ namespace cryptoki {
//@{ //@{
//! to be instanciated before first use //! to be instanciated before first use
class Init { class Library {
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: public:
//! Initialize for a given library (default cryptoki) //! Initialize for a given library (default cryptoki)
/*! Please notem, that you must not instanciate more than one /*! Please notem, that you must not instanciate more than one
Init per unique function list! Init per unique function list!
@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 */
Init(const std::string& library="opensc-pkcs11.so", bool exc=true); Library(const std::string& library="opensc-pkcs11.so", bool exc=true):
_init(library, exc) {
~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;
}
} }
public:
class Init {
Init& reset() { private:
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 friend class Library;
bool _exc;
CK_RV _res;
CK_FUNCTION_LIST* _fn;
#ifndef WIN32
void* _lib;
#else
HINSTANCE _lib;
#endif
//! Initialize Funcion List for this Instance
bool functionList(const std::string& library);
bool check(CK_RV result, const std::string& context="");
/*! @return error text of last cryptoki call */
std::string error(CK_RV res);
public:
//! 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();
Init& reset() {
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize"));
check(_fn->C_Initialize(0), CRYPTOKI_FN_LOG("C_Initialize"));
return *this;
}
CK_FUNCTION_LIST* fn() {
return _fn;
}
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
handling. If you disable it, you must check after every
operation whether it was successful or not. These methods
provide all you need for that. */
//@{
/*! @return @c true if last cryptoki on this object call was
successful */
operator bool();
/*! @return error text of last cryptoki call */
std::string error();
//@}
};
public:
CK_FUNCTION_LIST* operator->() {
return _init->fn();
}
bool exc() {
return _init->_exc;
}
/*! @name C Like Error Handling
You are strongly recommended not to disable exception You are strongly recommended not to disable exception
handling. If you disable it, you must check after every handling. If you disable it, you must check after every
operation whether it was successful or not. These methods operation whether it was successful or not. These methods
provide all you need for that. */ provide all you need for that. */
//@{ //@{
/*! @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 error text of last cryptoki call */ /*! @return error text of last cryptoki call */
std::string error(); std::string error() {
return _init->error();
}
std::string error(CK_RV res) {
return _init->error(res);
}
//@} //@}
Info info() { Info info() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
Info inf; Info inf;
CK_INFO cInf; CK_INFO cInf;
//! calls @c C_GetInfo //! calls @c C_GetInfo
if (!check(_fn->C_GetInfo(&cInf), CRYPTOKI_FN_LOG("C_GetInfo"))) if (!_init->check(_init->fn()
->C_GetInfo(&cInf), CRYPTOKI_FN_LOG("C_GetInfo")))
return inf; return inf;
inf.cryptokiVersion = cInf.cryptokiVersion; inf.cryptokiVersion = cInf.cryptokiVersion;
inf.manufacturerID = cInf.manufacturerID; inf.manufacturerID = cInf.manufacturerID;
@ -703,36 +754,42 @@ namespace cryptoki {
inf.libraryVersion = cInf.libraryVersion; inf.libraryVersion = cInf.libraryVersion;
return inf; return inf;
} }
//! Get a list of available slots //! Get a list of available slots
/*! @param tokenPresent whether a token must be inserted into the reader /*! @param tokenPresent whether a token must be inserted into the
reader
@param name if given, only return slots with a given name @param name if given, only return slots with a given name
@return list of matching slots */ @return list of matching slots */
SlotList slotList(bool tokenPresent=true, std::string name=std::string()); SlotList slotList(bool tokenPresent=true,
std::string name=std::string());
}; private:
mrw::Shared<Init> _init;
};
//! Slot and Token Management //! Slot and Token Management
class Slot { class Slot {
private: private:
friend class Init; friend class Library;
friend class Session; friend class Session;
friend class Object; friend class Object;
Init* _init; Library _library;
CK_SLOT_ID _slot; CK_SLOT_ID _slot;
CK_RV _res; CK_RV _res;
Slot(Init& init, CK_SLOT_ID slot): Slot(const Library& lib, CK_SLOT_ID slot):
_init(&init), _slot(slot), _res(CKR_OK) { _library(lib), _slot(slot), _res(CKR_OK) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
} }
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
_res = result; _res = result;
if (_init->_exc && !*this) if (_library.exc() && !*this)
if (!context.empty()) if (!context.empty())
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else else
@ -743,13 +800,13 @@ namespace cryptoki {
public: public:
//! Don't use without assignment! For standard containers only! //! Don't use without assignment! For standard containers only!
Slot(): _init(0) { Slot() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
} }
Slot& operator=(const Slot& o) { Slot& operator=(const Slot& o) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
_init = o._init; _library = o._library;
_slot = o._slot; _slot = o._slot;
_res = o._res; _res = o._res;
return *this; return *this;
@ -772,7 +829,7 @@ namespace cryptoki {
/*! @return error text of last cryptoki call */ /*! @return error text of last cryptoki call */
std::string error() { std::string error() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
return _init->error(_res); return _library.error(_res);
} }
//@} //@}
@ -782,7 +839,7 @@ namespace cryptoki {
MechanismInfo info(mechanism); MechanismInfo info(mechanism);
CK_MECHANISM_INFO cInfo; CK_MECHANISM_INFO cInfo;
//! calls @c C_GetMechanismInfo //! calls @c C_GetMechanismInfo
check(_init->_fn->C_GetMechanismInfo(_slot, mechanism, &cInfo), check(_library->C_GetMechanismInfo(_slot, mechanism, &cInfo),
CRYPTOKI_FN_LOG("C_GetMechanismInfo")); CRYPTOKI_FN_LOG("C_GetMechanismInfo"));
info.minKeySize = cInfo.ulMinKeySize; info.minKeySize = cInfo.ulMinKeySize;
info.maxKeySize = cInfo.ulMaxKeySize; info.maxKeySize = cInfo.ulMaxKeySize;
@ -795,12 +852,12 @@ namespace cryptoki {
MechanismList res; MechanismList res;
CK_ULONG count(0); CK_ULONG count(0);
//! calls @c C_GetMechanismList //! calls @c C_GetMechanismList
if (!check(_init->_fn->C_GetMechanismList(_slot, 0, &count), if (!check(_library->C_GetMechanismList(_slot, 0, &count),
CRYPTOKI_FN_LOG("C_GetMechanismList")) || !count) return res; CRYPTOKI_FN_LOG("C_GetMechanismList")) || !count) return res;
CK_MECHANISM_TYPE* mechanisms = 0; CK_MECHANISM_TYPE* mechanisms = 0;
try { try {
mechanisms = new CK_MECHANISM_TYPE[count]; mechanisms = new CK_MECHANISM_TYPE[count];
if (!check(_init->_fn->C_GetMechanismList(_slot, mechanisms, &count), if (!check(_library->C_GetMechanismList(_slot, mechanisms, &count),
CRYPTOKI_FN_LOG("C_GetMechanismList"))) { CRYPTOKI_FN_LOG("C_GetMechanismList"))) {
delete[] mechanisms; delete[] mechanisms;
return res; return res;
@ -820,7 +877,7 @@ namespace cryptoki {
SlotInfo info; SlotInfo info;
CK_SLOT_INFO cInfo; CK_SLOT_INFO cInfo;
//! calls @c C_GetSlotInfo //! calls @c C_GetSlotInfo
if (!check(_init->_fn->C_GetSlotInfo(_slot, &cInfo), if (!check(_library->C_GetSlotInfo(_slot, &cInfo),
CRYPTOKI_FN_LOG("C_GetSlotInfo"))) return info; CRYPTOKI_FN_LOG("C_GetSlotInfo"))) return info;
info.slotDescription = cInfo.slotDescription; info.slotDescription = cInfo.slotDescription;
info.manufacturerID = cInfo.manufacturerID; info.manufacturerID = cInfo.manufacturerID;
@ -835,7 +892,7 @@ namespace cryptoki {
TokenInfo info; TokenInfo info;
//! calls @c C_GetTokenInfo //! calls @c C_GetTokenInfo
CK_TOKEN_INFO cInfo; CK_TOKEN_INFO cInfo;
if (!check(_init->_fn->C_GetTokenInfo(_slot, &cInfo), if (!check(_library->C_GetTokenInfo(_slot, &cInfo),
CRYPTOKI_FN_LOG("C_GetTokenInfo"))) return info; CRYPTOKI_FN_LOG("C_GetTokenInfo"))) return info;
info.label = cInfo.label; info.label = cInfo.label;
info.manufacturerID = cInfo.manufacturerID; info.manufacturerID = cInfo.manufacturerID;
@ -863,7 +920,7 @@ namespace cryptoki {
bool inittoken(std::string pin, FixString<32> label) { bool inittoken(std::string pin, FixString<32> label) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_InitToken //! calls @c C_InitToken
return check(_init->_fn->C_InitToken return check(_library->C_InitToken
(_slot, (_slot,
(unsigned char*)&pin[0], pin.size(), (unsigned char*)&pin[0], pin.size(),
(unsigned char*)label.&fix()[0]) (unsigned char*)label.&fix()[0])
@ -880,7 +937,7 @@ namespace cryptoki {
bool registerforslotevent(SlotEventListener&) { bool registerforslotevent(SlotEventListener&) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_WaitForSlotEvent //! calls @c C_WaitForSlotEvent
return check(_init->_fn->C_WaitForSlotEvent(CK_FLAGS, &_slot, CK_VOID_PTR), return check(_library->C_WaitForSlotEvent(CK_FLAGS, &_slot, CK_VOID_PTR),
CRYPTOKI_FN_LOG("C_WaitForSlotEvent")); CRYPTOKI_FN_LOG("C_WaitForSlotEvent"));
} }
@endcode */ @endcode */
@ -894,23 +951,16 @@ namespace cryptoki {
friend class Login; friend class Login;
friend class Object; friend class Object;
CK_FUNCTION_LIST* fn() { mrw::Shared<Slot> _slot;
return _slot._init->_fn;
}
Slot& _slot;
CK_SESSION_HANDLE _session; CK_SESSION_HANDLE _session;
CK_RV _res; CK_RV _res;
Session(); // forbidden Session(); // forbidden
Session(const Session& o); // no-copy
Session& operator=(const Session& o); // no-copy
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
_res = result; _res = result;
if (_slot._init->_exc && !*this) if (_slot->_library.exc() && !*this)
if (!context.empty()) if (!context.empty())
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else else
@ -926,13 +976,13 @@ namespace cryptoki {
} catch (...) { // still try to close session } catch (...) { // still try to close session
//! calls @c C_CloseSession //! calls @c C_CloseSession
try { try {
check(_slot._init->_fn->C_CloseSession(_session), check(_slot->_library->C_CloseSession(_session),
CRYPTOKI_FN_LOG("C_CloseSession")); CRYPTOKI_FN_LOG("C_CloseSession"));
} catch (...) {} // only report first problem } catch (...) {} // only report first problem
throw; throw;
} }
//! calls @c C_CloseSession //! calls @c C_CloseSession
check(_slot._init->_fn->C_CloseSession(_session), check(_slot->_library->C_CloseSession(_session),
CRYPTOKI_FN_LOG("C_CloseSession")); CRYPTOKI_FN_LOG("C_CloseSession"));
} }
@ -940,12 +990,12 @@ namespace cryptoki {
//! Opens a new session. //! Opens a new session.
/*! @param slot slot to open a session on */ /*! @param slot slot to open a session on */
Session(Slot& slot, bool rw=false): Session(mrw::Shared<Slot> slot, bool rw=false):
_slot(slot), _session(0), _res(CKR_OK), _login(0) { _slot(slot), _session(0), _res(CKR_OK) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_OpenSession //! calls @c C_OpenSession
check(_slot._init->_fn->C_OpenSession check(_slot->_library->C_OpenSession
(_slot._slot, CKF_SERIAL_SESSION|(rw?CKF_RW_SESSION:0), (_slot->_slot, CKF_SERIAL_SESSION|(rw?CKF_RW_SESSION:0),
0, 0, &_session), 0, 0, &_session),
CRYPTOKI_FN_LOG("C_OpenSession")); CRYPTOKI_FN_LOG("C_OpenSession"));
//! @todo pass parameter //! @todo pass parameter
@ -997,7 +1047,7 @@ namespace cryptoki {
/*! @return error text of last cryptoki call */ /*! @return error text of last cryptoki call */
std::string error() { std::string error() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
return _slot._init->error(_res); return _slot->_library.error(_res);
} }
//@} //@}
@ -1011,7 +1061,7 @@ namespace cryptoki {
bool cancel() { bool cancel() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_CancelFunction //! calls @c C_CancelFunction
return check(_slot._init->_fn->C_CancelFunction(_session), return check(_slot->_library->C_CancelFunction(_session),
CRYPTOKI_FN_LOG("C_CancelFunction")); CRYPTOKI_FN_LOG("C_CancelFunction"));
} }
@ -1024,7 +1074,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_Digest //! calls @c C_Digest
check(_slot._init->_fn->C_Digest check(_slot->_library->C_Digest
(_session, (_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1039,7 +1089,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DigestEncryptUpdate //! calls @c C_DigestEncryptUpdate
check(_slot._init->_fn->C_DigestEncryptUpdate check(_slot->_library->C_DigestEncryptUpdate
(_session, (_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1053,7 +1103,7 @@ namespace cryptoki {
bool digestfinal() { bool digestfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DigestFinal //! calls @c C_DigestFinal
return check(_slot._init->_fn->C_DigestFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR), return check(_slot->_library->C_DigestFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_DigestFinal")); CRYPTOKI_FN_LOG("C_DigestFinal"));
} }
@endcode */ @endcode */
@ -1063,7 +1113,7 @@ namespace cryptoki {
bool digestinit() { bool digestinit() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DigestInit //! calls @c C_DigestInit
return check(_slot._init->_fn->C_DigestInit(_session, CK_MECHANISM_PTR), return check(_slot->_library->C_DigestInit(_session, CK_MECHANISM_PTR),
CRYPTOKI_FN_LOG("C_DigestInit")); CRYPTOKI_FN_LOG("C_DigestInit"));
} }
@endcode */ @endcode */
@ -1073,7 +1123,7 @@ namespace cryptoki {
bool digestupdate() { bool digestupdate() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DigestUpdate //! calls @c C_DigestUpdate
return check(_slot._init->_fn->C_DigestUpdate(_session, CK_BYTE_PTR, CK_ULONG), return check(_slot->_library->C_DigestUpdate(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_DigestUpdate")); CRYPTOKI_FN_LOG("C_DigestUpdate"));
} }
@endcode */ @endcode */
@ -1083,7 +1133,7 @@ namespace cryptoki {
bool findobjectsfinal() { bool findobjectsfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_FindObjectsFinal //! calls @c C_FindObjectsFinal
return check(_slot._init->_fn->C_FindObjectsFinal(_session), return check(_slot->_library->C_FindObjectsFinal(_session),
CRYPTOKI_FN_LOG("C_FindObjectsFinal")); CRYPTOKI_FN_LOG("C_FindObjectsFinal"));
} }
@endcode */ @endcode */
@ -1093,7 +1143,7 @@ namespace cryptoki {
bool findobjectsinit() { bool findobjectsinit() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_FindObjectsInit //! calls @c C_FindObjectsInit
return check(_slot._init->_fn->C_FindObjectsInit(_session, CK_ATTRIBUTE_PTR, CK_ULONG), return check(_slot->_library->C_FindObjectsInit(_session, CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_FindObjectsInit")); CRYPTOKI_FN_LOG("C_FindObjectsInit"));
} }
@endcode */ @endcode */
@ -1103,7 +1153,7 @@ namespace cryptoki {
bool findobjects() { bool findobjects() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_FindObjects //! calls @c C_FindObjects
return check(_session._slot._init->_fn->C_FindObjects(_session, CK_OBJECT_HANDLE_PTR, CK_ULONG, return check(_session->_slot->_library->C_FindObjects(_session, CK_OBJECT_HANDLE_PTR, CK_ULONG,
CK_ULONG_PTR), CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_FindObjects")); CRYPTOKI_FN_LOG("C_FindObjects"));
} }
@ -1114,7 +1164,7 @@ namespace cryptoki {
bool generaterandom() { bool generaterandom() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GenerateRandom //! calls @c C_GenerateRandom
return check(_slot._init->_fn->C_GenerateRandom(_session, CK_BYTE_PTR, CK_ULONG), return check(_slot->_library->C_GenerateRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_GenerateRandom")); CRYPTOKI_FN_LOG("C_GenerateRandom"));
} }
@endcode */ @endcode */
@ -1124,7 +1174,7 @@ namespace cryptoki {
bool getfunctionstatus() { bool getfunctionstatus() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GetFunctionStatus //! calls @c C_GetFunctionStatus
return check(_slot._init->_fn->C_GetFunctionStatus(_session), return check(_slot->_library->C_GetFunctionStatus(_session),
CRYPTOKI_FN_LOG("C_GetFunctionStatus")); CRYPTOKI_FN_LOG("C_GetFunctionStatus"));
} }
@endcode */ @endcode */
@ -1134,7 +1184,7 @@ namespace cryptoki {
bool getoperationstate() { bool getoperationstate() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GetOperationState //! calls @c C_GetOperationState
return check(_slot._init->_fn->C_GetOperationState(_session, CK_BYTE_PTR, CK_ULONG_PTR), return check(_slot->_library->C_GetOperationState(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_GetOperationState")); CRYPTOKI_FN_LOG("C_GetOperationState"));
} }
@endcode */ @endcode */
@ -1144,7 +1194,7 @@ namespace cryptoki {
bool getsessioninfo() { bool getsessioninfo() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GetSessionInfo //! calls @c C_GetSessionInfo
return check(_slot._init->_fn->C_GetSessionInfo(_session, CK_SESSION_INFO_PTR), return check(_slot->_library->C_GetSessionInfo(_session, CK_SESSION_INFO_PTR),
CRYPTOKI_FN_LOG("C_GetSessionInfo")); CRYPTOKI_FN_LOG("C_GetSessionInfo"));
} }
@endcode */ @endcode */
@ -1154,7 +1204,7 @@ namespace cryptoki {
bool initpin() { bool initpin() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_InitPIN //! calls @c C_InitPIN
return check(_slot._init->_fn->C_InitPIN(_session, CK_CHAR_PTR, CK_ULONG), return check(_slot->_library->C_InitPIN(_session, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_InitPIN")); CRYPTOKI_FN_LOG("C_InitPIN"));
} }
@endcode */ @endcode */
@ -1163,13 +1213,13 @@ namespace cryptoki {
public: public:
Login(Session& session, Login(mrw::Shared<Session> session,
const std::string& pin, const std::string& pin,
CK_USER_TYPE userType=CKU_USER): _session(session) { CK_USER_TYPE userType=CKU_USER): _session(session) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_Login //! calls @c C_Login
_session.check(_session.fn()->C_Login _session->check(_session->_slot->_library->C_Login
(_session._session, userType, (_session->_session, userType,
(CK_CHAR*)pin.c_str(), (CK_CHAR*)pin.c_str(),
pin.size()), pin.size()),
CRYPTOKI_FN_LOG("C_Login")); CRYPTOKI_FN_LOG("C_Login"));
@ -1178,8 +1228,8 @@ namespace cryptoki {
~Login() { ~Login() {
try { try {
//! calls @c C_Logout //! calls @c C_Logout
_session.check(_session.fn()->C_Logout _session->check(_session->_slot->_library->C_Logout
(_session._session), (_session->_session),
CRYPTOKI_FN_LOG("C_Logout")); CRYPTOKI_FN_LOG("C_Logout"));
} catch (...) { } catch (...) {
if (!std::uncaught_exception()) throw; if (!std::uncaught_exception()) throw;
@ -1188,35 +1238,33 @@ namespace cryptoki {
private: private:
Session& _session; mrw::Shared<Session> _session;
}; };
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) { void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
delete _login;
_login = new Login(*this, pin, userType); _login = new Login(*this, pin, userType);
} }
void logout() { void logout() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
try { try {
delete _login; _login.reset();
_login = 0;
} catch (...) { } catch (...) {
_login = 0; _login.reset();
throw; throw;
} }
} }
Login* _login; mrw::Shared<Login> _login;
/*! @todo Not implemented: /*! @todo Not implemented:
@code @code
bool seedrandom() { bool seedrandom() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SeedRandom //! calls @c C_SeedRandom
return check(_slot._init->_fn->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG), return check(_slot->_library->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SeedRandom")); CRYPTOKI_FN_LOG("C_SeedRandom"));
} }
@endcode */ @endcode */
@ -1226,7 +1274,7 @@ namespace cryptoki {
bool setpin() { bool setpin() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SetPIN //! calls @c C_SetPIN
return check(_slot._init->_fn->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG), return check(_slot->_library->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetPIN")); CRYPTOKI_FN_LOG("C_SetPIN"));
} }
@endcode */ @endcode */
@ -1239,13 +1287,13 @@ namespace cryptoki {
friend class Session; friend class Session;
CK_OBJECT_HANDLE _object; CK_OBJECT_HANDLE _object;
Session* _session; mrw::Shared<Session> _session;
CK_RV _res; CK_RV _res;
bool check(CK_RV result, const std::string& context="") { bool check(CK_RV result, const std::string& context="") {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
_res = result; _res = result;
if (_session->_slot._init->_exc && !*this) if (_session->_slot->_library.exc() && !*this)
if (!context.empty()) if (!context.empty())
throw access_error(context+": "+error()); throw access_error(context+": "+error());
else else
@ -1255,8 +1303,8 @@ namespace cryptoki {
Object(); // forbidden Object(); // forbidden
Object(Session& session, CK_OBJECT_HANDLE obj): Object(mrw::Shared<Session> session, CK_OBJECT_HANDLE obj):
_object(obj), _session(&session), _res(CKR_OK) { _object(obj), _session(session), _res(CKR_OK) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
} }
@ -1328,7 +1376,7 @@ namespace cryptoki {
/*! @return error text of last cryptoki call */ /*! @return error text of last cryptoki call */
std::string error() { std::string error() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
return _session->_slot._init->error(_res); return _session->_slot->_library.error(_res);
} }
//@} //@}
@ -1344,7 +1392,7 @@ namespace cryptoki {
bool copyobject() { bool copyobject() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_CopyObject //! calls @c C_CopyObject
return check(_session->_slot._init->_fn->C_CopyObject(_session->_session, CK_OBJECT_HANDLE, return check(_session->_slot->_library->C_CopyObject(_session->_session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_CopyObject")); CRYPTOKI_FN_LOG("C_CopyObject"));
} }
@ -1358,7 +1406,7 @@ namespace cryptoki {
CRYPTOKI_LOG("decryptinit: type="<<type<<"; mech=("<<mech.mechanism CRYPTOKI_LOG("decryptinit: type="<<type<<"; mech=("<<mech.mechanism
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); <<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
//! calls @c C_DecryptInit //! calls @c C_DecryptInit
return check(_session->_slot._init->_fn->C_DecryptInit return check(_session->_slot->_library->C_DecryptInit
(_session->_session, &mech, _object), (_session->_session, &mech, _object),
CRYPTOKI_FN_LOG("C_DecryptInit")); CRYPTOKI_FN_LOG("C_DecryptInit"));
} }
@ -1370,13 +1418,13 @@ namespace cryptoki {
CK_ULONG size(0); // two calls, first to get minimum buffer length CK_ULONG size(0); // two calls, first to get minimum buffer length
CRYPTOKI_LOG("get size"); CRYPTOKI_LOG("get size");
//! calls @c C_Decrypt //! calls @c C_Decrypt
check(_session->_slot._init->_fn->C_Decrypt check(_session->_slot->_library->C_Decrypt
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), 0, &size), (unsigned char*)&in[0], in.size(), 0, &size),
CRYPTOKI_FN_LOG("C_Decrypt")); CRYPTOKI_FN_LOG("C_Decrypt"));
CRYPTOKI_LOG("maximum size is "<<size<<"Bytes"); CRYPTOKI_LOG("maximum size is "<<size<<"Bytes");
res.resize(size, 0); res.resize(size, 0);
check(_session->_slot._init->_fn->C_Decrypt check(_session->_slot->_library->C_Decrypt
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1392,7 +1440,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptDigestUpdate //! calls @c C_DecryptDigestUpdate
check(_session->_slot._init->_fn->C_DecryptDigestUpdate check(_session->_slot->_library->C_DecryptDigestUpdate
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1404,7 +1452,7 @@ namespace cryptoki {
bool decryptfinal() { bool decryptfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DecryptFinal //! calls @c C_DecryptFinal
return check(_session->_slot._init->_fn->C_DecryptFinal return check(_session->_slot->_library->C_DecryptFinal
(_session->_session, 0, 0), (_session->_session, 0, 0),
CRYPTOKI_FN_LOG("C_DecryptFinal")); CRYPTOKI_FN_LOG("C_DecryptFinal"));
//! @todo does this work? //! @todo does this work?
@ -1416,7 +1464,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptUpdate //! calls @c C_DecryptUpdate
check(_session->_slot._init->_fn->C_DecryptUpdate check(_session->_slot->_library->C_DecryptUpdate
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1431,7 +1479,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_DecryptVerifyUpdate //! calls @c C_DecryptVerifyUpdate
check(_session->_slot._init->_fn->C_DecryptVerifyUpdate check(_session->_slot->_library->C_DecryptVerifyUpdate
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1445,14 +1493,14 @@ namespace cryptoki {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
std::string res; std::string res;
CK_ULONG size(0); CK_ULONG size(0);
check(_session->_slot._init->_fn->C_Sign check(_session->_slot->_library->C_Sign
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(),0, &size), (unsigned char*)&in[0], in.size(),0, &size),
CRYPTOKI_FN_LOG("C_Sign")); CRYPTOKI_FN_LOG("C_Sign"));
CRYPTOKI_LOG("maximum size is "<<size<<"Bytes"); CRYPTOKI_LOG("maximum size is "<<size<<"Bytes");
res.resize(size, 0); res.resize(size, 0);
//! calls @c C_Sign //! calls @c C_Sign
check(_session->_slot._init->_fn->C_Sign check(_session->_slot->_library->C_Sign
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1468,7 +1516,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_SignEncryptUpdate //! calls @c C_SignEncryptUpdate
check(_session->_slot._init->_fn->C_SignEncryptUpdate check(_session->_slot->_library->C_SignEncryptUpdate
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1482,7 +1530,7 @@ namespace cryptoki {
bool signfinal() { bool signfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SignFinal //! calls @c C_SignFinal
return check(_slot._init->_fn->C_SignFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR), return check(_slot->_library->C_SignFinal(_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_SignFinal")); CRYPTOKI_FN_LOG("C_SignFinal"));
} }
@endcode */ @endcode */
@ -1493,7 +1541,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_SignRecover //! calls @c C_SignRecover
check(_session->_slot._init->_fn->C_SignRecover check(_session->_slot->_library->C_SignRecover
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1507,7 +1555,7 @@ namespace cryptoki {
bool signupdate() { bool signupdate() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SignUpdate //! calls @c C_SignUpdate
return check(_session->_slot._init->_fn->C_SignUpdate(_session->_session, CK_BYTE_PTR, CK_ULONG), return check(_session->_slot->_library->C_SignUpdate(_session->_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SignUpdate")); CRYPTOKI_FN_LOG("C_SignUpdate"));
} }
@endcode */ @endcode */
@ -1515,7 +1563,7 @@ namespace cryptoki {
bool verify(std::string data, std::string signature) { bool verify(std::string data, std::string signature) {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_Verify //! calls @c C_Verify
return check(_session->_slot._init->_fn->C_Verify return check(_session->_slot->_library->C_Verify
(_session->_session, (_session->_session,
(unsigned char*)&data[0], data.size(), (unsigned char*)&data[0], data.size(),
(unsigned char*)&signature[0], signature.size()), (unsigned char*)&signature[0], signature.size()),
@ -1527,7 +1575,7 @@ namespace cryptoki {
bool verifyfinal() { bool verifyfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_VerifyFinal //! calls @c C_VerifyFinal
return check(_session->_slot._init->_fn->C_VerifyFinal(_session->_session, CK_BYTE_PTR, CK_ULONG), return check(_session->_slot->_library->C_VerifyFinal(_session->_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_VerifyFinal")); CRYPTOKI_FN_LOG("C_VerifyFinal"));
} }
@endcode */ @endcode */
@ -1538,7 +1586,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_VerifyRecover //! calls @c C_VerifyRecover
check(_session->_slot._init->_fn->C_VerifyRecover check(_session->_slot->_library->C_VerifyRecover
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1552,7 +1600,7 @@ namespace cryptoki {
bool verifyupdate() { bool verifyupdate() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_VerifyUpdate //! calls @c C_VerifyUpdate
return check(_session->_slot._init->_fn->C_VerifyUpdate(_session->_session, CK_BYTE_PTR, CK_ULONG), return check(_session->_slot->_library->C_VerifyUpdate(_session->_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_VerifyUpdate")); CRYPTOKI_FN_LOG("C_VerifyUpdate"));
} }
@endcode */ @endcode */
@ -1563,7 +1611,7 @@ namespace cryptoki {
bool derivekey() { bool derivekey() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DeriveKey //! calls @c C_DeriveKey
return check(_session->_slot._init->_fn->C_DeriveKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session->_slot->_library->C_DeriveKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ATTRIBUTE_PTR, CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_DeriveKey")); CRYPTOKI_FN_LOG("C_DeriveKey"));
} }
@ -1572,7 +1620,7 @@ namespace cryptoki {
bool destroy() { bool destroy() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DestroyObject //! calls @c C_DestroyObject
return check(_session->_slot._init->_fn->C_DestroyObject return check(_session->_slot->_library->C_DestroyObject
(_session->_session, _object), (_session->_session, _object),
CRYPTOKI_FN_LOG("C_DestroyObject")); CRYPTOKI_FN_LOG("C_DestroyObject"));
} }
@ -1583,7 +1631,7 @@ namespace cryptoki {
bool digestkey() { bool digestkey() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_DigestKey //! calls @c C_DigestKey
return check(_session->_slot._init->_fn->C_DigestKey(_session->_session, CK_OBJECT_HANDLE), return check(_session->_slot->_library->C_DigestKey(_session->_session, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_DigestKey")); CRYPTOKI_FN_LOG("C_DigestKey"));
} }
@endcode */ @endcode */
@ -1596,7 +1644,7 @@ namespace cryptoki {
CRYPTOKI_LOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism CRYPTOKI_LOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); <<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
//! calls @c C_EncryptInit //! calls @c C_EncryptInit
return check(_session->_slot._init->_fn->C_EncryptInit return check(_session->_slot->_library->C_EncryptInit
(_session->_session, &mech, _object), (_session->_session, &mech, _object),
CRYPTOKI_FN_LOG("C_EncryptInit")); CRYPTOKI_FN_LOG("C_EncryptInit"));
} }
@ -1607,13 +1655,13 @@ namespace cryptoki {
CK_ULONG size(0); // two calls, first to get minimum buffer length CK_ULONG size(0); // two calls, first to get minimum buffer length
CRYPTOKI_LOG("get size"); CRYPTOKI_LOG("get size");
//! calls @c C_Encrypt //! calls @c C_Encrypt
check(_session->_slot._init->_fn->C_Encrypt check(_session->_slot->_library->C_Encrypt
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), 0, &size), (unsigned char*)&in[0], in.size(), 0, &size),
CRYPTOKI_FN_LOG("C_Decrypt")); CRYPTOKI_FN_LOG("C_Decrypt"));
CRYPTOKI_LOG("maximum size is "<<size<<"Bytes"); CRYPTOKI_LOG("maximum size is "<<size<<"Bytes");
res.resize(size, 0); res.resize(size, 0);
check(_session->_slot._init->_fn->C_Encrypt check(_session->_slot->_library->C_Encrypt
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1627,7 +1675,7 @@ namespace cryptoki {
bool encryptfinal() { bool encryptfinal() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_EncryptFinal //! calls @c C_EncryptFinal
return check(_session->_slot._init->_fn->C_EncryptFinal(_session->_session, CK_BYTE_PTR, CK_ULONG_PTR), return check(_session->_slot->_library->C_EncryptFinal(_session->_session, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_EncryptFinal")); CRYPTOKI_FN_LOG("C_EncryptFinal"));
} }
@endcode */ @endcode */
@ -1638,7 +1686,7 @@ namespace cryptoki {
res.resize(in.size()); res.resize(in.size());
CK_ULONG size(res.size()); //! @todo check if size is ok CK_ULONG size(res.size()); //! @todo check if size is ok
//! calls @c C_EncryptUpdate //! calls @c C_EncryptUpdate
check(_session->_slot._init->_fn->C_EncryptUpdate check(_session->_slot->_library->C_EncryptUpdate
(_session->_session, (_session->_session,
(unsigned char*)&in[0], in.size(), (unsigned char*)&in[0], in.size(),
(unsigned char*)&res[0], &size), (unsigned char*)&res[0], &size),
@ -1652,7 +1700,7 @@ namespace cryptoki {
bool generatekey() { bool generatekey() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GenerateKey //! calls @c C_GenerateKey
return check(_session->_slot._init->_fn->C_GenerateKey(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, return check(_session->_slot->_library->C_GenerateKey(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_OBJECT_HANDLE_PTR), CK_ULONG, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKey")); CRYPTOKI_FN_LOG("C_GenerateKey"));
} }
@ -1664,7 +1712,7 @@ namespace cryptoki {
bool generatekeypair() { bool generatekeypair() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GenerateKeyPair //! calls @c C_GenerateKeyPair
return check(_session->_slot._init->_fn->C_GenerateKeyPair(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR, return check(_session->_slot->_library->C_GenerateKeyPair(_session->_session, CK_MECHANISM_PTR, CK_ATTRIBUTE_PTR,
CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR), CK_OBJECT_HANDLE_PTR, CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_GenerateKeyPair")); CRYPTOKI_FN_LOG("C_GenerateKeyPair"));
@ -1684,7 +1732,7 @@ namespace cryptoki {
Attribute res; Attribute res;
CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0}); CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0});
//! calls @c C_GetAttributeValue //! calls @c C_GetAttributeValue
if (!check(_session->_slot._init->_fn->C_GetAttributeValue if (!check(_session->_slot->_library->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session->_session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue")) CRYPTOKI_FN_LOG("C_GetAttributeValue"))
|| !(long)attr.ulValueLen>0l) || !(long)attr.ulValueLen>0l)
@ -1693,7 +1741,7 @@ namespace cryptoki {
try { try {
attr.pValue = malloc(attr.ulValueLen); attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
if (check(_session->_slot._init->_fn->C_GetAttributeValue if (check(_session->_slot->_library->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session->_session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) CRYPTOKI_FN_LOG("C_GetAttributeValue")))
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
@ -1809,7 +1857,7 @@ namespace cryptoki {
attr = (CK_ATTRIBUTE){*it, 0, 0}; attr = (CK_ATTRIBUTE){*it, 0, 0};
try { try {
//! calls @c C_GetAttributeValue //! calls @c C_GetAttributeValue
if (_session->_slot._init->_fn->C_GetAttributeValue if (_session->_slot->_library->C_GetAttributeValue
(_session->_session, _object, &attr, 1) (_session->_session, _object, &attr, 1)
== CKR_ATTRIBUTE_TYPE_INVALID == CKR_ATTRIBUTE_TYPE_INVALID
|| _res == CKR_ATTRIBUTE_SENSITIVE) { || _res == CKR_ATTRIBUTE_SENSITIVE) {
@ -1819,7 +1867,7 @@ namespace cryptoki {
if ((long)attr.ulValueLen>0l) { if ((long)attr.ulValueLen>0l) {
attr.pValue = malloc(attr.ulValueLen); attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen); attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
if (check(_session->_slot._init->_fn->C_GetAttributeValue if (check(_session->_slot->_library->C_GetAttributeValue
(_session->_session, _object, &attr, 1), (_session->_session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))) CRYPTOKI_FN_LOG("C_GetAttributeValue")))
/*! @todo There's no @c CKA_WRAP_TEMPLATE in Open /*! @todo There's no @c CKA_WRAP_TEMPLATE in Open
@ -1881,7 +1929,7 @@ namespace cryptoki {
bool getobjectsize() { bool getobjectsize() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_GetObjectSize //! calls @c C_GetObjectSize
return check(_session->_slot._init->_fn->C_GetObjectSize(_session->_session, CK_OBJECT_HANDLE, CK_ULONG_PTR), return check(_session->_slot->_library->C_GetObjectSize(_session->_session, CK_OBJECT_HANDLE, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_GetObjectSize")); CRYPTOKI_FN_LOG("C_GetObjectSize"));
} }
@endcode */ @endcode */
@ -1892,7 +1940,7 @@ namespace cryptoki {
bool setattributevalue() { bool setattributevalue() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SetAttributeValue //! calls @c C_SetAttributeValue
return check(_session->_slot._init->_fn->C_SetAttributeValue(_session->_session, CK_OBJECT_HANDLE, return check(_session->_slot->_library->C_SetAttributeValue(_session->_session, CK_OBJECT_HANDLE,
CK_ATTRIBUTE_PTR, CK_ULONG), CK_ATTRIBUTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetAttributeValue")); CRYPTOKI_FN_LOG("C_SetAttributeValue"));
} }
@ -1903,7 +1951,7 @@ namespace cryptoki {
bool setoperationstate() { bool setoperationstate() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SetOperationState //! calls @c C_SetOperationState
return check(_session->_slot._init->_fn->C_SetOperationState(_session->_session, CK_BYTE_PTR, CK_ULONG, return check(_session->_slot->_library->C_SetOperationState(_session->_session, CK_BYTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE, CK_OBJECT_HANDLE), CK_OBJECT_HANDLE, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SetOperationState")); CRYPTOKI_FN_LOG("C_SetOperationState"));
} }
@ -1917,7 +1965,7 @@ namespace cryptoki {
CRYPTOKI_LOG("signinit: type="<<type<<"; mech=("<<mech.mechanism CRYPTOKI_LOG("signinit: type="<<type<<"; mech=("<<mech.mechanism
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); <<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
//! calls @c C_SignInit //! calls @c C_SignInit
return check(_session->_slot._init->_fn->C_SignInit return check(_session->_slot->_library->C_SignInit
(_session->_session, &mech, _object), (_session->_session, &mech, _object),
CRYPTOKI_FN_LOG("C_SignInit")); CRYPTOKI_FN_LOG("C_SignInit"));
} }
@ -1927,7 +1975,7 @@ namespace cryptoki {
bool signrecoverinit() { bool signrecoverinit() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_SignRecoverInit //! calls @c C_SignRecoverInit
return check(_session->_slot._init->_fn->C_SignRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session->_slot->_library->C_SignRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_SignRecoverInit")); CRYPTOKI_FN_LOG("C_SignRecoverInit"));
} }
@endcode */ @endcode */
@ -1937,7 +1985,7 @@ namespace cryptoki {
bool unwrapkey() { bool unwrapkey() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_UnwrapKey //! calls @c C_UnwrapKey
return check(_session->_slot._init->_fn->C_UnwrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session->_slot->_library->C_UnwrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG, CK_ATTRIBUTE_PTR, CK_ULONG,
CK_OBJECT_HANDLE_PTR), CK_OBJECT_HANDLE_PTR),
CRYPTOKI_FN_LOG("C_UnwrapKey")); CRYPTOKI_FN_LOG("C_UnwrapKey"));
@ -1952,7 +2000,7 @@ namespace cryptoki {
CRYPTOKI_LOG("verifyinit: type="<<type<<"; mech=("<<mech.mechanism CRYPTOKI_LOG("verifyinit: type="<<type<<"; mech=("<<mech.mechanism
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')'); <<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
//! calls @c C_VerifyInit //! calls @c C_VerifyInit
return check(_session->_slot._init->_fn->C_VerifyInit return check(_session->_slot->_library->C_VerifyInit
(_session->_session, &mech, _object), (_session->_session, &mech, _object),
CRYPTOKI_FN_LOG("C_VerifyInit")); CRYPTOKI_FN_LOG("C_VerifyInit"));
} }
@ -1962,7 +2010,7 @@ namespace cryptoki {
bool verifyrecoverinit() { bool verifyrecoverinit() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_VerifyRecoverInit //! calls @c C_VerifyRecoverInit
return check(_session->_slot._init->_fn->C_VerifyRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE), return check(_session->_slot->_library->C_VerifyRecoverInit(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE),
CRYPTOKI_FN_LOG("C_VerifyRecoverInit")); CRYPTOKI_FN_LOG("C_VerifyRecoverInit"));
} }
@endcode */ @endcode */
@ -1973,7 +2021,7 @@ namespace cryptoki {
bool wrapkey() { bool wrapkey() {
CRYPTOKI_LOG("log"); CRYPTOKI_LOG("log");
//! calls @c C_WrapKey //! calls @c C_WrapKey
return check(_session->_slot._init->_fn->C_WrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE, return check(_session->_slot->_library->C_WrapKey(_session->_session, CK_MECHANISM_PTR, CK_OBJECT_HANDLE,
CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR), CK_OBJECT_HANDLE, CK_BYTE_PTR, CK_ULONG_PTR),
CRYPTOKI_FN_LOG("C_WrapKey")); CRYPTOKI_FN_LOG("C_WrapKey"));
} }

@ -11,7 +11,7 @@
#define PCSC_HXX #define PCSC_HXX
#ifndef PCSC_LOG #ifndef PCSC_LOG
//! Declare PCSC_LOG before #include in your code, if you want logging. //! Declare PCSC_LOG before #include in your de, if you want logging.
/*! PCSC_LOG passes its argument to a stream, so your definition must /*! PCSC_LOG passes its argument to a stream, so your definition must
behave so that the argument can be streamed. behave so that the argument can be streamed.
@ -31,6 +31,7 @@
#include <cryptaux.hxx> #include <cryptaux.hxx>
#include <mrw/shared.hxx>
#include <string> #include <string>
#ifdef WIN32 #ifdef WIN32
@ -214,8 +215,8 @@ namespace pcsc {
/*! @note Please note that the Reader is required in the /*! @note Please note that the Reader is required in the
destructor und must therefore live longer than the destructor und must therefore live longer than the
Transaction instance. */ Transaction instance. */
Transaction(Reader& r): _reader(r), _running(true) { Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
_reader.beginTransaction(); _reader->beginTransaction();
} }
//! Cancels the transaction if not yet finished. //! Cancels the transaction if not yet finished.
~Transaction() try { ~Transaction() try {
@ -225,11 +226,11 @@ namespace pcsc {
} }
//! Ends the running transaction. //! Ends the running transaction.
void end() { void end() {
if (_running) _reader.endTransaction(); if (_running) _reader->endTransaction();
_running = false; _running = false;
} }
private: private:
Reader& _reader; mrw::Shared<Reader> _reader;
bool _running; bool _running;
}; };
@ -248,7 +249,7 @@ namespace pcsc {
~Reader() { ~Reader() {
_state = SCardDisconnect(_id, SCARD_RESET_CARD); _state = SCardDisconnect(_id, SCARD_RESET_CARD);
if (!std::uncaught_exception()) if (!std::uncaught_exception())
_connection.check("disconnect smartcard"); _connection->check("disconnect smartcard");
} }
//! Get reader status. //! Get reader status.
@ -411,7 +412,7 @@ namespace pcsc {
case SCARD_PROTOCOL_T0: return SCARD_PCI_T0; case SCARD_PROTOCOL_T0: return SCARD_PCI_T0;
case SCARD_PROTOCOL_T1: return SCARD_PCI_T1; case SCARD_PROTOCOL_T1: return SCARD_PCI_T1;
} }
if (_connection._exc) throw not_implemented("unknown protocol"); if (_connection->exc()) throw not_implemented("unknown protocol");
return 0; return 0;
} }
@ -420,18 +421,18 @@ namespace pcsc {
an error occured in the last command. */ an error occured in the last command. */
bool check(long state, const std::string context="") { bool check(long state, const std::string context="") {
_state = state; _state = state;
return _connection.check(state, context); return _connection->check(state, context);
} }
//! Only Connection is allowed to instanciate. //! Only Connection is allowed to instanciate.
friend class Connection; friend class Connection;
//! Establishes a connection to the given named cardreader //! Establishes a connection to the given named cardreader
Reader(const std::string& nm, Connection& c, Reader(const std::string& nm, const Connection& c,
DWORD mode=SCARD_SHARE_SHARED, DWORD mode=SCARD_SHARE_SHARED,
DWORD protocol=SCARD_PROTOCOL_T1): DWORD protocol=SCARD_PROTOCOL_T1):
name(nm), _connection(c) { name(nm), _connection(c) {
check(SCardConnect(_connection._id, strconv(name).c_str(), check(SCardConnect(_connection->id(), strconv(name).c_str(),
mode, protocol, mode, protocol,
&_id, &_protocol), &_id, &_protocol),
"connect smartcard \""+name); "connect smartcard \""+name);
@ -440,13 +441,10 @@ namespace pcsc {
//! forbidden //! forbidden
Reader(); Reader();
//! forbidden
Reader(const Reader&);
//...........................................................variables //...........................................................variables
private: private:
Connection& _connection; mrw::Shared<Connection> _connection;
SCARDHANDLE _id; SCARDHANDLE _id;
DWORD _state; DWORD _state;
DWORD _protocol; DWORD _protocol;
@ -495,15 +493,13 @@ namespace pcsc {
- @c false: no exceptions, check your instance after each - @c false: no exceptions, check your instance after each
operation */ operation */
Connection(Scope s=USER, bool exceptions=true): Connection(Scope s=USER, bool exceptions=true):
_exc(exceptions), _id(0), _connectionlifetime(new ConnectionLifetime(s, exceptions)) {
_state(SCardEstablishContext(s, 0, 0, &_id)) {
check("establish smartcard context"); check("establish smartcard context");
} }
//! Closes the connection (releases the smartcard context) //! Closes the connection (releases the smartcard context)
~Connection() { ~Connection() {
_state = SCardReleaseContext(_id); // connection is closed, when last _connectionlifetime is destructed
if (!std::uncaught_exception()) check("smartcard release context");
} }
//! Scans for available readers from a specified list of groups. //! Scans for available readers from a specified list of groups.
@ -512,14 +508,16 @@ namespace pcsc {
Strings res; Strings res;
std::string grp(join(groups)); std::string grp(join(groups));
DWORD num(0); DWORD num(0);
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, 0, if (!check(SCardListReaders(_connectionlifetime->id(),
groups.size()?strconv(grp).data():0, 0,
&num), &num),
"smartcard get size of readers of groups "+grp)) "smartcard get size of readers of groups "+grp))
return res; return res;
PCSC_LOG("size of readers: "<<num); PCSC_LOG("size of readers: "<<num);
if (!num) return res; if (!num) return res;
std::auto_ptr<char_t> nm(new char_t[num]); std::auto_ptr<char_t> nm(new char_t[num]);
if (!check(SCardListReaders(_id, groups.size()?strconv(grp).data():0, if (!check(SCardListReaders(_connectionlifetime->id(),
groups.size()?strconv(grp).data():0,
nm.get(), &num), nm.get(), &num),
"smartcard list reader names of groups "+grp)) "smartcard list reader names of groups "+grp))
return res; return res;
@ -533,12 +531,10 @@ namespace pcsc {
//! Get a reader, open a connection if not already open. //! Get a reader, open a connection if not already open.
/*! First use scan() to get a list of readers, then open a /*! First use scan() to get a list of readers, then open a
connection to the reader, then access it. */ connection to the reader, then access it. */
Reader& reader(const std::string& name) { mrw::Shared<Reader> reader(const std::string& name) {
if (_reader.find(name)==_reader.end()) if (_readers.find(name)==_readers.end())
_reader.insert _readers.insert(std::make_pair(name, new Reader(name, *this)));
(std::make_pair return _readers.find(name)->second;
(name, shared_ptr<Reader>::t(new Reader(name, *this))));
return *_reader.find(name)->second;
} }
//! Close connection of a named reader. //! Close connection of a named reader.
@ -556,257 +552,14 @@ namespace pcsc {
pcsc::Connection::Strings readers(scan()); pcsc::Connection::Strings readers(scan());
for (pcsc::Connection::Strings::const_iterator it(readers.begin()); for (pcsc::Connection::Strings::const_iterator it(readers.begin());
it!=readers.end(); ++it) it!=readers.end(); ++it)
if (crypto::hex(reader(*it).status().atr).find(atr)!=string::npos) if (crypto::hex(reader(*it)->status().atr).find(atr)!=string::npos)
res.push_back(*it); res.push_back(*it);
return res; return res;
} }
//! @c false if last operation was not successful //! @c false if last operation was not successful
operator bool() const { operator bool() const {
#ifdef WIN32 return *_connectionlifetime;
return (_state>>30&3)==0;
#else
return _state==SCARD_S_SUCCESS;
#endif
}
//! Get the describing text of the last error
std::string error() const {
std::stringstream ss;
switch (_state) {
case SCARD_E_CANCELLED:
ss<<"The action was canceled by an SCardCancel request.";
break;
case SCARD_E_CANT_DISPOSE:
ss<<"The system could not dispose of the media in the requested"
<<" manner.";
break;
case SCARD_E_CARD_UNSUPPORTED:
ss<<"The smart card does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_DUPLICATE_READER:
ss<<"The reader driver did not produce a unique reader name.";
break;
case SCARD_E_INSUFFICIENT_BUFFER:
ss<<"The data buffer for returned data is too small for the"
<<" returned data.";
break;
case SCARD_E_INVALID_ATR:
ss<<"An ATR string obtained from the registry is not a valid"
<<" ATR string.";
break;
case SCARD_E_INVALID_HANDLE:
ss<<"The supplied handle was not valid.";
break;
case SCARD_E_INVALID_PARAMETER:
ss<<"One or more of the supplied parameters could not be properly"
<<" interpreted.";
break;
case SCARD_E_INVALID_TARGET:
ss<<"Registry startup information is missing or not valid.";
break;
case SCARD_E_INVALID_VALUE:
ss<<"One or more of the supplied parameters values could not"
<<" be properly interpreted.";
break;
case SCARD_E_NOT_READY:
ss<<"The reader or smart card is not ready to accept commands.";
break;
case SCARD_E_NOT_TRANSACTED:
ss<<"An attempt was made to end a nonexistent transaction.";
break;
case SCARD_E_NO_MEMORY:
ss<<"Not enough memory available to complete this command.";
break;
case SCARD_E_NO_SERVICE:
ss<<"The smart card resource manager is not running.";
break;
case SCARD_E_NO_SMARTCARD:
ss<<"The operation requires a smart card, but no smart card"
<<" is currently in the device.";
break;
case SCARD_E_PCI_TOO_SMALL:
ss<<"The PCI receive buffer was too small.";
break;
case SCARD_E_PROTO_MISMATCH:
ss<<"The requested protocols are incompatible with the protocol"
<<" currently in use with the smart card.";
break;
case SCARD_E_READER_UNAVAILABLE:
ss<<"The specified reader is not currently available for use.";
break;
case SCARD_E_READER_UNSUPPORTED:
ss<<"The reader driver does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_SERVICE_STOPPED:
ss<<"The smart card resource manager has shut down.";
break;
case SCARD_E_SHARING_VIOLATION:
ss<<"The smart card cannot be accessed because of other outstanding"
<<" connections.";
break;
case SCARD_E_SYSTEM_CANCELLED:
ss<<"The action was cancelled by the system, presumably to log"
<<" off or shut down.";
break;
case SCARD_E_TIMEOUT:
ss<<"The user-specified time-out value has expired.";
break;
case SCARD_E_UNKNOWN_CARD:
ss<<"The specified smart card name is not recognized.";
break;
case SCARD_E_UNKNOWN_READER:
ss<<"The specified reader name is not recognized.";
break;
case SCARD_E_UNSUPPORTED_FEATURE:
ss<<"This smart card does not support the requested feature.";
break;
case SCARD_F_COMM_ERROR:
ss<<"An internal communications error has been detected.";
break;
case SCARD_F_INTERNAL_ERROR:
ss<<"An internal consistency check failed.";
break;
case SCARD_F_UNKNOWN_ERROR:
ss<<"An internal error has been detected, but the source is"
<<" unknown.";
break;
case SCARD_F_WAITED_TOO_LONG:
ss<<"An internal consistency timer has expired.";
break;
case SCARD_S_SUCCESS:
ss<<"No error was encountered.";
break;
case SCARD_W_REMOVED_CARD:
ss<<"The smart card has been removed, so that further communication"
<<" is not possible.";
break;
case SCARD_W_RESET_CARD:
ss<<"The smart card was reset.";
break;
case SCARD_W_UNPOWERED_CARD:
ss<<"Power has been removed from the smart card, so that"
<<" further communication is not possible.";
break;
case SCARD_W_UNRESPONSIVE_CARD:
ss<<"The smart card is not responding to a reset.";
break;
case SCARD_W_UNSUPPORTED_CARD:
ss<<"The reader cannot communicate with the smart card,"
<<" due to ATR configuration conflicts.";
break;
#ifndef __APPLE__
case SCARD_E_NO_READERS_AVAILABLE:
ss<<"No smart card reader is available.";
break;
#endif
#ifdef WIN32
case ERROR_BROKEN_PIPE:
ss<<"The client attempted a smart card operation in a"
<<" remote session, such as a client session running"
<<" on a terminal server, and the operating system in"
<<" use does not support smart card redirection.";
break;
case SCARD_E_BAD_SEEK:
ss<<"There was an error trying to set the smart card file"
<<" object pointer.";
break;
case SCARD_E_CERTIFICATE_UNAVAILABLE:
ss<<"The requested certificate could not be obtained.";
break;
case SCARD_E_COMM_DATA_LOST:
ss<<"A communications error with the smart card has been detected.";
break;
case SCARD_E_DIR_NOT_FOUND:
ss<<"The specified directory does not exist in the smart card.";
break;
case SCARD_E_FILE_NOT_FOUND:
ss<<"The specified file does not exist in the smart card.";
break;
case SCARD_E_ICC_CREATEORDER:
ss<<"The requested order of object creation is not supported.";
break;
case SCARD_E_ICC_INSTALLATION:
ss<<"No primary provider can be found for the smart card.";
break;
case SCARD_E_INVALID_CHV:
ss<<"The supplied PIN is incorrect.";
break;
case SCARD_E_NO_ACCESS:
ss<<"Access is denied to this file.";
break;
case SCARD_E_NO_DIR:
ss<<"The supplied path does not represent a smart card directory.";
break;
case SCARD_E_NO_FILE:
ss<<"The supplied path does not represent a smart card file.";
break;
case SCARD_E_NO_KEY_CONTAINER:
ss<<"The requested key container does not exist on the smart card.";
break;
case SCARD_E_NO_SUCH_CERTIFICATE:
ss<<"The requested certificate does not exist.";
break;
case SCARD_E_SERVER_TOO_BUSY:
ss<<"The Smart card resource manager is too busy to complete this"
<<" operation.";
break;
case SCARD_E_UNEXPECTED:
ss<<"An unexpected card error has occurred.";
break;
case SCARD_E_UNKNOWN_RES_MNG:
ss<<"An unrecognized error code was returned from a layered"
<<" component.";
break;
case SCARD_E_WRITE_TOO_MANY:
ss<<"The smartcard does not have enough memory to store the"
<<" information.";
break;
case SCARD_P_SHUTDOWN:
ss<<"The operation has been aborted to allow the server application"
<<" to exit.";
break;
case SCARD_W_CANCELLED_BY_USER:
ss<<"The action was cancelled by the user.";
break;
case SCARD_W_CARD_NOT_AUTHENTICATED:
ss<<"No PIN was presented to the smart card.";
break;
case SCARD_W_CHV_BLOCKED:
ss<<"The card cannot be accessed because the maximum number"
<<" of PIN entry attempts has been reached.";
break;
case SCARD_W_EOF:
ss<<"The end of the smart card file has been reached.";
break;
case SCARD_W_SECURITY_VIOLATION:
ss<<"Access was denied because of a security violation.";
break;
case SCARD_W_WRONG_CHV:
ss<<"The card cannot be accessed because the wrong PIN was"
<<" presented.";
break;
#endif
default:
ss<<"unknown PCSC state=0x"
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
switch (_state>>30) {
case 0: ss<<" means SUCCESS"; break;
case 1: ss<<" means INFORMATIONAL"; break;
case 2: ss<<" means WARNING"; break;
case 3: ss<<" means ERROR"; break;
default: ss<<" illegal value";
}
ss<<" C="<<(_state>>29&1);
ss<<" R="<<(_state>>28&1);
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
<<(_state>>16&0xfff);
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
<<(_state&0xffff);
}
return ss.str();
} }
//................................................................methods //................................................................methods
@ -816,20 +569,15 @@ namespace pcsc {
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check(long state, const std::string& context="") { bool check(long state, const std::string& context="") {
_state = state; _connectionlifetime->state(state);
return check(context); return check(context);
} }
//! Throws an exception if neccessary. //! Throws an exception if neccessary.
/*! @throw access_error if it is instanciated for exceptions and /*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */ an error occured in the last command. */
bool check(const std::string& context="") { bool check(const std::string& context="") {
if (_exc&&!*this) return _connectionlifetime->check(context);
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return *this;
} }
//! Splits a buffer with 0 separators into a vector of strings. //! Splits a buffer with 0 separators into a vector of strings.
@ -852,14 +600,324 @@ namespace pcsc {
} }
return res; return res;
} }
//! Connection id
SCARDCONTEXT id() {
return _connectionlifetime->id();
}
//! @c true if exceptions are thrown
bool exc() {
return _connectionlifetime->exc();
}
//..............................................................variables //..............................................................variables
private: private:
class ConnectionLifetime {
public:
//! opens connection that is closed on destruction
ConnectionLifetime(Scope s, bool exc):
_exc(exc), _id(0),
_state(SCardEstablishContext(s, 0, 0, &_id)) {
check("establish smartcard context");
}
//! Closes the connection (releases the smartcard context)
~ConnectionLifetime() {
_state = SCardReleaseContext(_id);
if (!std::uncaught_exception()) check("smartcard release context");
}
//! @c false if last operation was not successful
operator bool() const {
#ifdef WIN32
return (_state>>30&3)==0;
#else
return _state==SCARD_S_SUCCESS;
#endif
}
//! Throws an exception if neccessary.
/*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */
bool check(const std::string& context="") {
if (_exc&&!*this)
if (context.size())
throw access_error(context+": "+error());
else
throw access_error(error());
return *this;
}
//! Get the describing text of the last error
std::string error() const {
std::stringstream ss;
switch (_state) {
case SCARD_E_CANCELLED:
ss<<"The action was canceled by an SCardCancel request.";
break;
case SCARD_E_CANT_DISPOSE:
ss<<"The system could not dispose of the media in the requested"
<<" manner.";
break;
case SCARD_E_CARD_UNSUPPORTED:
ss<<"The smart card does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_DUPLICATE_READER:
ss<<"The reader driver did not produce a unique reader name.";
break;
case SCARD_E_INSUFFICIENT_BUFFER:
ss<<"The data buffer for returned data is too small for the"
<<" returned data.";
break;
case SCARD_E_INVALID_ATR:
ss<<"An ATR string obtained from the registry is not a valid"
<<" ATR string.";
break;
case SCARD_E_INVALID_HANDLE:
ss<<"The supplied handle was not valid.";
break;
case SCARD_E_INVALID_PARAMETER:
ss<<"One or more of the supplied parameters could not be properly"
<<" interpreted.";
break;
case SCARD_E_INVALID_TARGET:
ss<<"Registry startup information is missing or not valid.";
break;
case SCARD_E_INVALID_VALUE:
ss<<"One or more of the supplied parameters values could not"
<<" be properly interpreted.";
break;
case SCARD_E_NOT_READY:
ss<<"The reader or smart card is not ready to accept commands.";
break;
case SCARD_E_NOT_TRANSACTED:
ss<<"An attempt was made to end a nonexistent transaction.";
break;
case SCARD_E_NO_MEMORY:
ss<<"Not enough memory available to complete this command.";
break;
case SCARD_E_NO_SERVICE:
ss<<"The smart card resource manager is not running.";
break;
case SCARD_E_NO_SMARTCARD:
ss<<"The operation requires a smart card, but no smart card"
<<" is currently in the device.";
break;
case SCARD_E_PCI_TOO_SMALL:
ss<<"The PCI receive buffer was too small.";
break;
case SCARD_E_PROTO_MISMATCH:
ss<<"The requested protocols are incompatible with the protocol"
<<" currently in use with the smart card.";
break;
case SCARD_E_READER_UNAVAILABLE:
ss<<"The specified reader is not currently available for use.";
break;
case SCARD_E_READER_UNSUPPORTED:
ss<<"The reader driver does not meet minimal requirements for"
<<" support.";
break;
case SCARD_E_SERVICE_STOPPED:
ss<<"The smart card resource manager has shut down.";
break;
case SCARD_E_SHARING_VIOLATION:
ss<<"The smart card cannot be accessed because of other outstanding"
<<" connections.";
break;
case SCARD_E_SYSTEM_CANCELLED:
ss<<"The action was cancelled by the system, presumably to log"
<<" off or shut down.";
break;
case SCARD_E_TIMEOUT:
ss<<"The user-specified time-out value has expired.";
break;
case SCARD_E_UNKNOWN_CARD:
ss<<"The specified smart card name is not recognized.";
break;
case SCARD_E_UNKNOWN_READER:
ss<<"The specified reader name is not recognized.";
break;
case SCARD_E_UNSUPPORTED_FEATURE:
ss<<"This smart card does not support the requested feature.";
break;
case SCARD_F_COMM_ERROR:
ss<<"An internal communications error has been detected.";
break;
case SCARD_F_INTERNAL_ERROR:
ss<<"An internal consistency check failed.";
break;
case SCARD_F_UNKNOWN_ERROR:
ss<<"An internal error has been detected, but the source is"
<<" unknown.";
break;
case SCARD_F_WAITED_TOO_LONG:
ss<<"An internal consistency timer has expired.";
break;
case SCARD_S_SUCCESS:
ss<<"No error was encountered.";
break;
case SCARD_W_REMOVED_CARD:
ss<<"The smart card has been removed, so that further communication"
<<" is not possible.";
break;
case SCARD_W_RESET_CARD:
ss<<"The smart card was reset.";
break;
case SCARD_W_UNPOWERED_CARD:
ss<<"Power has been removed from the smart card, so that"
<<" further communication is not possible.";
break;
case SCARD_W_UNRESPONSIVE_CARD:
ss<<"The smart card is not responding to a reset.";
break;
case SCARD_W_UNSUPPORTED_CARD:
ss<<"The reader cannot communicate with the smart card,"
<<" due to ATR configuration conflicts.";
break;
#ifndef __APPLE__
case SCARD_E_NO_READERS_AVAILABLE:
ss<<"No smart card reader is available.";
break;
#endif
#ifdef WIN32
case ERROR_BROKEN_PIPE:
ss<<"The client attempted a smart card operation in a"
<<" remote session, such as a client session running"
<<" on a terminal server, and the operating system in"
<<" use does not support smart card redirection.";
break;
case SCARD_E_BAD_SEEK:
ss<<"There was an error trying to set the smart card file"
<<" object pointer.";
break;
case SCARD_E_CERTIFICATE_UNAVAILABLE:
ss<<"The requested certificate could not be obtained.";
break;
case SCARD_E_COMM_DATA_LOST:
ss<<"A communications error with the smart card has been detected.";
break;
case SCARD_E_DIR_NOT_FOUND:
ss<<"The specified directory does not exist in the smart card.";
break;
case SCARD_E_FILE_NOT_FOUND:
ss<<"The specified file does not exist in the smart card.";
break;
case SCARD_E_ICC_CREATEORDER:
ss<<"The requested order of object creation is not supported.";
break;
case SCARD_E_ICC_INSTALLATION:
ss<<"No primary provider can be found for the smart card.";
break;
case SCARD_E_INVALID_CHV:
ss<<"The supplied PIN is incorrect.";
break;
case SCARD_E_NO_ACCESS:
ss<<"Access is denied to this file.";
break;
case SCARD_E_NO_DIR:
ss<<"The supplied path does not represent a smart card directory.";
break;
case SCARD_E_NO_FILE:
ss<<"The supplied path does not represent a smart card file.";
break;
case SCARD_E_NO_KEY_CONTAINER:
ss<<"The requested key container does not exist on the smart card.";
break;
case SCARD_E_NO_SUCH_CERTIFICATE:
ss<<"The requested certificate does not exist.";
break;
case SCARD_E_SERVER_TOO_BUSY:
ss<<"The Smart card resource manager is too busy to complete this"
<<" operation.";
break;
case SCARD_E_UNEXPECTED:
ss<<"An unexpected card error has occurred.";
break;
case SCARD_E_UNKNOWN_RES_MNG:
ss<<"An unrecognized error code was returned from a layered"
<<" component.";
break;
case SCARD_E_WRITE_TOO_MANY:
ss<<"The smartcard does not have enough memory to store the"
<<" information.";
break;
case SCARD_P_SHUTDOWN:
ss<<"The operation has been aborted to allow the server application"
<<" to exit.";
break;
case SCARD_W_CANCELLED_BY_USER:
ss<<"The action was cancelled by the user.";
break;
case SCARD_W_CARD_NOT_AUTHENTICATED:
ss<<"No PIN was presented to the smart card.";
break;
case SCARD_W_CHV_BLOCKED:
ss<<"The card cannot be accessed because the maximum number"
<<" of PIN entry attempts has been reached.";
break;
case SCARD_W_EOF:
ss<<"The end of the smart card file has been reached.";
break;
case SCARD_W_SECURITY_VIOLATION:
ss<<"Access was denied because of a security violation.";
break;
case SCARD_W_WRONG_CHV:
ss<<"The card cannot be accessed because the wrong PIN was"
<<" presented.";
break;
#endif
default:
ss<<"unknown PCSC state=0x"
<<std::hex<<std::setfill('0')<<std::setw(8)<<_state;
switch (_state>>30) {
case 0: ss<<" means SUCCESS"; break;
case 1: ss<<" means INFORMATIONAL"; break;
case 2: ss<<" means WARNING"; break;
case 3: ss<<" means ERROR"; break;
default: ss<<" illegal value";
}
ss<<" C="<<(_state>>29&1);
ss<<" R="<<(_state>>28&1);
ss<<" Facility=0x"<<std::hex<<std::setfill('0')<<std::setw(3)
<<(_state>>16&0xfff);
ss<<" Code=0x"<<std::hex<<std::setfill('0')<<std::setw(4)
<<(_state&0xffff);
}
return ss.str();
}
//! set state
void state(long s) {
_state = s;
}
//! @returns state
long state() {
return _state;
}
//! @returns connection id
SCARDCONTEXT id() {
return _id;
}
bool exc() {
return _exc;
}
private:
bool _exc;
SCARDCONTEXT _id;
long _state;
};
bool _exc;
SCARDCONTEXT _id; //! Readers are closed when the last shared object is destructed
long _state; std::map<std::string, mrw::Shared<Reader> > _readers;
std::map<std::string, shared_ptr<Reader>::t > _reader;
//! Connection is closed when the last shared object is destructed
/*! Handling the connection lifetime in a separate shared object
allows to copy connections and still make sure, that the
lifetime of the connection is as long as all copied opbjects
live. */
mrw::Shared<ConnectionLifetime> _connectionlifetime;
}; };

Loading…
Cancel
Save