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
m4_define(x_packagename, libpcscxx)
m4_define(x_major, 1)
m4_define(x_major, 2)
m4_define(x_minor, 0)
PACKAGENAME=x_packagename
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(VECTOR(((int[]){1,2,3,4})));
// print(v);
cryptoki::Init init(argc==2?argv[1]:"onepin-opensc-pkcs11.so");
cryptoki::Info inf(init.info());
cryptoki::Library cryptoki(argc==2?argv[1]:"onepin-opensc-pkcs11.so");
cryptoki::Info inf(cryptoki.info());
std::cout<<"Library-Version: "<<pcsc::version()<<std::endl;
std::cout<<"##################### INFO #####################"<<std::endl
<<"cryptokiVersion: \""<<(int)inf.cryptokiVersion.major
@ -23,7 +23,7 @@ int main(int argc, char const*const*const argv) try {
<<"libraryDescription: \""<<inf.libraryDescription<<'"'<<std::endl
<<"libraryVersion: \""<<(int)inf.libraryVersion.major
<<'.'<<(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)
try {
cryptoki::SlotInfo slotInfo(it->slotinfo());

@ -58,7 +58,7 @@ int main(int argc, char** argv) try {
<<"-----------------------------------------------------"<<std::endl
<<txt<<std::endl
<<"-----------------------------------------------------"<<std::endl;
cryptoki::Init c(lib);
cryptoki::Library c(lib);
cryptoki::SlotList sl(c.slotList());
for (cryptoki::SlotList::iterator s(sl.begin()); s!=sl.end(); ++s) {
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());
it!=reader.end(); ++it) {
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<<"ATR = "<<crypto::hex(s.atr)<<std::endl;
}

@ -9,10 +9,87 @@
#include <pcsc.hxx>
#include <mrw/args.hxx>
#include <mrw/vector.hxx>
#include <mrw/shared.hxx>
#include <stdexcept>
#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 {
std::string lib("libcvP11.so");
@ -28,20 +105,11 @@ int main(int argc, char** argv) try {
mrw::args::decl::param_list()
<<mrw::args::param(lib, "lib")));
pcsc::Connection pcsc;
cryptoki::Init cryptoki(lib);
// Scan for a Post SuisseID
pcsc::Connection::Strings readers
(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");
}
suisseid::Manager suisseid;
suisseid::Manager::Cards cards(suisseid.scan());
for (suisseid::Manager::Cards::iterator card(cards.begin());
card!=cards.end(); ++card)
std::cout<<"Found SuisseID: "<<(*card)->name()<<std::endl;
return 0;
} catch (std::exception& x) {
std::cerr<<"**** ERROR in "<<*argv<<": "<<x.what()<<std::endl;

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

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

@ -11,7 +11,7 @@
#define PCSC_HXX
#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
behave so that the argument can be streamed.
@ -31,6 +31,7 @@
#include <cryptaux.hxx>
#include <mrw/shared.hxx>
#include <string>
#ifdef WIN32
@ -214,8 +215,8 @@ namespace pcsc {
/*! @note Please note that the Reader is required in the
destructor und must therefore live longer than the
Transaction instance. */
Transaction(Reader& r): _reader(r), _running(true) {
_reader.beginTransaction();
Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
_reader->beginTransaction();
}
//! Cancels the transaction if not yet finished.
~Transaction() try {
@ -225,11 +226,11 @@ namespace pcsc {
}
//! Ends the running transaction.
void end() {
if (_running) _reader.endTransaction();
if (_running) _reader->endTransaction();
_running = false;
}
private:
Reader& _reader;
mrw::Shared<Reader> _reader;
bool _running;
};
@ -248,7 +249,7 @@ namespace pcsc {
~Reader() {
_state = SCardDisconnect(_id, SCARD_RESET_CARD);
if (!std::uncaught_exception())
_connection.check("disconnect smartcard");
_connection->check("disconnect smartcard");
}
//! Get reader status.
@ -411,7 +412,7 @@ namespace pcsc {
case SCARD_PROTOCOL_T0: return SCARD_PCI_T0;
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;
}
@ -420,18 +421,18 @@ namespace pcsc {
an error occured in the last command. */
bool check(long state, const std::string context="") {
_state = state;
return _connection.check(state, context);
return _connection->check(state, context);
}
//! Only Connection is allowed to instanciate.
friend class Connection;
//! 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 protocol=SCARD_PROTOCOL_T1):
name(nm), _connection(c) {
check(SCardConnect(_connection._id, strconv(name).c_str(),
check(SCardConnect(_connection->id(), strconv(name).c_str(),
mode, protocol,
&_id, &_protocol),
"connect smartcard \""+name);
@ -440,13 +441,10 @@ namespace pcsc {
//! forbidden
Reader();
//! forbidden
Reader(const Reader&);
//...........................................................variables
private:
Connection& _connection;
mrw::Shared<Connection> _connection;
SCARDHANDLE _id;
DWORD _state;
DWORD _protocol;
@ -495,15 +493,13 @@ namespace pcsc {
- @c false: no exceptions, check your instance after each
operation */
Connection(Scope s=USER, bool exceptions=true):
_exc(exceptions), _id(0),
_state(SCardEstablishContext(s, 0, 0, &_id)) {
_connectionlifetime(new ConnectionLifetime(s, exceptions)) {
check("establish smartcard context");
}
//! Closes the connection (releases the smartcard context)
~Connection() {
_state = SCardReleaseContext(_id);
if (!std::uncaught_exception()) check("smartcard release context");
// connection is closed, when last _connectionlifetime is destructed
}
//! Scans for available readers from a specified list of groups.
@ -512,14 +508,16 @@ namespace pcsc {
Strings res;
std::string grp(join(groups));
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),
"smartcard get size of readers of groups "+grp))
return res;
PCSC_LOG("size of readers: "<<num);
if (!num) return res;
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),
"smartcard list reader names of groups "+grp))
return res;
@ -533,12 +531,10 @@ namespace pcsc {
//! Get a reader, open a connection if not already open.
/*! First use scan() to get a list of readers, then open a
connection to the reader, then access it. */
Reader& reader(const std::string& name) {
if (_reader.find(name)==_reader.end())
_reader.insert
(std::make_pair
(name, shared_ptr<Reader>::t(new Reader(name, *this))));
return *_reader.find(name)->second;
mrw::Shared<Reader> reader(const std::string& name) {
if (_readers.find(name)==_readers.end())
_readers.insert(std::make_pair(name, new Reader(name, *this)));
return _readers.find(name)->second;
}
//! Close connection of a named reader.
@ -556,257 +552,14 @@ namespace pcsc {
pcsc::Connection::Strings readers(scan());
for (pcsc::Connection::Strings::const_iterator it(readers.begin());
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);
return res;
}
//! @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
}
//! 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();
return *_connectionlifetime;
}
//................................................................methods
@ -816,20 +569,15 @@ namespace pcsc {
/*! @throw access_error if it is instanciated for exceptions and
an error occured in the last command. */
bool check(long state, const std::string& context="") {
_state = state;
_connectionlifetime->state(state);
return check(context);
}
//! 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;
return _connectionlifetime->check(context);
}
//! Splits a buffer with 0 separators into a vector of strings.
@ -852,14 +600,324 @@ namespace pcsc {
}
return res;
}
//! Connection id
SCARDCONTEXT id() {
return _connectionlifetime->id();
}
//! @c true if exceptions are thrown
bool exc() {
return _connectionlifetime->exc();
}
//..............................................................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;
long _state;
std::map<std::string, shared_ptr<Reader>::t > _reader;
//! Readers are closed when the last shared object is destructed
std::map<std::string, mrw::Shared<Reader> > _readers;
//! 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