fixed tons of warnings; refs #28
This commit is contained in:
+95
-80
@@ -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 file’s 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 file’s 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 MF’s AC ALLOCATE is granted.
|
||||
@pre The command can only be executed, if the right
|
||||
referenced by the MF’s 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 file’s 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 file’s 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>xxh…xxh</td><td>80h 88h Mode 00h</td><td>xxh</td>
|
||||
<td>22h…22h</td><td>xxh</td><td>xxh…xxh</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>xxh…xxh</td>
|
||||
<td>80h 88h Mode 00h</td>
|
||||
<td>xxh</td>
|
||||
<td>22h…22h</td>
|
||||
<td>xxh</td>
|
||||
<td>xxh…xxh</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 DF’s 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
|
||||
DF’s 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 {
|
||||
|
||||
+8
-3
@@ -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;
|
||||
|
||||
+14
-9
@@ -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
|
||||
|
||||
+276
-260
@@ -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
|
||||
<cryptoki.hxx></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
|
||||
<cryptoki.hxx></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*)¶m[0]:0, param.size()
|
||||
type, param.size()?const_cast<CK_VOID_PTR>((const void*)¶m[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
|
||||
|
||||
+50
-12
@@ -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) {
|
||||
|
||||
+42
-32
@@ -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:
|
||||
|
||||
+1
-1
@@ -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 {
|
||||
|
||||
+12
-12
@@ -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.
|
||||
|
||||
+28
-8
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user