fixed tons of warnings; refs #28

master
Marc Wäckerlin 11 years ago
parent 9596d5d760
commit 3012a6c5ed
  1. 5
      doc/examples/cardos-demo.cxx
  2. 6
      doc/examples/create-files-demo.cxx
  3. 14
      doc/examples/cryptoki-demo.cxx
  4. 11
      doc/examples/cryptoki-sign-demo.cxx
  5. 175
      src/cardos.hxx
  6. 11
      src/cryptaux.hxx
  7. 23
      src/cryptoki.cxx
  8. 536
      src/cryptoki.hxx
  9. 62
      src/openssl-engine.hxx
  10. 74
      src/openssl.hxx
  11. 2
      src/overview.doc
  12. 24
      src/pcsc.hxx
  13. 36
      src/suisseid.hxx

@ -104,9 +104,8 @@ class Commands: public cardos::Commands {
void selectReader() {
listReader();
if (_readers.size()<0) return;
int num(-1);
if (std::cin>>num && num>=0 && num<_readers.size()) {
pcsc::Connection::Strings::size_type num(0);
if (std::cin>>num && num<_readers.size()) {
_reader = pcsc::Connection::reader(_readers[num]);
std::cout<<"Active Reader: "<<_readers[num]<<std::endl;
} else throw std::runtime_error("no valid reader selected");

@ -21,8 +21,6 @@
#include <iostream>
#include <iomanip>
pcsc::Connection::Strings readers;
void list() {
pcsc::Connection::Strings readers(pcsc::Connection::scan());
std::cout<<"Found "<<readers.size()<<" readers"
@ -34,7 +32,7 @@ void list() {
}
int main(int argc, char** argv) try {
int reader(0);
unsigned int reader(0);
std::string pin;
std::string path("3f00");
std::string id("8888");
@ -62,7 +60,7 @@ int main(int argc, char** argv) try {
<<mrw::args::param(data, "text"))
);
pcsc::Connection::Strings readers(pcsc::Connection::scan());
if (reader<0 || readers.size()<reader) {
if (readers.size()<reader) {
std::cerr<<"reader not found: "<<reader<<std::endl;
return 1;
}

@ -75,14 +75,14 @@ int main(int argc, char const*const*const argv) try {
cryptoki::Session session(*it);
cryptoki::ObjectList objs(session.find());
std::cout<<"Objects Found: "<<objs.size()<<std::endl;
for (cryptoki::ObjectList::iterator it(objs.begin());
it!=objs.end(); ++it) {
for (cryptoki::ObjectList::iterator it2(objs.begin());
it2!=objs.end(); ++it2) {
std::cout<<"-------------------- Object -----------------"<<std::endl;
cryptoki::AttributeMap attrs(it->attributes());
for (cryptoki::AttributeMap::iterator it(attrs.begin());
it!=attrs.end(); ++it) {
std::cout<<" - attribute: "<<it->second.name()<<" = "<<std::endl
<<crypto::readable(it->second.value, 15, 5)<<std::endl;
cryptoki::AttributeMap attrs(it2->attributes());
for (cryptoki::AttributeMap::iterator it3(attrs.begin());
it3!=attrs.end(); ++it3) {
std::cout<<" - attribute: "<<it3->second.name()<<" = "<<std::endl
<<crypto::readable(it3->second.value, 15, 5)<<std::endl;
}
}
std::cout<<"**** Success"<<std::endl;

@ -71,17 +71,18 @@ int main(int argc, char** argv) try {
cryptoki::ObjectList certs
(session.find(cryptoki::Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
for (cryptoki::ObjectList::iterator c(certs.begin()); c!=certs.end(); ++c) {
std::string label(c->attribute(CKA_LABEL).value);
for (cryptoki::ObjectList::iterator it(certs.begin());
it!=certs.end(); ++it) {
std::string label(it->attribute(CKA_LABEL).value);
if (cert.size()&&cert!=label) continue;
cryptoki::Attribute id(c->attribute(CKA_ID));
cryptoki::Attribute id(it->attribute(CKA_ID));
cryptoki::ObjectList keys
(session.find(cryptoki::Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY),
id));
if (!keys.size()) continue;
std::cout<<"Found Certificate: "
<<c->attribute(CKA_LABEL).value<<std::endl;
<<it->attribute(CKA_LABEL).value<<std::endl;
if (!cert.size()) continue;
std::cout<<"Pin: ";
std::string pin;
@ -98,7 +99,7 @@ int main(int argc, char** argv) try {
#ifndef MRW__OLD_PRE11_COMPILER
auto start = std::chrono::system_clock::now();
#endif
for (int i(0); i<r; ++i)
for (unsigned int i(0); i<r; ++i)
std::cout<<"Text:"<<std::endl
<<crypto::readable(txt)<<std::endl
<<"Signature:"<<std::endl

@ -111,7 +111,7 @@ namespace cardos {
//----------------------------------------------------------------------------
class array_range: public exception {
public:
array_range(unsigned int i, unsigned int j) throw():
array_range(unsigned long i, unsigned long j) throw():
exception("array index out of range: "+mrw::string(i)
+"; length: "+mrw::string(j)) {
}
@ -198,16 +198,16 @@ namespace cardos {
public:
BerValue(unsigned char tag, const std::string& value):
_tag(tag), _value(value) {
BerValue(unsigned char t, const std::string& v):
_tag(t), _value(v) {
if (isContainer())
while (_value.size()) _sequence.push_back(BerValue(_value));
}
BerValue(unsigned char tag, const std::vector<BerValue>& values):
_tag(tag), _sequence(values) {
BerValue(unsigned char t, const std::vector<BerValue>& vs):
_tag(t), _sequence(vs) {
if (!isContainer())
throw runtime_error("BER tag 0x"+crypto::binToHex(tag)
throw runtime_error("BER tag 0x"+crypto::binToHex(_tag)
+" is not a container");
}
@ -227,7 +227,7 @@ namespace cardos {
return tagPC()==CONSTRUCTED;
}
unsigned int size() {
std::vector<BerValue>::size_type size() {
return _sequence.size();
}
@ -235,7 +235,7 @@ namespace cardos {
return _tag;
}
BerValue operator[](unsigned int i) {
BerValue operator[](std::vector<BerValue>::size_type i) {
if (i>=_sequence.size()) throw array_range(i, _sequence.size());
return _sequence[i];
}
@ -424,13 +424,13 @@ namespace cardos {
Commands() {}
/// Initialize with given smart card reader.
Commands(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader):
_reader(reader) {
Commands(pcsc::shared_ptr<pcsc::Connection::Reader>::t r):
_reader(r) {
}
/// Set smart card reader.
void reader(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader) {
_reader = reader;
void reader(pcsc::shared_ptr<pcsc::Connection::Reader>::t r) {
_reader = r;
}
//@}
@ -446,10 +446,10 @@ namespace cardos {
will not return an error, if the current file is already
active.
@prereq The command can only be executed, if the right
referenced by the files AC ACTIVATE is granted in
the security status of the current DF. The command
cannot be applied to CODE files. */
@pre The command can only be executed, if the right
referenced by the files AC ACTIVATE is granted in the
security status of the current DF. The command cannot
be applied to CODE files. */
void activateFile() {
CRYPTOLOG("log");
check(send(0x00, 0x44, 0x00, 0x00));
@ -480,10 +480,8 @@ namespace cardos {
<table>
<caption>Bytes P1-P2</caption>
<thead>
<tr><td colspan="2">P1 (MODE)</td><td>P2</td><td>Meaning</td></tr>
<tr><td>Bit 7</td><td>Bits 6 0</td><td/><td/></tr>
</thead>
<tr><td>Bit 7</td><td>Bits 6 0</td><td></td><td></td></tr>
<tr>
<td>1</td><td>HI value</td><td>LO value</td>
<td>Allocate buffer with size HI-LO</td>
@ -493,8 +491,8 @@ namespace cardos {
</tr>
</table>
@prereq The command can only be executed, if the right
referenced by the MFs AC ALLOCATE is granted.
@pre The command can only be executed, if the right
referenced by the MFs AC ALLOCATE is granted.
@returns 1 byte: ID of allocated buffer
@ -502,7 +500,8 @@ namespace cardos {
std::string allocateTransactionBuffer(unsigned short size) {
CRYPTOLOG("log");
if (size>0x7FFF) throw runtime_error("requested buffer too large");
return check(send(0x80, 0x12, 8|size>>8, size&0xFF));
return check(send(0x80, 0x12, (unsigned char)(8|size>>8),
(unsigned char)(size&0xFF)));
}
//! Free transaction buffer
@ -553,9 +552,9 @@ namespace cardos {
the record consists of one byte. The tag byte is not
interpreted by APPEND RECORD.
@prereq The command can only be executed, if the right
referenced by the files AC APPEND is granted in the
security status of the current DF. */
@pre The command can only be executed, if the right
referenced by the files AC APPEND is granted in the
security status of the current DF. */
void appendRecord(unsigned char efId, std::string data) {
CRYPTOLOG("log");
check(send(0x00, 0xE2, 0x00, efId, data));
@ -577,7 +576,7 @@ namespace cardos {
- the number of loaded Packages (s. GET DATA command, mode 88h)
- the system internal parameters (9 bytes consisting 22h) and
- optionally, the Chip Unique Identification Number
(as indicated in mode byte P1, @refs getData, mode 81h,
(as indicated in mode byte P1, @ref getData, mode 81h,
Bytes 11-16).
The commands supports 2 modes indicated by the parameter P1:
@ -594,28 +593,37 @@ namespace cardos {
chapter 2.4.2.4
<table>
<caption>Format of the input for hash value calculation</caption>
<thead><tr>
<th>System_Challenge</th>
<th>Command Header<br/>CLA INS P1 P2</th>
<th>Global Life Cycle Phase</th>
<th>Internal Parameters</th>
<th>Number of loaded Packages</th>
<th>Chip Unique Identification Number (opt.)</th>
</tr></thead>
<tr>
<td>xxhxxh</td><td>80h 88h Mode 00h</td><td>xxh</td>
<td>22h22h</td><td>xxh</td><td>xxhxxh</td>
</tr><tr>
<td>n bytes</td><td>4 bytes</td><td>1 byte</td><td>9 bytes</td>
<td>1 byte</td><td>6 bytes/empty</td>
</tr>
<caption>Format of the input for hash value calculation</caption>
<tr>
<th>System_Challenge</th>
<th>Command Header<br/>CLA INS P1 P2</th>
<th>Global Life Cycle Phase</th>
<th>Internal Parameters</th>
<th>Number of loaded Packages</th>
<th>Chip Unique Identification Number (opt.)</th>
</tr>
<tr>
<td>xxhxxh</td>
<td>80h 88h Mode 00h</td>
<td>xxh</td>
<td>22h22h</td>
<td>xxh</td>
<td>xxhxxh</td>
</tr>
<tr>
<td>n bytes</td>
<td>4 bytes</td>
<td>1 byte</td>
<td>9 bytes</td>
<td>1 byte</td>
<td>6 bytes/empty</td>
</tr>
</table>
@prereq The System_Challenge provided by the application
must be greater or equal to 16 bytes. Since the
command does not support chaining, the length of the
System_Challenge is limited by the IO buffer size.
@pre The System_Challenge provided by the application must
be greater or equal to 16 bytes. Since the command
does not support chaining, the length of the
System_Challenge is limited by the IO buffer size.
@note The application must use the corresponding RSA2 public
key to verify the Digital Signature received from the
@ -653,7 +661,7 @@ namespace cardos {
}
//! Creates a file (only EF or DF)
void createFile(std::string path="", const std::string data="") {
void createFile(std::string /*path*/="", const std::string& /*data*/="") {
CRYPTOLOG("log");
// pcsc::Connection::Reader::Transaction lock(_reader);
// if (path.size()) select(path);
@ -818,8 +826,8 @@ namespace cardos {
CRYPTOLOG("log");
std::string data;
data.resize(2);
data[0] = size>>8;
data[1] = size&0xff;
data[0] = char((unsigned char)(size>>8));
data[1] = char((unsigned char)(size&0xff));
return check(send(0x80, 0x32, 0x00, efId, data)); // 0x08 or 0x80?
// old code was 0x80, manual says 0x08 (manual exactly says: "8xh")
}
@ -907,13 +915,13 @@ namespace cardos {
can also be undone (without reset) with another PHASE
CONTROL command.
@prereq Changing from ADMINISTRATION to OPERATIONAL is not
protected. Changing from OPERATIONAL to
ADMINISTRATION is controlled by the right referenced
by the current DFs AC LCYCLE.
@pre Changing from ADMINISTRATION to OPERATIONAL is not
protected. Changing from OPERATIONAL to ADMINISTRATION
is controlled by the right referenced by the current
DFs AC LCYCLE.
@prereq The command can be executed in the life cycle phases
ADMINISTRATION and OPERATIONAL. */
@pre The command can be executed in the life cycle phases
ADMINISTRATION and OPERATIONAL. */
void phaseControl() {
CRYPTOLOG("log");
check(send(0x80, 0x10, 0x00, 0x00));
@ -930,7 +938,8 @@ namespace cardos {
CRYPTOLOG("log");
pcsc::Connection::Reader::Transaction lock(_reader);
if (path.size()) select(path);
return check(send(0x00, 0xB0, offset>>8, offset&0xFF));
return check(send(0x00, 0xB0, (unsigned char)(offset>>8),
(unsigned char)(offset&0xFF)));
}
enum ReadRecordMode {
@ -950,7 +959,8 @@ namespace cardos {
CRYPTOLOG("log");
pcsc::Connection::Reader::Transaction lock(_reader);
if (path.size()) select(path);
return check(send(0x00, 0xB2, record, (sfi&0xF8)|mode));
return check(send(0x00, 0xB2, record,
(unsigned char)((sfi&0xF8)|mode)));
}
/// Read all records from a record oriented file
@ -1042,7 +1052,8 @@ namespace cardos {
//! Updates a BINARY file
void updateBinary(std::string data, unsigned short offset=0) {
CRYPTOLOG("log");
check(send(0x00, 0xD6, offset>>8, offset&0xFF, data));
check(send(0x00, 0xD6, (unsigned char)(offset>>8),
(unsigned char)(offset&0xFF), data));
}
//! Overwrites an existing record.
@ -1051,7 +1062,8 @@ namespace cardos {
unsigned char sfi = 0,
ReadRecordMode mode = ABSOLUTE_RECORD) {
CRYPTOLOG("log");
return check(send(0x00, 0xDC, record, (sfi&0xF8)|mode, data));
return check(send(0x00, 0xDC, record,
(unsigned char)((sfi&0xF8)|mode), data));
}
enum VerifyMode {
@ -1063,14 +1075,14 @@ namespace cardos {
void verify(std::string pin, unsigned char id,
VerifyMode mode = SEARCH_FROM_DF) {
CRYPTOLOG("log");
check(send(0x00, 0x20, 0x00, id|mode, pin));
check(send(0x00, 0x20, 0x00, (unsigned char)(id|mode), pin));
}
//! Performs a PIN test (CHV test)
/*! @return number of remaining PIN retries or -1 if PIN is locked */
int verify(unsigned char id, VerifyMode mode = SEARCH_FROM_DF) {
CRYPTOLOG("log");
std::string res(send(0x00, 0x20, 0x00, id|mode));
std::string res(send(0x00, 0x20, 0x00, (unsigned char)(id|mode)));
unsigned int value((((unsigned int)(unsigned char)res[0])*256)
+((unsigned int)(unsigned char)res[1]));
if ((value&0x63C0)==0x63C0) return value&0x0F;
@ -1511,7 +1523,9 @@ namespace cardos {
return result;
}
std::string send(char cla, char ins, char p1, char p2, std::string lc) {
std::string send(unsigned char cla, unsigned char ins,
unsigned char p1, unsigned char p2,
std::string lc) {
if (!_reader) throw runtime_error("no reader selected");
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
<<" ins="<<crypto::binToHex(ins)
@ -1521,7 +1535,8 @@ namespace cardos {
return logResult(_reader->transmit(cla, ins, p1, p2, lc));
}
std::string send(char cla, char ins, char p1, char p2) {
std::string send(unsigned char cla, unsigned char ins,
unsigned char p1, unsigned char p2) {
if (!_reader) throw runtime_error("no reader selected");
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
<<" ins="<<crypto::binToHex(ins)
@ -1545,7 +1560,7 @@ namespace cardos {
typedef pcsc::shared_ptr<Object>::t Child;
typedef std::vector<Child> Children;
public:
Object(const std::string& path): _path(path) {}
Object(const std::string& p): _path(p) {}
virtual ~Object() {}
virtual const std::string& path() const {
return _path;
@ -1618,11 +1633,11 @@ namespace cardos {
/// Represents a File on a Smart Card
class File: public Object {
public:
File(Commands& cmd, const std::string& path, const std::string& file):
Object(path), _file(file) {
CRYPTOLOG("new file "<<file<<" at "<<path);
File(Commands& cmd, const std::string& p, const std::string& file):
Object(p), _file(file) {
CRYPTOLOG("new file "<<file<<" at "<<p);
try {
_content = cmd.readBinary(path+file);
_content = cmd.readBinary(p+file);
try {
_contentInfo = cardos::BerValues(_content).print();
} catch (...) {
@ -1631,9 +1646,9 @@ namespace cardos {
_contentInfo = x.what();
}
}
File(const std::string& path, const std::string& file):
Object(path), _file(file) {
CRYPTOLOG("new file "<<file<<" at "<<path);
File(const std::string& p, const std::string& file):
Object(p), _file(file) {
CRYPTOLOG("new file "<<file<<" at "<<p);
}
std::string name() const {
return _file;
@ -1660,9 +1675,9 @@ namespace cardos {
/// Represents a Link on a Smart Card
class Link: public File {
public:
Link(Commands& cmd, const std::string& path, const std::string& file):
File(cmd, path, file) {
CRYPTOLOG("new link "<<file<<" at "<<path);
Link(Commands& cmd, const std::string& p, const std::string& file):
File(cmd, p, file) {
CRYPTOLOG("new link "<<file<<" at "<<p);
}
std::string type() const {
return "Link";
@ -1673,11 +1688,11 @@ namespace cardos {
/// Represents a Counter on a Smart Card
class Counter: public File {
public:
Counter(Commands& cmd, const std::string& path, const std::string& file):
File(path, file) {
CRYPTOLOG("new counter "<<file<<" at "<<path);
Counter(Commands& cmd, const std::string& p, const std::string& file):
File(p, file) {
CRYPTOLOG("new counter "<<file<<" at "<<p);
try {
_content = cmd.readRecord(path+file);
_content = cmd.readRecord(p+file);
std::stringstream s;
s<<crypto::ulongFromBinary(_content);
_contentInfo = s.str();
@ -1694,8 +1709,8 @@ namespace cardos {
/// Represents a Directory on a Smart Card
class Dir: public Object {
public:
Dir(Commands& cmd, const std::string& path): Object(path) {
CRYPTOLOG("new directory path="<<path);
Dir(Commands& cmd, const std::string& p): Object(p) {
CRYPTOLOG("new directory path="<<p);
setup(cmd);
}
std::string name() const {

@ -80,6 +80,11 @@
# endif
#endif
namespace pcsc {
/// Get library version identification
std::string version();
}
//! @ref gcrypto @copydoc gcrypto
namespace crypto {
@ -165,9 +170,9 @@ namespace crypto {
<<s.find_first_not_of(HEX))).str());
std::string res;
for (std::string::const_iterator it(s.begin()); it!=s.end(); ++it) {
unsigned char c(HEX.find(*it));
std::string::size_type c(HEX.find(*it));
if (++it!=s.end()) (c <<= 4) += HEX.find(*it);
res += std::string(1, (char)c);
res += std::string(1, (std::string::value_type)c);
}
return res;
}
@ -176,7 +181,7 @@ namespace crypto {
inline std::string toBinary(unsigned long data, int bytes=2) {
std::string res(0, bytes);
for (int i(0); i<bytes; ++i) {
res[i] = data&0xff;
res[i] = std::string::value_type(data&0xff);
data>>=8;
}
return res;

@ -33,33 +33,38 @@ namespace cryptoki {
if (!_lib) throw exception("open of library failed: "+library);
CRYPTOLOG("loaded: "<<library);
#ifndef WIN32
CK_C_GetFunctionList fn
((CK_C_GetFunctionList)dlsym(_lib, "C_GetFunctionList"));
/// @bug in dlsym: returns void* but should return void(*)()
CK_C_GetFunctionList fnl
(reinterpret_cast<CK_C_GetFunctionList>
(reinterpret_cast<long long>
(dlsym(_lib, "C_GetFunctionList"))));
#else
CK_C_GetFunctionList fn
CK_C_GetFunctionList fnl
((CK_C_GetFunctionList)GetProcAddress(_lib, "C_GetFunctionList"));
#endif
if (!fn)
if (!fnl)
throw exception("required library symbol C_GetFunctionList not found in "
+library);
CRYPTOLOG("Got C_GetFunctionList, now call it");
//! calls @c C_GetFunctionList
return check(fn(&_fn), CRYPTOKI_FN_LOG("C_GetFunctionList"));
return check(fnl(&_fn), CRYPTOKI_FN_LOG("C_GetFunctionList"));
}
bool Library::Init::check(CK_RV result, const std::string& context) {
_res = result;
if (_exc && !*this)
if (context.size())
if (_exc && !*this) {
if (context.size()) {
if (_res==CKR_PIN_INCORRECT)
throw wrong_pin(context+": "+error());
else
throw access_error(context+": "+error());
else
} else {
if (_res==CKR_PIN_INCORRECT)
throw wrong_pin(error());
else
throw access_error(error());
}
}
return _res==CKR_OK;
}
@ -344,7 +349,7 @@ namespace cryptoki {
attrs.push_back(Attribute(CKA_SECONDARY_AUTH).from<CK_BBOOL>(FALSE));
attrs.push_back(Attribute(CKA_DECRYPT) // Required by Doujak/Inverardi
.from<CK_BBOOL>(usage&(X509v3_KU_DATA_ENCIPHERMENT
|usage&X509v3_KU_KEY_ENCIPHERMENT)
|(usage&X509v3_KU_KEY_ENCIPHERMENT))
?TRUE:FALSE)); // instead of CKA_UNWRAP
attrs.push_back(Attribute(CKA_SIGN)
.from<CK_BBOOL>(usage&(X509v3_KU_DIGITAL_SIGNATURE

@ -54,7 +54,7 @@
#if __GNUC__ >= 2
//! Cryptoki Error Message Formatting
/*! If you want to change cryptoki error formatting, just
redefine your own CRYPTOKY_FN_LOG macro before <code>#include
redefine your own CRYPTOKY_FN_LOG macro before <code>\#include
&lt;cryptoki.hxx&gt;</code>.
#return std::String */
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
@ -64,19 +64,15 @@
#define CRYPTOKI_QUOTE2(X) #X
//! Cryptoki Error Message Formatting
/*! If you want to change cryptoki error formatting, just
redefine your own CRYPTOKY_FN_LOG macro before <code>#include
redefine your own CRYPTOKY_FN_LOG macro before <code>\#include
&lt;cryptoki.hxx&gt;</code>.
#return std::String */
@return string */
#define CRYPTOKI_FN_LOG(X) X " failed in \
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__)
#endif
#endif
//@}
namespace pcsc {
std::string version();
}
//! @ref gcryptoki @copydoc gcryptoki
namespace cryptoki {
@ -261,7 +257,7 @@ namespace cryptoki {
std::string res(indent, ' ');
switch (type) {
case CKA_CLASS:
switch (*((CK_OBJECT_CLASS*)&value[0])) {
switch (*((const CK_OBJECT_CLASS*)&value[0])) {
case CKO_DATA: return res+"DATA";
case CKO_CERTIFICATE: return res+"CERTIFICATE";
case CKO_PUBLIC_KEY: return res+"PUBLIC_KEY";
@ -279,7 +275,7 @@ namespace cryptoki {
/** To use this method, you must know what type the attribute
represents. */
template<typename TYPE> Attribute& from(const TYPE& v) {
value = std::string((char*)&v, sizeof(TYPE));
value = std::string((const char*)&v, sizeof(TYPE));
return *this;
}
/// Convert to a given type.
@ -1107,9 +1103,9 @@ namespace cryptoki {
shared library. Normally you need only one instance.
@param library name of the shared library that supports pkcs#11
@param exc wether exceptions should be thrown */
Library(const std::string& library, bool exc=true):
_init(new Init(library, exc)) {
@param exceptions whether exceptions should be thrown */
Library(const std::string& library, bool exceptions=true):
_init(new Init(library, exceptions)) {
CRYPTOLOG("log");
}
@ -1545,7 +1541,8 @@ namespace cryptoki {
public:
//! Opens a new session.
/*! @param slot slot to open a session on */
/*! @param slot slot to open a session on
@param rw whether session is read/write or read only*/
Session(const Slot& slot, bool rw=false):
_slot(slot), _session(0), _res(CKR_OK) {
CRYPTOLOG("log");
@ -1553,8 +1550,7 @@ namespace cryptoki {
//! @todo pass parameter
}
//! Opens a new session.
/*! @param slot slot to open a session on */
//! Copy session.
Session(const Session& o):
_slot(o._slot), _session(o._session), _res(CKR_OK) {
CRYPTOLOG("log");
@ -1822,6 +1818,26 @@ namespace cryptoki {
CRYPTOKI_FN_LOG("C_GetSessionInfo"));
return info;
}
/*! @todo Not implemented:
@code
bool seedrandom() {
CRYPTOLOG("log");
//! calls @c C_SeedRandom
return check(_slot.library()->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SeedRandom"));
}
@endcode */
/*! @todo Not implemented:
@code
bool setpin() {
CRYPTOLOG("log");
//! calls @c C_SetPIN
return check(_slot.library()->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetPIN"));
}
@endcode */
/*! @todo Not implemented:
@code
@ -1833,6 +1849,13 @@ namespace cryptoki {
}
@endcode */
//@}
/** @name login with pin
Unlock access with pin (login) and unlock after use (logout). */
//@{
private:
class Login {
@ -1846,8 +1869,8 @@ namespace cryptoki {
//! calls @c C_Login
_session.check(_session._slot.library()->C_Login
(_session._session, userType,
(CK_CHAR*)pin.c_str(),
pin.size()),
const_cast<CK_CHAR*>((const CK_CHAR*)pin.c_str()),
(int)pin.size()),
CRYPTOKI_FN_LOG("C_Login"));
}
@ -1874,37 +1897,26 @@ namespace cryptoki {
public:
void login(const std::string& pin, CK_USER_TYPE userType=CKU_USER) {
/// Login to card
/** @param pin to unlock card
@param userType user type */
void login(const std::string& pin,
CK_USER_TYPE userType=CKU_USER) {
CRYPTOLOG("log");
_login = new Login(*this, pin, userType);
}
/// Logout from card
/** Undo the last login. */
void logout() {
CRYPTOLOG("log");
_login.reset();
}
mrw::Shared<Login> _login;
/*! @todo Not implemented:
@code
bool seedrandom() {
CRYPTOLOG("log");
//! calls @c C_SeedRandom
return check(_slot.library()->C_SeedRandom(_session, CK_BYTE_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SeedRandom"));
}
@endcode */
/*! @todo Not implemented:
@code
bool setpin() {
CRYPTOLOG("log");
//! calls @c C_SetPIN
return check(_slot.library()->C_SetPIN(_session, CK_CHAR_PTR, CK_ULONG, CK_CHAR_PTR, CK_ULONG),
CRYPTOKI_FN_LOG("C_SetPIN"));
}
@endcode */
//@}
};
class Object {
@ -1985,6 +1997,218 @@ namespace cryptoki {
//! @todo don't call verifyfinal()?
}
bool destroy() {
CRYPTOLOG("log");
//! calls @c C_DestroyObject
return check(_session._slot.library()->C_DestroyObject
(_session._session, _object),
CRYPTOKI_FN_LOG("C_DestroyObject"));
}
//! Get a Single Attribute
Attribute operator[](CK_ATTRIBUTE_TYPE a) {
CRYPTOLOG("log");
return attribute(a);
}
//! Get a Single Attribute
Attribute attribute(CK_ATTRIBUTE_TYPE a) {
CRYPTOLOG("log");
Attribute res;
CK_ATTRIBUTE attr(CK_ATTRIBUTE{a, 0, 0});
//! calls @c C_GetAttributeValue
if (!check(_session._slot.library()->C_GetAttributeValue
(_session._session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))
|| !(long)attr.ulValueLen>0l)
//! Without exception handling, size and type must be checked too.
return res;
try {
attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
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
Cryptoki. From the Specs: «In the special case
of an attribute whose value is an array of
attributes, for example CKA_WRAP_TEMPLATE, where
it is passed in with pValue not NULL, then if
the pValue of elements within the array is
NULL_PTR then the ulValueLen of elements within
the array will be set to the required length. If
the pValue of elements within the array is not
NULL_PTR, then the ulValueLen element of
attributes within the array must reflect the
space that the corresponding pValue points to,
and pValue is filled in if there is sufficient
room. Therefore it is important to initialize
the contents of a buffer before calling
C_GetAttributeValue to get such an array
value. If any ulValueLen within the array isn't
large enough, it will be set to -1 and the
function will return CKR_BUFFER_TOO_SMALL, as it
does if an attribute in the pTemplate argument
has ulValueLen too small. Note that any
attribute whose value is an array of attributes
is identifiable by virtue of the attribute type
having the CKF_ARRAY_ATTRIBUTE bit set.» */
res = Attribute(attr);
else
free(attr.pValue);
} catch (...) {
free(attr.pValue);
throw;
}
return res;
}
//! Get a List of Attributes.
/*! If @c attrs is empty, all available attributes are
returned. Attributes that cannot be accessed or that are not
available in this Object won't be in the result map. There
is no exception in this case. */
AttributeMap attributes(AttributeTypeList attrs
= AttributeTypeList()) {
CRYPTOLOG("log");
AttributeMap res;
//! Gets all attributes, if @c attrs is empty
if (attrs.empty()) {
attrs.push_back(CKA_CLASS);
attrs.push_back(CKA_TOKEN);
attrs.push_back(CKA_PRIVATE);
attrs.push_back(CKA_LABEL);
attrs.push_back(CKA_APPLICATION);
attrs.push_back(CKA_VALUE);
attrs.push_back(CKA_OBJECT_ID);
attrs.push_back(CKA_CERTIFICATE_TYPE);
attrs.push_back(CKA_ISSUER);
attrs.push_back(CKA_SERIAL_NUMBER);
attrs.push_back(CKA_AC_ISSUER);
attrs.push_back(CKA_OWNER);
attrs.push_back(CKA_ATTR_TYPES);
attrs.push_back(CKA_TRUSTED);
attrs.push_back(CKA_KEY_TYPE);
attrs.push_back(CKA_SUBJECT);
attrs.push_back(CKA_ID);
attrs.push_back(CKA_SENSITIVE);
attrs.push_back(CKA_ENCRYPT);
attrs.push_back(CKA_DECRYPT);
attrs.push_back(CKA_WRAP);
attrs.push_back(CKA_UNWRAP);
attrs.push_back(CKA_SIGN);
attrs.push_back(CKA_SIGN_RECOVER);
attrs.push_back(CKA_VERIFY);
attrs.push_back(CKA_VERIFY_RECOVER);
attrs.push_back(CKA_DERIVE);
attrs.push_back(CKA_START_DATE);
attrs.push_back(CKA_END_DATE);
attrs.push_back(CKA_MODULUS);
attrs.push_back(CKA_MODULUS_BITS);
attrs.push_back(CKA_PUBLIC_EXPONENT);
attrs.push_back(CKA_PRIVATE_EXPONENT);
attrs.push_back(CKA_PRIME_1);
attrs.push_back(CKA_PRIME_2);
attrs.push_back(CKA_EXPONENT_1);
attrs.push_back(CKA_EXPONENT_2);
attrs.push_back(CKA_COEFFICIENT);
attrs.push_back(CKA_PRIME);
attrs.push_back(CKA_SUBPRIME);
attrs.push_back(CKA_BASE);
attrs.push_back(CKA_PRIME_BITS);
//attrs.push_back(CKA_SUBPRIME_BITS);
attrs.push_back(CKA_VALUE_BITS);
attrs.push_back(CKA_VALUE_LEN);
attrs.push_back(CKA_EXTRACTABLE);
attrs.push_back(CKA_LOCAL);
attrs.push_back(CKA_NEVER_EXTRACTABLE);
attrs.push_back(CKA_ALWAYS_SENSITIVE);
attrs.push_back(CKA_KEY_GEN_MECHANISM);
attrs.push_back(CKA_MODIFIABLE);
attrs.push_back(CKA_ECDSA_PARAMS);
attrs.push_back(CKA_EC_PARAMS);
attrs.push_back(CKA_EC_POINT);
attrs.push_back(CKA_SECONDARY_AUTH);
attrs.push_back(CKA_AUTH_PIN_FLAGS);
attrs.push_back(CKA_HW_FEATURE_TYPE);
attrs.push_back(CKA_RESET_ON_INIT);
attrs.push_back(CKA_HAS_RESET);
attrs.push_back(CKA_VENDOR_DEFINED);
//attrs.push_back(CKA_IBM_OPAQUE);
}
CK_ATTRIBUTE attr;
for (AttributeTypeList::const_iterator it(attrs.begin());
it!=attrs.end(); ++it) {
attr = CK_ATTRIBUTE{*it, 0, 0};
try {
//! calls @c C_GetAttributeValue
if (_session._slot.library()->C_GetAttributeValue
(_session._session, _object, &attr, 1)
== CKR_ATTRIBUTE_TYPE_INVALID
|| _res == CKR_ATTRIBUTE_SENSITIVE) {
continue; //! Ignores unsupported Attributes.
} else {
check(_res, CRYPTOKI_FN_LOG("C_GetAttributeValue"));
if ((long)attr.ulValueLen>0l) {
attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
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
Cryptoki. From the Specs: «In the special
case of an attribute whose value is an
array of attributes, for example
CKA_WRAP_TEMPLATE, where it is passed in
with pValue not NULL, then if the pValue
of elements within the array is NULL_PTR
then the ulValueLen of elements within the
array will be set to the required
length. If the pValue of elements within
the array is not NULL_PTR, then the
ulValueLen element of attributes within
the array must reflect the space that the
corresponding pValue points to, and pValue
is filled in if there is sufficient
room. Therefore it is important to
initialize the contents of a buffer before
calling C_GetAttributeValue to get such an
array value. If any ulValueLen within the
array isn't large enough, it will be set
to -1 and the function will return
CKR_BUFFER_TOO_SMALL, as it does if an
attribute in the pTemplate argument has
ulValueLen too small. Note that any
attribute whose value is an array of
attributes is identifiable by virtue of
the attribute type having the
CKF_ARRAY_ATTRIBUTE bit set.» */
res.insert(std::make_pair(attr.type, Attribute(attr)));
else
free(attr.pValue);
} else if (*it==CKA_MODULUS && attr.ulValueLen==0) {
/*! @bug This is a bug in opensc-pkcs11.so: If
@c CKA_MODULUS has a size of 0 bytes, the
following query to @c CKA_MODULUS_BITS ends
in a segmentation fault.
@note @c CKA_MODULUS @b must immediately be
followed by @c CKA_MODULUS_BITS in the
attribute list, because if the size of @c
CKA_MODULUS is 0 Bytes, the following
attribute query is skipped as a work around
to this bug. */
if (++it==attrs.end()) break;
}
}
} catch (...) {
free(attr.pValue);
throw;
}
}
return res;
}
//@}
/*! @name C Like Error Handling
@ -2046,13 +2270,15 @@ namespace cryptoki {
//! calls @c C_Decrypt
check(_session._slot.library()->C_Decrypt
(_session._session,
(unsigned char*)&in[0], in.size(), 0, &size),
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]),
in.size(), 0, &size),
CRYPTOKI_FN_LOG("C_Decrypt"));
CRYPTOLOG("maximum size is "<<size<<"Bytes");
res.resize(size, 0);
check(_session._slot.library()->C_Decrypt
(_session._session,
(unsigned char*)&in[0], in.size(),
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]),
in.size(),
(unsigned char*)&res[0], &size),
CRYPTOKI_FN_LOG("C_Decrypt"));
CRYPTOLOG("exact size is "<<size<<"Bytes");
@ -2068,7 +2294,7 @@ namespace cryptoki {
//! calls @c C_DecryptDigestUpdate
check(_session._slot.library()->C_DecryptDigestUpdate
(_session._session,
(unsigned char*)&in[0], in.size(),
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), in.size(),
(unsigned char*)&res[0], &size),
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate"));
res.resize(size);
@ -2230,7 +2456,6 @@ namespace cryptoki {
CRYPTOKI_FN_LOG("C_VerifyUpdate"));
}
@endcode */
//@}
/*! @todo Not implemented:
@code
@ -2243,15 +2468,6 @@ namespace cryptoki {
}
@endcode */
bool destroy() {
CRYPTOLOG("log");
//! calls @c C_DestroyObject
return check(_session._slot.library()->C_DestroyObject
(_session._session, _object),
CRYPTOKI_FN_LOG("C_DestroyObject"));
}
/*! @todo Not implemented:
@code
bool digestkey() {
@ -2265,7 +2481,8 @@ namespace cryptoki {
bool encryptinit(CK_MECHANISM_TYPE type, const std::string& param) {
CRYPTOLOG("log");
CK_MECHANISM mech = {
type, param.size()?(void*)&param[0]:0, param.size()
type, param.size()?const_cast<CK_VOID_PTR>((const void*)&param[0]):0,
param.size()
};
CRYPTOLOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
@ -2283,13 +2500,14 @@ namespace cryptoki {
//! calls @c C_Encrypt
check(_session._slot.library()->C_Encrypt
(_session._session,
(unsigned char*)&in[0], in.size(), 0, &size),
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]),
in.size(), 0, &size),
CRYPTOKI_FN_LOG("C_Decrypt"));
CRYPTOLOG("maximum size is "<<size<<"Bytes");
res.resize(size, 0);
check(_session._slot.library()->C_Encrypt
(_session._session,
(unsigned char*)&in[0], in.size(),
const_cast<CK_BYTE_PTR>((const unsigned char*)&in[0]), in.size(),
(unsigned char*)&res[0], &size),
CRYPTOKI_FN_LOG("C_Encrypt"));
res.resize(size);
@ -2345,211 +2563,6 @@ namespace cryptoki {
}
@endcode */
//! Get a Single Attribute
Attribute operator[](CK_ATTRIBUTE_TYPE a) {
CRYPTOLOG("log");
return attribute(a);
}
//! Get a Single Attribute
Attribute attribute(CK_ATTRIBUTE_TYPE a) {
CRYPTOLOG("log");
Attribute res;
CK_ATTRIBUTE attr((CK_ATTRIBUTE){a, 0, 0});
//! calls @c C_GetAttributeValue
if (!check(_session._slot.library()->C_GetAttributeValue
(_session._session, _object, &attr, 1),
CRYPTOKI_FN_LOG("C_GetAttributeValue"))
|| !(long)attr.ulValueLen>0l)
//! Without exception handling, size and type must be checked too.
return res;
try {
attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
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
Cryptoki. From the Specs: «In the special case
of an attribute whose value is an array of
attributes, for example CKA_WRAP_TEMPLATE, where
it is passed in with pValue not NULL, then if
the pValue of elements within the array is
NULL_PTR then the ulValueLen of elements within
the array will be set to the required length. If
the pValue of elements within the array is not
NULL_PTR, then the ulValueLen element of
attributes within the array must reflect the
space that the corresponding pValue points to,
and pValue is filled in if there is sufficient
room. Therefore it is important to initialize
the contents of a buffer before calling
C_GetAttributeValue to get such an array
value. If any ulValueLen within the array isn't
large enough, it will be set to -1 and the
function will return CKR_BUFFER_TOO_SMALL, as it
does if an attribute in the pTemplate argument
has ulValueLen too small. Note that any
attribute whose value is an array of attributes
is identifiable by virtue of the attribute type
having the CKF_ARRAY_ATTRIBUTE bit set.» */
res = Attribute(attr);
else
free(attr.pValue);
} catch (...) {
free(attr.pValue);
throw;
}
return res;
}
//! Get a List of Attributes.
/*! If @c attrs is empty, all available attributes are
returned. Attributes that cannot be accessed or that are not
available in this Object won't be in the result map. There
is no exception in this case. */
AttributeMap attributes(AttributeTypeList attrs
= AttributeTypeList()) {
CRYPTOLOG("log");
AttributeMap res;
//! Gets all attributes, if @c attrs is empty
if (attrs.empty()) {
attrs.push_back(CKA_CLASS);
attrs.push_back(CKA_TOKEN);
attrs.push_back(CKA_PRIVATE);
attrs.push_back(CKA_LABEL);
attrs.push_back(CKA_APPLICATION);
attrs.push_back(CKA_VALUE);
attrs.push_back(CKA_OBJECT_ID);
attrs.push_back(CKA_CERTIFICATE_TYPE);
attrs.push_back(CKA_ISSUER);
attrs.push_back(CKA_SERIAL_NUMBER);
attrs.push_back(CKA_AC_ISSUER);
attrs.push_back(CKA_OWNER);
attrs.push_back(CKA_ATTR_TYPES);
attrs.push_back(CKA_TRUSTED);
attrs.push_back(CKA_KEY_TYPE);
attrs.push_back(CKA_SUBJECT);
attrs.push_back(CKA_ID);
attrs.push_back(CKA_SENSITIVE);
attrs.push_back(CKA_ENCRYPT);
attrs.push_back(CKA_DECRYPT);
attrs.push_back(CKA_WRAP);
attrs.push_back(CKA_UNWRAP);
attrs.push_back(CKA_SIGN);
attrs.push_back(CKA_SIGN_RECOVER);
attrs.push_back(CKA_VERIFY);
attrs.push_back(CKA_VERIFY_RECOVER);
attrs.push_back(CKA_DERIVE);
attrs.push_back(CKA_START_DATE);
attrs.push_back(CKA_END_DATE);
attrs.push_back(CKA_MODULUS);
attrs.push_back(CKA_MODULUS_BITS);
attrs.push_back(CKA_PUBLIC_EXPONENT);
attrs.push_back(CKA_PRIVATE_EXPONENT);
attrs.push_back(CKA_PRIME_1);
attrs.push_back(CKA_PRIME_2);
attrs.push_back(CKA_EXPONENT_1);
attrs.push_back(CKA_EXPONENT_2);
attrs.push_back(CKA_COEFFICIENT);
attrs.push_back(CKA_PRIME);
attrs.push_back(CKA_SUBPRIME);
attrs.push_back(CKA_BASE);
attrs.push_back(CKA_PRIME_BITS);
//attrs.push_back(CKA_SUBPRIME_BITS);
attrs.push_back(CKA_VALUE_BITS);
attrs.push_back(CKA_VALUE_LEN);
attrs.push_back(CKA_EXTRACTABLE);
attrs.push_back(CKA_LOCAL);
attrs.push_back(CKA_NEVER_EXTRACTABLE);
attrs.push_back(CKA_ALWAYS_SENSITIVE);
attrs.push_back(CKA_KEY_GEN_MECHANISM);
attrs.push_back(CKA_MODIFIABLE);
attrs.push_back(CKA_ECDSA_PARAMS);
attrs.push_back(CKA_EC_PARAMS);
attrs.push_back(CKA_EC_POINT);
attrs.push_back(CKA_SECONDARY_AUTH);
attrs.push_back(CKA_AUTH_PIN_FLAGS);
attrs.push_back(CKA_HW_FEATURE_TYPE);
attrs.push_back(CKA_RESET_ON_INIT);
attrs.push_back(CKA_HAS_RESET);
attrs.push_back(CKA_VENDOR_DEFINED);
//attrs.push_back(CKA_IBM_OPAQUE);
}
CK_ATTRIBUTE attr;
for (AttributeTypeList::const_iterator it(attrs.begin());
it!=attrs.end(); ++it) {
attr = (CK_ATTRIBUTE){*it, 0, 0};
try {
//! calls @c C_GetAttributeValue
if (_session._slot.library()->C_GetAttributeValue
(_session._session, _object, &attr, 1)
== CKR_ATTRIBUTE_TYPE_INVALID
|| _res == CKR_ATTRIBUTE_SENSITIVE) {
continue; //! Ignores unsupported Attributes.
} else {
check(_res, CRYPTOKI_FN_LOG("C_GetAttributeValue"));
if ((long)attr.ulValueLen>0l) {
attr.pValue = malloc(attr.ulValueLen);
attr.pValue = memset(attr.pValue, 0, attr.ulValueLen);
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
Cryptoki. From the Specs: «In the special
case of an attribute whose value is an
array of attributes, for example
CKA_WRAP_TEMPLATE, where it is passed in
with pValue not NULL, then if the pValue
of elements within the array is NULL_PTR
then the ulValueLen of elements within the
array will be set to the required
length. If the pValue of elements within
the array is not NULL_PTR, then the
ulValueLen element of attributes within
the array must reflect the space that the
corresponding pValue points to, and pValue
is filled in if there is sufficient
room. Therefore it is important to
initialize the contents of a buffer before
calling C_GetAttributeValue to get such an
array value. If any ulValueLen within the
array isn't large enough, it will be set
to -1 and the function will return
CKR_BUFFER_TOO_SMALL, as it does if an
attribute in the pTemplate argument has
ulValueLen too small. Note that any
attribute whose value is an array of
attributes is identifiable by virtue of
the attribute type having the
CKF_ARRAY_ATTRIBUTE bit set.» */
res.insert(std::make_pair(attr.type, Attribute(attr)));
else
free(attr.pValue);
} else if (*it==CKA_MODULUS && attr.ulValueLen==0) {
/*! @bug This is a bug in opensc-pkcs11.so: If
@c CKA_MODULUS has a size of 0 bytes, the
following query to @c CKA_MODULUS_BITS ends
in a segmentation fault.
@note @c CKA_MODULUS @b must immediately be
followed by @c CKA_MODULUS_BITS in the
attribute list, because if the size of @c
CKA_MODULUS is 0 Bytes, the following
attribute query is skipped as a work around
to this bug. */
if (++it==attrs.end()) break;
}
}
} catch (...) {
free(attr.pValue);
throw;
}
}
return res;
}
/*! @todo Not implemented:
@code
bool getobjectsize() {
@ -2660,8 +2673,9 @@ namespace cryptoki {
}
//! @groupadd cryptokitypes
//! @addtogroup cryptokitypes
//@{
/// Append a cryptoki::Attribute to a cryptoki::AttributeList.
inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
const cryptoki::Attribute& attr) {
@ -2669,6 +2683,7 @@ inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
list.push_back(attr);
return list;
}
/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList.
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
const cryptoki::Attribute& attr) {
@ -2677,6 +2692,7 @@ inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
res.push_back(attr);
return res;
}
//@}
#endif

@ -38,9 +38,26 @@
#if __GNUC__ >= 2
//! Macro for internal OpenSSL checks.
/*! You can define a different implementation in your compile call */
#define OPENSSL_CHECK(X) if (!(X)) {ERR_load_ENGINE_strings(); std::stringstream ss; for (unsigned int err(0); err=ERR_get_error();) ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; ss<<"Command "<<#X<<" failed in function "<<__PRETTY_FUNCTION__<<" in file "<<__FILE__<<":"<<__LINE__; throw std::runtime_error(ss.str());}
#define OPENSSL_CHECK(X) \
if (!(X)) { \
ERR_load_ENGINE_strings(); \
std::stringstream ss; \
for (unsigned long err(0); (err=ERR_get_error());) \
ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; \
ss<<"Command "<<#X<<" failed in function "<<__PRETTY_FUNCTION__ \
<<" in file "<<__FILE__<<":"<<__LINE__; \
throw std::runtime_error(ss.str()); \
}
#else
#define OPENSSL_CHECK(X) if (!(X)) {ERR_load_ENGINE_strings(); std::stringstream ss; for (unsigned int err(0); err=ERR_get_error();) ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; ss<<"Command "<<#X<<" failed in file "<<__FILE__<<":"<<__LINE__; throw std::runtime_error(ss.str());}
#define OPENSSL_CHECK(X) \
if (!(X)) { \
ERR_load_ENGINE_strings(); \
std::stringstream ss; \
for (unsigned long err(0); (err=ERR_get_error());) \
ss<<"Error: "<<ERR_error_string(err, 0)<<"; "; \
ss<<"Command "<<#X<<" failed in file "<<__FILE__<<":"<<__LINE__; \
throw std::runtime_error(ss.str()); \
}
#endif
#endif
@ -98,13 +115,13 @@ namespace openssl {
CRYPTOLOG("log");
return 0;
}
virtual int rsaEncrypt() {
virtual std::string rsaEncrypt(const std::string&, int) {
CRYPTOLOG("log");
return 1;
throw std::runtime_error("rsaEncrypt not implemented");
}
virtual int rsaDecrypt() {
virtual std::string rsaDecrypt(const std::string&, int) {
CRYPTOLOG("log");
return 1;
throw std::runtime_error("rsaDecrypt not implemented");
}
virtual std::string rsaSign(const std::string&, unsigned int) {
CRYPTOLOG("log");
@ -166,7 +183,7 @@ namespace openssl {
private:
static int destroy(ENGINE* e) {
static int destroy(ENGINE*) {
CRYPTOLOG("log");
return 1;
}
@ -195,17 +212,38 @@ namespace openssl {
Map::iterator it(_map.find(e));
return it!=_map.end()?it->second->privkey(c, u, d):0;
}
static int rsaEncrypt(int flen,const unsigned char *from,
static int rsaEncrypt(int flen, const unsigned char *from,
unsigned char *to,
RSA *rsa, int padding) {
CRYPTOLOG("log");
Map::iterator it(_map.find(rsa->engine));
return it!=_map.end()?it->second->rsaEncrypt():0;
if (it==_map.end()) return 0;
try {
std::string res(it->second->rsaEncrypt
(std::string((const char*)from, flen),
padding));
std::copy(res.begin(), res.end(), to);
return 1;
} catch (const std::exception& e) {
CRYPTOLOG("ERROR: "<<e.what());
return 0;
}
}
static int rsaDecrypt(int flen, const unsigned char *from, unsigned char *to, RSA *rsa, int padding) {
static int rsaDecrypt(int flen, const unsigned char *from,
unsigned char *to, RSA *rsa, int padding) {
CRYPTOLOG("log");
Map::iterator it(_map.find(rsa->engine));
return it!=_map.end()?it->second->rsaDecrypt():0;
if (it==_map.end()) return 0;
try {
std::string res(it->second->rsaDecrypt
(std::string((const char*)from, flen),
padding));
std::copy(res.begin(), res.end(), to);
return 1;
} catch (const std::exception& e) {
CRYPTOLOG("ERROR: "<<e.what());
return 0;
}
}
static int rsaSign(int type, const unsigned char *from,
unsigned int flen,
@ -221,7 +259,7 @@ namespace openssl {
type));
CRYPTOLOG("to="<<(void*)to<<"; len="<<*tlen);
CRYPTOLOG("siglen="<<res.size());
*tlen = res.size();
*tlen = (unsigned int)res.size();
std::copy(res.begin(), res.end(), to);
return 1;
} catch (const std::exception& e) {

@ -62,10 +62,6 @@
#include <cstdio>
#include <cassert>
namespace pcsc {
std::string version();
}
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API
Support for SSL-connections, engines, keys and certificates. */
//@{
@ -371,11 +367,11 @@ namespace openssl {
//----------------------------------------------------------------------------
class ssl_verification_failed: public ssl_error {
public:
ssl_verification_failed(int num) throw():
ssl_verification_failed(long num) throw():
ssl_error("certificate verification failed: "+reason(num)) {
CRYPTOLOG("**** exception ****");
}
static std::string reason(int num) {
static std::string reason(long num) {
switch (num) {
case X509_V_OK:
return "X509_V_OK: Ok the operation was successful.";
@ -534,7 +530,7 @@ namespace openssl {
CRYPTOLOG("log");
}
BigNum(const std::string& num):
_bn(BN_bin2bn((const unsigned char*)num.data(), num.size(), 0)) {
_bn(BN_bin2bn((const unsigned char*)num.data(), (int)num.size(), 0)) {
CRYPTOLOG("log");
}
~BigNum() {
@ -603,7 +599,7 @@ namespace openssl {
return &_cb;
}
operator std::string() const {
return std::string((char*)_cb, 8);
return std::string((const std::string::value_type*)_cb, 8);
}
private:
DES_cblock _cb;
@ -654,9 +650,11 @@ namespace openssl {
}
//! DES CBC Encryption
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes.
@param key block key
@param ivec vector */
inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) {
CRYPTOLOG("log");
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
@ -669,9 +667,10 @@ namespace openssl {
}
//! DES CBC Encryption with empty vector
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes.
@param key block key */
inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) {
CRYPTOLOG("log");
CBlock8 ivec;
@ -679,9 +678,11 @@ namespace openssl {
}
//! DES CBC Decryption
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes.
@param key block key
@param ivec vector */
inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) {
CRYPTOLOG("log");
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
@ -696,16 +697,20 @@ namespace openssl {
//! DES CBC Decryption with empty vector
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
integral multiple of eight bytes.
@param key block key */
inline std::string desCbcDec(const std::string& txt, const CBlock8& key) {
CRYPTOLOG("log");
CBlock8 ivec;
return desCbcDec(txt, key, ivec);
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes.
@param key1 block key 1
@param key2 block key 2
@param ivec vector */
inline std::string des2edeCbcEnc(std::string txt,
CBlock8 key1, CBlock8 key2,
CBlock8 ivec = CBlock8()) {
@ -720,9 +725,12 @@ namespace openssl {
return res;
}
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes. */
/*! @param txt If the length is not an integral multiple of eight
bytes, it is zero filled. The output is always an
integral multiple of eight bytes.
@param key1 block key 1
@param key2 block key 2
@param ivec vector */
inline std::string des2edeCbcDec(std::string txt,
CBlock8 key1, CBlock8 key2,
CBlock8 ivec = CBlock8()) {
@ -785,7 +793,8 @@ namespace openssl {
//! Initialize from DER encoded cerificate.
X509(const std::string& der): _x509(0) {
CRYPTOLOG("log");
V0_CONST unsigned char* c((unsigned char*)der.begin().operator->());
V0_CONST unsigned char* c
((V0_CONST unsigned char*)der.begin().operator->());
if (!(_x509=d2i_X509(0, &c, der.size())) ||
(const char*)c!=der.begin().operator->()+der.size())
throw x509_decoding_failed(der);
@ -1121,13 +1130,13 @@ namespace openssl {
try {
EVP_PKEY *pkey(0);
::X509 *cert(0);
STACK_OF(X509) *ca(0);
if (!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &ca))
STACK_OF(X509) *cal(0);
if (!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &cal))
throw pkcs12_parsing_failed(filename);
if (pkey) _key = new PrivateKey(pkey);
if (cert) _cert = new X509(cert);
for (int i(sk_num(CV_STACK ca)); i>0; --i)
_ca.push_back(new X509((::X509*)sk_pop(CV_STACK ca)));
for (int i(sk_num(CV_STACK cal)); i>0; --i)
_ca.push_back(new X509((::X509*)sk_pop(CV_STACK cal)));
PKCS12_free(p12);
} catch (...) {
PKCS12_free(p12);
@ -1210,7 +1219,8 @@ namespace openssl {
//! Read PKCS#7 from memory.
PKCS7(const std::string& memory) {
CRYPTOLOG("log");
BIO* mem(BIO_new_mem_buf((void*)memory.data(), memory.size()));
BIO* mem(BIO_new_mem_buf(const_cast<void*>((const void*)memory.data()),
(int)memory.size()));
::PKCS7 *p7(d2i_PKCS7_bio(mem, 0));
BIO_free(mem);
if (!p7) throw pkcs7_parsing_failed();
@ -1327,7 +1337,7 @@ namespace openssl {
TCP& write(const std::string& s) {
CRYPTOLOG("log");
if (!_bio) throw tcp_closed_connection();
unsigned int x(BIO_write(_bio, s.begin().operator->(), s.size()));
unsigned int x(BIO_write(_bio, s.begin().operator->(), (int)s.size()));
if (x<=0)
if (BIO_should_retry(_bio)) return write(s);
else {
@ -1432,7 +1442,7 @@ namespace openssl {
void verify() {
CRYPTOLOG("log");
if (!_ssl) throw ssl_no_connection();
int res(SSL_get_verify_result(_ssl));
long res(SSL_get_verify_result(_ssl));
if (res!=X509_V_OK) throw ssl_verification_failed(res);
}
private:

@ -21,7 +21,7 @@
For special documentations, such as global overviews and
tutorials, please refere to [Pages](pages.html).
@chapter mainoverview Overview of the Components
@section mainoverview Overview of the Components
@dot
digraph g {

@ -77,10 +77,6 @@
}
#endif
namespace pcsc {
std::string version();
}
/*! @defgroup gpcsc C++ Wrapper around pcsc-lite API
This library is a C++ wrapper to the awful pcsc-lite interface.
@ -250,7 +246,7 @@ namespace pcsc {
DWORD dummy(0);
DWORD s;
DWORD len(MAX_ATR_SIZE);
unsigned char a[len];
unsigned char a[MAX_ATR_SIZE];
check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len),
"query smartcard status");
return Status(s, std::string((char*)a, len));
@ -316,15 +312,17 @@ namespace pcsc {
@note Prefer the transmit methods that passes @c cla, @c
ins, @c p1 and @c p2 separate.*/
std::string transmit(std::string in) {
DWORD len(1024); // arbitrary
unsigned char buff[len];
const DWORD bufflen(1024);
DWORD len(bufflen); // arbitrary
unsigned char buff[bufflen];
SCARD_IO_REQUEST rPci;
rPci.dwProtocol = pci()->dwProtocol;
rPci.cbPciLength = sizeof(rPci);
// log only in verbose debuggung; could log pins
CRYPTOLOG_VERBOSE("SCardTransmit: "<<crypto::hex(in));
check(SCardTransmit(_id, &rPci,
(unsigned char*)in.c_str(), in.size(),
(LPCBYTE)in.c_str(),
in.size(),
0, buff, &len),
"smartcard transmit message "+crypto::hex(in));
//CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
@ -342,7 +340,7 @@ namespace pcsc {
CRYPTOLOG("SCardControl: "<<"Command: "<<controlCode);
CRYPTOLOG(" -> "<<crypto::hex(in));
check(SCardControl(_id, controlCode,
(unsigned char*)in.c_str(), in.size(),
(LPCBYTE)in.c_str(), in.size(),
dataBuffer, sizeof(dataBuffer), &len),
"smartcard control message sent");
CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)dataBuffer, len)));
@ -498,6 +496,8 @@ namespace pcsc {
//! Find all readers with a given ATR.
/*! @param atr full or partial ATR to match to the reader's ATR
@param s scope of scanning
@param exceptions whether exeptions should be thrown on error
@returns list of readers that contain @c atr in their ATR */
static Strings getReadersWithAtr(const std::string& atr,
Scope s=USER, bool exceptions=true) {
@ -593,9 +593,9 @@ namespace pcsc {
//! 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;
check(context);
bool check(long s, const std::string& context="") {
_state = s;
return check(context);
}
//! Throws an exception if neccessary.

@ -67,7 +67,7 @@ namespace suisseid {
pukRetries
[URL="\ref cardos::Commands::pukRetries"];
changePin
[URL="\ref cardos::Commands::changePin"];
[URL="\ref cardos::Commands::changePins"];
broken [label="replace card"];
start -> transportState;
@ -201,7 +201,7 @@ namespace suisseid {
}
/// Get the reader, needed for example to lock a transaction
/** @begincode
/** @code
pcsc::Connection::Reader::Transaction lock(card.reader());
[... do some low level stuff ...]
@endcode */
@ -292,7 +292,7 @@ namespace suisseid {
/// @copydoc Card::Card
Post(mrw::Shared<pcsc::Connection::Reader> reader,
const cryptoki::Library& cryptoki):
Card(reader, cryptoki), _minPinLen(0), _maxPinLen(-1) {
Card(reader, cryptoki), _minPinLen(0), _maxPinLen(0) {
}
virtual unsigned int minimalPinLength() {
@ -301,7 +301,7 @@ namespace suisseid {
}
virtual unsigned int maximalPinLength() {
if (_maxPinLen==-1) evaluatePinLengths();
if (_maxPinLen==0) evaluatePinLengths();
return _maxPinLen;
}
@ -411,9 +411,12 @@ namespace suisseid {
// By now, scan only for PostSuisseID; in future use factory pattern
pcsc::Connection::Strings readers
(pcsc::Connection::getReadersWithAtr("4b53776973735369676e"));
CRYPTOLOG("number of pcsc-readers: "<<readers.size());
for (pcsc::Connection::Strings::iterator reader(readers.begin());
reader!=readers.end(); ++reader) {
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
CRYPTOLOG("number of cryptoki-readers for "<<*reader
<<": "<<slots.size());
if (slots.size()==1)
res.push_back(dynamic_cast<Card*>
(new Post(pcsc::Connection::reader(*reader),
@ -452,7 +455,8 @@ namespace suisseid {
/// @name Slots
//@{
/// Structure to provide old and new pin
struct PinPukChange {
std::string oldpin;
std::string newpin;
@ -460,49 +464,65 @@ namespace suisseid {
return oldpin.size() && newpin.size();
}
};
/// Pin change required - get pins from user
virtual PinPukChange pinChange() {
CRYPTOLOG("log");
return PinPukChange();
}
/// Transport pin change required - get pins from user
virtual PinPukChange pinChangeTransportPin() {
CRYPTOLOG("log");
return pinChange();
}
/// Puk change required - get pins from user
virtual PinPukChange pinChangePuk() {
CRYPTOLOG("log");
return pinChange();
}
/// Transport pin locked - you may show an error message
virtual void transportPinLocked() {
CRYPTOLOG("log");
}
/// PKCS#15 pin locked - you may show an error message
virtual void pkcs15PinLocked() {
CRYPTOLOG("log");
}
/// SigG pin locked - you may show an error message
virtual void sigGPinLocked() {
CRYPTOLOG("log");
}
/// Puk locked - you may show an error message
virtual void pukLocked() {
CRYPTOLOG("log");
}
/// Certificates will expire soon - you may show an error message
virtual void certsExpireSoon() {
CRYPTOLOG("log");
}
/// Certificates are expired soon - you may show an error message
virtual void certsExpired() {
CRYPTOLOG("log");
}
/// Certificates have been revoked - you may show an error message
virtual void certsRevoked() {
CRYPTOLOG("log");
}
/// install certificates on the card
/** @param bool whether to force reinstallation of existin certificates
/** @param reinstall whether to force reinstallation of existing
certificates
@return @c true on success */
virtual bool installCerts(bool = true) {
virtual bool installCerts(bool reinstall = true) {
CRYPTOLOG("log");
return false;
}

Loading…
Cancel
Save