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. 61
      src/cryptoki.cxx
  7. 296
      src/cryptoki.hxx
  8. 196
      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,7 +166,7 @@ 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) {
CRYPTOKI_LOG("library: "<<library);
//! calls @c functionList
@ -181,41 +181,60 @@ namespace cryptoki {
+": 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() {
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),
_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,20 +625,36 @@ namespace cryptoki {
//@{
//! to be instanciated before first use
class Library {
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 */
Library(const std::string& library="opensc-pkcs11.so", bool exc=true):
_init(library, exc) {
}
public:
class Init {
private:
friend class Slot;
friend class Session;
friend class Object;
friend class Library;
bool _exc;
CK_RV _res;
CK_FUNCTION_LIST* _fn;
Init(const Init&); // forbidden
Init& operator=(const Init&); // forbidden
#ifndef WIN32
void* _lib;
#else
HINSTANCE _lib;
#endif
//! Initialize Funcion List for this Instance
bool functionList(const std::string& library);
@ -657,15 +674,7 @@ namespace cryptoki {
@param exc wether exceptions should be thrown */
Init(const std::string& library="opensc-pkcs11.so", bool exc=true);
~Init() {
CRYPTOKI_LOG("log");
try {
//! calls @c C_Finalize
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize"));
} catch (...) {
if (!std::uncaught_exception()) throw;
}
}
~Init();
Init& reset() {
check(_fn->C_Finalize(0), CRYPTOKI_FN_LOG("C_Finalize"));
@ -673,6 +682,10 @@ namespace cryptoki {
return *this;
}
CK_FUNCTION_LIST* fn() {
return _fn;
}
/*! @name C Like Error Handling
You are strongly recommended not to disable exception
@ -681,7 +694,8 @@ namespace cryptoki {
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();
/*! @return error text of last cryptoki call */
@ -689,12 +703,49 @@ namespace cryptoki {
//@}
};
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() {
return *_init;
}
/*! @return error text of last cryptoki call */
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;
@ -705,10 +756,16 @@ namespace cryptoki {
}
//! 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;
};
@ -716,23 +773,23 @@ namespace cryptoki {
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,19 +552,100 @@ 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 {
return *_connectionlifetime;
}
//................................................................methods
private:
//! Sets state and throws an exception if neccessary.
/*! @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="") {
_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="") {
return _connectionlifetime->check(context);
}
//! Splits a buffer with 0 separators into a vector of strings.
Strings split(const std::string& in) {
Strings res;
for (std::string::size_type pos(0); pos<in.size() && in[pos]!=0;
pos+=res.rbegin()->size()+1)
res.push_back(in.substr(pos).c_str());
return res;
}
//! Joins a vector of strings into a buffer with 0 separators.
std::string join(const Strings& in) {
std::string res;
if (in.size()) {
for (Strings::const_iterator it(in.begin());
it!=in.end(); ++it)
res+=*it+'\0';
res+='\0';
}
return res;
}
//! Connection id
SCARDCONTEXT id() {
return _connectionlifetime->id();
}
//! @c true if exceptions are thrown
bool exc() {
return _connectionlifetime->exc();
}
//..............................................................variables
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 {
@ -808,58 +885,39 @@ namespace pcsc {
}
return ss.str();
}
//................................................................methods
private:
//! Sets state and throws an exception if neccessary.
/*! @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;
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;
//! set state
void state(long s) {
_state = s;
}
//! Splits a buffer with 0 separators into a vector of strings.
Strings split(const std::string& in) {
Strings res;
for (std::string::size_type pos(0); pos<in.size() && in[pos]!=0;
pos+=res.rbegin()->size()+1)
res.push_back(in.substr(pos).c_str());
return res;
//! @returns state
long state() {
return _state;
}
//! Joins a vector of strings into a buffer with 0 separators.
std::string join(const Strings& in) {
std::string res;
if (in.size()) {
for (Strings::const_iterator it(in.begin());
it!=in.end(); ++it)
res+=*it+'\0';
res+='\0';
//! @returns connection id
SCARDCONTEXT id() {
return _id;
}
return res;
bool exc() {
return _exc;
}
//..............................................................variables
private:
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