fixed tons of warnings; refs #28
This commit is contained in:
@@ -104,9 +104,8 @@ class Commands: public cardos::Commands {
|
|||||||
|
|
||||||
void selectReader() {
|
void selectReader() {
|
||||||
listReader();
|
listReader();
|
||||||
if (_readers.size()<0) return;
|
pcsc::Connection::Strings::size_type num(0);
|
||||||
int num(-1);
|
if (std::cin>>num && num<_readers.size()) {
|
||||||
if (std::cin>>num && num>=0 && num<_readers.size()) {
|
|
||||||
_reader = pcsc::Connection::reader(_readers[num]);
|
_reader = pcsc::Connection::reader(_readers[num]);
|
||||||
std::cout<<"Active Reader: "<<_readers[num]<<std::endl;
|
std::cout<<"Active Reader: "<<_readers[num]<<std::endl;
|
||||||
} else throw std::runtime_error("no valid reader selected");
|
} else throw std::runtime_error("no valid reader selected");
|
||||||
|
|||||||
@@ -21,8 +21,6 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
pcsc::Connection::Strings readers;
|
|
||||||
|
|
||||||
void list() {
|
void list() {
|
||||||
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
||||||
std::cout<<"Found "<<readers.size()<<" readers"
|
std::cout<<"Found "<<readers.size()<<" readers"
|
||||||
@@ -34,7 +32,7 @@ void list() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) try {
|
int main(int argc, char** argv) try {
|
||||||
int reader(0);
|
unsigned int reader(0);
|
||||||
std::string pin;
|
std::string pin;
|
||||||
std::string path("3f00");
|
std::string path("3f00");
|
||||||
std::string id("8888");
|
std::string id("8888");
|
||||||
@@ -62,7 +60,7 @@ int main(int argc, char** argv) try {
|
|||||||
<<mrw::args::param(data, "text"))
|
<<mrw::args::param(data, "text"))
|
||||||
);
|
);
|
||||||
pcsc::Connection::Strings readers(pcsc::Connection::scan());
|
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;
|
std::cerr<<"reader not found: "<<reader<<std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,14 +75,14 @@ int main(int argc, char const*const*const argv) try {
|
|||||||
cryptoki::Session session(*it);
|
cryptoki::Session session(*it);
|
||||||
cryptoki::ObjectList objs(session.find());
|
cryptoki::ObjectList objs(session.find());
|
||||||
std::cout<<"Objects Found: "<<objs.size()<<std::endl;
|
std::cout<<"Objects Found: "<<objs.size()<<std::endl;
|
||||||
for (cryptoki::ObjectList::iterator it(objs.begin());
|
for (cryptoki::ObjectList::iterator it2(objs.begin());
|
||||||
it!=objs.end(); ++it) {
|
it2!=objs.end(); ++it2) {
|
||||||
std::cout<<"-------------------- Object -----------------"<<std::endl;
|
std::cout<<"-------------------- Object -----------------"<<std::endl;
|
||||||
cryptoki::AttributeMap attrs(it->attributes());
|
cryptoki::AttributeMap attrs(it2->attributes());
|
||||||
for (cryptoki::AttributeMap::iterator it(attrs.begin());
|
for (cryptoki::AttributeMap::iterator it3(attrs.begin());
|
||||||
it!=attrs.end(); ++it) {
|
it3!=attrs.end(); ++it3) {
|
||||||
std::cout<<" - attribute: "<<it->second.name()<<" = "<<std::endl
|
std::cout<<" - attribute: "<<it3->second.name()<<" = "<<std::endl
|
||||||
<<crypto::readable(it->second.value, 15, 5)<<std::endl;
|
<<crypto::readable(it3->second.value, 15, 5)<<std::endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::cout<<"**** Success"<<std::endl;
|
std::cout<<"**** Success"<<std::endl;
|
||||||
|
|||||||
@@ -71,17 +71,18 @@ int main(int argc, char** argv) try {
|
|||||||
cryptoki::ObjectList certs
|
cryptoki::ObjectList certs
|
||||||
(session.find(cryptoki::Attribute(CKA_CLASS)
|
(session.find(cryptoki::Attribute(CKA_CLASS)
|
||||||
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
|
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
|
||||||
for (cryptoki::ObjectList::iterator c(certs.begin()); c!=certs.end(); ++c) {
|
for (cryptoki::ObjectList::iterator it(certs.begin());
|
||||||
std::string label(c->attribute(CKA_LABEL).value);
|
it!=certs.end(); ++it) {
|
||||||
|
std::string label(it->attribute(CKA_LABEL).value);
|
||||||
if (cert.size()&&cert!=label) continue;
|
if (cert.size()&&cert!=label) continue;
|
||||||
cryptoki::Attribute id(c->attribute(CKA_ID));
|
cryptoki::Attribute id(it->attribute(CKA_ID));
|
||||||
cryptoki::ObjectList keys
|
cryptoki::ObjectList keys
|
||||||
(session.find(cryptoki::Attribute(CKA_CLASS)
|
(session.find(cryptoki::Attribute(CKA_CLASS)
|
||||||
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY),
|
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY),
|
||||||
id));
|
id));
|
||||||
if (!keys.size()) continue;
|
if (!keys.size()) continue;
|
||||||
std::cout<<"Found Certificate: "
|
std::cout<<"Found Certificate: "
|
||||||
<<c->attribute(CKA_LABEL).value<<std::endl;
|
<<it->attribute(CKA_LABEL).value<<std::endl;
|
||||||
if (!cert.size()) continue;
|
if (!cert.size()) continue;
|
||||||
std::cout<<"Pin: ";
|
std::cout<<"Pin: ";
|
||||||
std::string pin;
|
std::string pin;
|
||||||
@@ -98,7 +99,7 @@ int main(int argc, char** argv) try {
|
|||||||
#ifndef MRW__OLD_PRE11_COMPILER
|
#ifndef MRW__OLD_PRE11_COMPILER
|
||||||
auto start = std::chrono::system_clock::now();
|
auto start = std::chrono::system_clock::now();
|
||||||
#endif
|
#endif
|
||||||
for (int i(0); i<r; ++i)
|
for (unsigned int i(0); i<r; ++i)
|
||||||
std::cout<<"Text:"<<std::endl
|
std::cout<<"Text:"<<std::endl
|
||||||
<<crypto::readable(txt)<<std::endl
|
<<crypto::readable(txt)<<std::endl
|
||||||
<<"Signature:"<<std::endl
|
<<"Signature:"<<std::endl
|
||||||
|
|||||||
+95
-80
@@ -111,7 +111,7 @@ namespace cardos {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class array_range: public exception {
|
class array_range: public exception {
|
||||||
public:
|
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)
|
exception("array index out of range: "+mrw::string(i)
|
||||||
+"; length: "+mrw::string(j)) {
|
+"; length: "+mrw::string(j)) {
|
||||||
}
|
}
|
||||||
@@ -198,16 +198,16 @@ namespace cardos {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
BerValue(unsigned char tag, const std::string& value):
|
BerValue(unsigned char t, const std::string& v):
|
||||||
_tag(tag), _value(value) {
|
_tag(t), _value(v) {
|
||||||
if (isContainer())
|
if (isContainer())
|
||||||
while (_value.size()) _sequence.push_back(BerValue(_value));
|
while (_value.size()) _sequence.push_back(BerValue(_value));
|
||||||
}
|
}
|
||||||
|
|
||||||
BerValue(unsigned char tag, const std::vector<BerValue>& values):
|
BerValue(unsigned char t, const std::vector<BerValue>& vs):
|
||||||
_tag(tag), _sequence(values) {
|
_tag(t), _sequence(vs) {
|
||||||
if (!isContainer())
|
if (!isContainer())
|
||||||
throw runtime_error("BER tag 0x"+crypto::binToHex(tag)
|
throw runtime_error("BER tag 0x"+crypto::binToHex(_tag)
|
||||||
+" is not a container");
|
+" is not a container");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +227,7 @@ namespace cardos {
|
|||||||
return tagPC()==CONSTRUCTED;
|
return tagPC()==CONSTRUCTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int size() {
|
std::vector<BerValue>::size_type size() {
|
||||||
return _sequence.size();
|
return _sequence.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,7 +235,7 @@ namespace cardos {
|
|||||||
return _tag;
|
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());
|
if (i>=_sequence.size()) throw array_range(i, _sequence.size());
|
||||||
return _sequence[i];
|
return _sequence[i];
|
||||||
}
|
}
|
||||||
@@ -424,13 +424,13 @@ namespace cardos {
|
|||||||
Commands() {}
|
Commands() {}
|
||||||
|
|
||||||
/// Initialize with given smart card reader.
|
/// Initialize with given smart card reader.
|
||||||
Commands(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader):
|
Commands(pcsc::shared_ptr<pcsc::Connection::Reader>::t r):
|
||||||
_reader(reader) {
|
_reader(r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set smart card reader.
|
/// Set smart card reader.
|
||||||
void reader(pcsc::shared_ptr<pcsc::Connection::Reader>::t reader) {
|
void reader(pcsc::shared_ptr<pcsc::Connection::Reader>::t r) {
|
||||||
_reader = reader;
|
_reader = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
@@ -446,10 +446,10 @@ namespace cardos {
|
|||||||
will not return an error, if the current file is already
|
will not return an error, if the current file is already
|
||||||
active.
|
active.
|
||||||
|
|
||||||
@prereq The command can only be executed, if the right
|
@pre The command can only be executed, if the right
|
||||||
referenced by the file’s AC ACTIVATE is granted in
|
referenced by the file’s AC ACTIVATE is granted in the
|
||||||
the security status of the current DF. The command
|
security status of the current DF. The command cannot
|
||||||
cannot be applied to CODE files. */
|
be applied to CODE files. */
|
||||||
void activateFile() {
|
void activateFile() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
check(send(0x00, 0x44, 0x00, 0x00));
|
check(send(0x00, 0x44, 0x00, 0x00));
|
||||||
@@ -480,10 +480,8 @@ namespace cardos {
|
|||||||
|
|
||||||
<table>
|
<table>
|
||||||
<caption>Bytes P1-P2</caption>
|
<caption>Bytes P1-P2</caption>
|
||||||
<thead>
|
|
||||||
<tr><td colspan="2">P1 (MODE)</td><td>P2</td><td>Meaning</td></tr>
|
<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>
|
<tr><td>Bit 7</td><td>Bits 6 – 0</td><td></td><td></td></tr>
|
||||||
</thead>
|
|
||||||
<tr>
|
<tr>
|
||||||
<td>1</td><td>HI value</td><td>LO value</td>
|
<td>1</td><td>HI value</td><td>LO value</td>
|
||||||
<td>Allocate buffer with size HI-LO</td>
|
<td>Allocate buffer with size HI-LO</td>
|
||||||
@@ -493,8 +491,8 @@ namespace cardos {
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@prereq The command can only be executed, if the right
|
@pre The command can only be executed, if the right
|
||||||
referenced by the MF’s AC ALLOCATE is granted.
|
referenced by the MF’s AC ALLOCATE is granted.
|
||||||
|
|
||||||
@returns 1 byte: ID of allocated buffer
|
@returns 1 byte: ID of allocated buffer
|
||||||
|
|
||||||
@@ -502,7 +500,8 @@ namespace cardos {
|
|||||||
std::string allocateTransactionBuffer(unsigned short size) {
|
std::string allocateTransactionBuffer(unsigned short size) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
if (size>0x7FFF) throw runtime_error("requested buffer too large");
|
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
|
//! Free transaction buffer
|
||||||
@@ -553,9 +552,9 @@ namespace cardos {
|
|||||||
the record consists of one byte. The tag byte is not
|
the record consists of one byte. The tag byte is not
|
||||||
interpreted by APPEND RECORD.
|
interpreted by APPEND RECORD.
|
||||||
|
|
||||||
@prereq The command can only be executed, if the right
|
@pre The command can only be executed, if the right
|
||||||
referenced by the file’s AC APPEND is granted in the
|
referenced by the file’s AC APPEND is granted in the
|
||||||
security status of the current DF. */
|
security status of the current DF. */
|
||||||
void appendRecord(unsigned char efId, std::string data) {
|
void appendRecord(unsigned char efId, std::string data) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
check(send(0x00, 0xE2, 0x00, efId, data));
|
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 number of loaded Packages (s. GET DATA command, mode 88h)
|
||||||
- the system internal parameters (9 bytes consisting 22h) and
|
- the system internal parameters (9 bytes consisting 22h) and
|
||||||
- optionally, the Chip Unique Identification Number
|
- 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).
|
Bytes 11-16).
|
||||||
|
|
||||||
The commands supports 2 modes indicated by the parameter P1:
|
The commands supports 2 modes indicated by the parameter P1:
|
||||||
@@ -594,28 +593,37 @@ namespace cardos {
|
|||||||
chapter 2.4.2.4
|
chapter 2.4.2.4
|
||||||
|
|
||||||
<table>
|
<table>
|
||||||
<caption>Format of the input for hash value calculation</caption>
|
<caption>Format of the input for hash value calculation</caption>
|
||||||
<thead><tr>
|
<tr>
|
||||||
<th>System_Challenge</th>
|
<th>System_Challenge</th>
|
||||||
<th>Command Header<br/>CLA INS P1 P2</th>
|
<th>Command Header<br/>CLA INS P1 P2</th>
|
||||||
<th>Global Life Cycle Phase</th>
|
<th>Global Life Cycle Phase</th>
|
||||||
<th>Internal Parameters</th>
|
<th>Internal Parameters</th>
|
||||||
<th>Number of loaded Packages</th>
|
<th>Number of loaded Packages</th>
|
||||||
<th>Chip Unique Identification Number (opt.)</th>
|
<th>Chip Unique Identification Number (opt.)</th>
|
||||||
</tr></thead>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>xxh…xxh</td><td>80h 88h Mode 00h</td><td>xxh</td>
|
<td>xxh…xxh</td>
|
||||||
<td>22h…22h</td><td>xxh</td><td>xxh…xxh</td>
|
<td>80h 88h Mode 00h</td>
|
||||||
</tr><tr>
|
<td>xxh</td>
|
||||||
<td>n bytes</td><td>4 bytes</td><td>1 byte</td><td>9 bytes</td>
|
<td>22h…22h</td>
|
||||||
<td>1 byte</td><td>6 bytes/empty</td>
|
<td>xxh</td>
|
||||||
</tr>
|
<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>
|
</table>
|
||||||
|
|
||||||
@prereq The System_Challenge provided by the application
|
@pre The System_Challenge provided by the application must
|
||||||
must be greater or equal to 16 bytes. Since the
|
be greater or equal to 16 bytes. Since the command
|
||||||
command does not support chaining, the length of the
|
does not support chaining, the length of the
|
||||||
System_Challenge is limited by the IO buffer size.
|
System_Challenge is limited by the IO buffer size.
|
||||||
|
|
||||||
@note The application must use the corresponding RSA2 public
|
@note The application must use the corresponding RSA2 public
|
||||||
key to verify the Digital Signature received from the
|
key to verify the Digital Signature received from the
|
||||||
@@ -653,7 +661,7 @@ namespace cardos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! Creates a file (only EF or DF)
|
//! 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");
|
CRYPTOLOG("log");
|
||||||
// pcsc::Connection::Reader::Transaction lock(_reader);
|
// pcsc::Connection::Reader::Transaction lock(_reader);
|
||||||
// if (path.size()) select(path);
|
// if (path.size()) select(path);
|
||||||
@@ -818,8 +826,8 @@ namespace cardos {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
std::string data;
|
std::string data;
|
||||||
data.resize(2);
|
data.resize(2);
|
||||||
data[0] = size>>8;
|
data[0] = char((unsigned char)(size>>8));
|
||||||
data[1] = size&0xff;
|
data[1] = char((unsigned char)(size&0xff));
|
||||||
return check(send(0x80, 0x32, 0x00, efId, data)); // 0x08 or 0x80?
|
return check(send(0x80, 0x32, 0x00, efId, data)); // 0x08 or 0x80?
|
||||||
// old code was 0x80, manual says 0x08 (manual exactly says: "8xh")
|
// 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
|
can also be undone (without reset) with another PHASE
|
||||||
CONTROL command.
|
CONTROL command.
|
||||||
|
|
||||||
@prereq Changing from ADMINISTRATION to OPERATIONAL is not
|
@pre Changing from ADMINISTRATION to OPERATIONAL is not
|
||||||
protected. Changing from OPERATIONAL to
|
protected. Changing from OPERATIONAL to ADMINISTRATION
|
||||||
ADMINISTRATION is controlled by the right referenced
|
is controlled by the right referenced by the current
|
||||||
by the current DF’s AC LCYCLE.
|
DF’s AC LCYCLE.
|
||||||
|
|
||||||
@prereq The command can be executed in the life cycle phases
|
@pre The command can be executed in the life cycle phases
|
||||||
ADMINISTRATION and OPERATIONAL. */
|
ADMINISTRATION and OPERATIONAL. */
|
||||||
void phaseControl() {
|
void phaseControl() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
check(send(0x80, 0x10, 0x00, 0x00));
|
check(send(0x80, 0x10, 0x00, 0x00));
|
||||||
@@ -930,7 +938,8 @@ namespace cardos {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
pcsc::Connection::Reader::Transaction lock(_reader);
|
pcsc::Connection::Reader::Transaction lock(_reader);
|
||||||
if (path.size()) select(path);
|
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 {
|
enum ReadRecordMode {
|
||||||
@@ -950,7 +959,8 @@ namespace cardos {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
pcsc::Connection::Reader::Transaction lock(_reader);
|
pcsc::Connection::Reader::Transaction lock(_reader);
|
||||||
if (path.size()) select(path);
|
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
|
/// Read all records from a record oriented file
|
||||||
@@ -1042,7 +1052,8 @@ namespace cardos {
|
|||||||
//! Updates a BINARY file
|
//! Updates a BINARY file
|
||||||
void updateBinary(std::string data, unsigned short offset=0) {
|
void updateBinary(std::string data, unsigned short offset=0) {
|
||||||
CRYPTOLOG("log");
|
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.
|
//! Overwrites an existing record.
|
||||||
@@ -1051,7 +1062,8 @@ namespace cardos {
|
|||||||
unsigned char sfi = 0,
|
unsigned char sfi = 0,
|
||||||
ReadRecordMode mode = ABSOLUTE_RECORD) {
|
ReadRecordMode mode = ABSOLUTE_RECORD) {
|
||||||
CRYPTOLOG("log");
|
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 {
|
enum VerifyMode {
|
||||||
@@ -1063,14 +1075,14 @@ namespace cardos {
|
|||||||
void verify(std::string pin, unsigned char id,
|
void verify(std::string pin, unsigned char id,
|
||||||
VerifyMode mode = SEARCH_FROM_DF) {
|
VerifyMode mode = SEARCH_FROM_DF) {
|
||||||
CRYPTOLOG("log");
|
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)
|
//! Performs a PIN test (CHV test)
|
||||||
/*! @return number of remaining PIN retries or -1 if PIN is locked */
|
/*! @return number of remaining PIN retries or -1 if PIN is locked */
|
||||||
int verify(unsigned char id, VerifyMode mode = SEARCH_FROM_DF) {
|
int verify(unsigned char id, VerifyMode mode = SEARCH_FROM_DF) {
|
||||||
CRYPTOLOG("log");
|
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 value((((unsigned int)(unsigned char)res[0])*256)
|
||||||
+((unsigned int)(unsigned char)res[1]));
|
+((unsigned int)(unsigned char)res[1]));
|
||||||
if ((value&0x63C0)==0x63C0) return value&0x0F;
|
if ((value&0x63C0)==0x63C0) return value&0x0F;
|
||||||
@@ -1511,7 +1523,9 @@ namespace cardos {
|
|||||||
return result;
|
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");
|
if (!_reader) throw runtime_error("no reader selected");
|
||||||
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
|
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
|
||||||
<<" ins="<<crypto::binToHex(ins)
|
<<" ins="<<crypto::binToHex(ins)
|
||||||
@@ -1521,7 +1535,8 @@ namespace cardos {
|
|||||||
return logResult(_reader->transmit(cla, ins, p1, p2, lc));
|
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");
|
if (!_reader) throw runtime_error("no reader selected");
|
||||||
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
|
CARDOS_LOG("APDU: cla="<<crypto::binToHex(cla)
|
||||||
<<" ins="<<crypto::binToHex(ins)
|
<<" ins="<<crypto::binToHex(ins)
|
||||||
@@ -1545,7 +1560,7 @@ namespace cardos {
|
|||||||
typedef pcsc::shared_ptr<Object>::t Child;
|
typedef pcsc::shared_ptr<Object>::t Child;
|
||||||
typedef std::vector<Child> Children;
|
typedef std::vector<Child> Children;
|
||||||
public:
|
public:
|
||||||
Object(const std::string& path): _path(path) {}
|
Object(const std::string& p): _path(p) {}
|
||||||
virtual ~Object() {}
|
virtual ~Object() {}
|
||||||
virtual const std::string& path() const {
|
virtual const std::string& path() const {
|
||||||
return _path;
|
return _path;
|
||||||
@@ -1618,11 +1633,11 @@ namespace cardos {
|
|||||||
/// Represents a File on a Smart Card
|
/// Represents a File on a Smart Card
|
||||||
class File: public Object {
|
class File: public Object {
|
||||||
public:
|
public:
|
||||||
File(Commands& cmd, const std::string& path, const std::string& file):
|
File(Commands& cmd, const std::string& p, const std::string& file):
|
||||||
Object(path), _file(file) {
|
Object(p), _file(file) {
|
||||||
CRYPTOLOG("new file "<<file<<" at "<<path);
|
CRYPTOLOG("new file "<<file<<" at "<<p);
|
||||||
try {
|
try {
|
||||||
_content = cmd.readBinary(path+file);
|
_content = cmd.readBinary(p+file);
|
||||||
try {
|
try {
|
||||||
_contentInfo = cardos::BerValues(_content).print();
|
_contentInfo = cardos::BerValues(_content).print();
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
@@ -1631,9 +1646,9 @@ namespace cardos {
|
|||||||
_contentInfo = x.what();
|
_contentInfo = x.what();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
File(const std::string& path, const std::string& file):
|
File(const std::string& p, const std::string& file):
|
||||||
Object(path), _file(file) {
|
Object(p), _file(file) {
|
||||||
CRYPTOLOG("new file "<<file<<" at "<<path);
|
CRYPTOLOG("new file "<<file<<" at "<<p);
|
||||||
}
|
}
|
||||||
std::string name() const {
|
std::string name() const {
|
||||||
return _file;
|
return _file;
|
||||||
@@ -1660,9 +1675,9 @@ namespace cardos {
|
|||||||
/// Represents a Link on a Smart Card
|
/// Represents a Link on a Smart Card
|
||||||
class Link: public File {
|
class Link: public File {
|
||||||
public:
|
public:
|
||||||
Link(Commands& cmd, const std::string& path, const std::string& file):
|
Link(Commands& cmd, const std::string& p, const std::string& file):
|
||||||
File(cmd, path, file) {
|
File(cmd, p, file) {
|
||||||
CRYPTOLOG("new link "<<file<<" at "<<path);
|
CRYPTOLOG("new link "<<file<<" at "<<p);
|
||||||
}
|
}
|
||||||
std::string type() const {
|
std::string type() const {
|
||||||
return "Link";
|
return "Link";
|
||||||
@@ -1673,11 +1688,11 @@ namespace cardos {
|
|||||||
/// Represents a Counter on a Smart Card
|
/// Represents a Counter on a Smart Card
|
||||||
class Counter: public File {
|
class Counter: public File {
|
||||||
public:
|
public:
|
||||||
Counter(Commands& cmd, const std::string& path, const std::string& file):
|
Counter(Commands& cmd, const std::string& p, const std::string& file):
|
||||||
File(path, file) {
|
File(p, file) {
|
||||||
CRYPTOLOG("new counter "<<file<<" at "<<path);
|
CRYPTOLOG("new counter "<<file<<" at "<<p);
|
||||||
try {
|
try {
|
||||||
_content = cmd.readRecord(path+file);
|
_content = cmd.readRecord(p+file);
|
||||||
std::stringstream s;
|
std::stringstream s;
|
||||||
s<<crypto::ulongFromBinary(_content);
|
s<<crypto::ulongFromBinary(_content);
|
||||||
_contentInfo = s.str();
|
_contentInfo = s.str();
|
||||||
@@ -1694,8 +1709,8 @@ namespace cardos {
|
|||||||
/// Represents a Directory on a Smart Card
|
/// Represents a Directory on a Smart Card
|
||||||
class Dir: public Object {
|
class Dir: public Object {
|
||||||
public:
|
public:
|
||||||
Dir(Commands& cmd, const std::string& path): Object(path) {
|
Dir(Commands& cmd, const std::string& p): Object(p) {
|
||||||
CRYPTOLOG("new directory path="<<path);
|
CRYPTOLOG("new directory path="<<p);
|
||||||
setup(cmd);
|
setup(cmd);
|
||||||
}
|
}
|
||||||
std::string name() const {
|
std::string name() const {
|
||||||
|
|||||||
+8
-3
@@ -80,6 +80,11 @@
|
|||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace pcsc {
|
||||||
|
/// Get library version identification
|
||||||
|
std::string version();
|
||||||
|
}
|
||||||
|
|
||||||
//! @ref gcrypto @copydoc gcrypto
|
//! @ref gcrypto @copydoc gcrypto
|
||||||
namespace crypto {
|
namespace crypto {
|
||||||
|
|
||||||
@@ -165,9 +170,9 @@ namespace crypto {
|
|||||||
<<s.find_first_not_of(HEX))).str());
|
<<s.find_first_not_of(HEX))).str());
|
||||||
std::string res;
|
std::string res;
|
||||||
for (std::string::const_iterator it(s.begin()); it!=s.end(); ++it) {
|
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);
|
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;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -176,7 +181,7 @@ namespace crypto {
|
|||||||
inline std::string toBinary(unsigned long data, int bytes=2) {
|
inline std::string toBinary(unsigned long data, int bytes=2) {
|
||||||
std::string res(0, bytes);
|
std::string res(0, bytes);
|
||||||
for (int i(0); i<bytes; ++i) {
|
for (int i(0); i<bytes; ++i) {
|
||||||
res[i] = data&0xff;
|
res[i] = std::string::value_type(data&0xff);
|
||||||
data>>=8;
|
data>>=8;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
+14
-9
@@ -33,33 +33,38 @@ namespace cryptoki {
|
|||||||
if (!_lib) throw exception("open of library failed: "+library);
|
if (!_lib) throw exception("open of library failed: "+library);
|
||||||
CRYPTOLOG("loaded: "<<library);
|
CRYPTOLOG("loaded: "<<library);
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
CK_C_GetFunctionList fn
|
/// @bug in dlsym: returns void* but should return void(*)()
|
||||||
((CK_C_GetFunctionList)dlsym(_lib, "C_GetFunctionList"));
|
CK_C_GetFunctionList fnl
|
||||||
|
(reinterpret_cast<CK_C_GetFunctionList>
|
||||||
|
(reinterpret_cast<long long>
|
||||||
|
(dlsym(_lib, "C_GetFunctionList"))));
|
||||||
#else
|
#else
|
||||||
CK_C_GetFunctionList fn
|
CK_C_GetFunctionList fnl
|
||||||
((CK_C_GetFunctionList)GetProcAddress(_lib, "C_GetFunctionList"));
|
((CK_C_GetFunctionList)GetProcAddress(_lib, "C_GetFunctionList"));
|
||||||
#endif
|
#endif
|
||||||
if (!fn)
|
if (!fnl)
|
||||||
throw exception("required library symbol C_GetFunctionList not found in "
|
throw exception("required library symbol C_GetFunctionList not found in "
|
||||||
+library);
|
+library);
|
||||||
CRYPTOLOG("Got C_GetFunctionList, now call it");
|
CRYPTOLOG("Got C_GetFunctionList, now call it");
|
||||||
//! calls @c C_GetFunctionList
|
//! 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) {
|
bool Library::Init::check(CK_RV result, const std::string& context) {
|
||||||
_res = result;
|
_res = result;
|
||||||
if (_exc && !*this)
|
if (_exc && !*this) {
|
||||||
if (context.size())
|
if (context.size()) {
|
||||||
if (_res==CKR_PIN_INCORRECT)
|
if (_res==CKR_PIN_INCORRECT)
|
||||||
throw wrong_pin(context+": "+error());
|
throw wrong_pin(context+": "+error());
|
||||||
else
|
else
|
||||||
throw access_error(context+": "+error());
|
throw access_error(context+": "+error());
|
||||||
else
|
} else {
|
||||||
if (_res==CKR_PIN_INCORRECT)
|
if (_res==CKR_PIN_INCORRECT)
|
||||||
throw wrong_pin(error());
|
throw wrong_pin(error());
|
||||||
else
|
else
|
||||||
throw access_error(error());
|
throw access_error(error());
|
||||||
|
}
|
||||||
|
}
|
||||||
return _res==CKR_OK;
|
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_SECONDARY_AUTH).from<CK_BBOOL>(FALSE));
|
||||||
attrs.push_back(Attribute(CKA_DECRYPT) // Required by Doujak/Inverardi
|
attrs.push_back(Attribute(CKA_DECRYPT) // Required by Doujak/Inverardi
|
||||||
.from<CK_BBOOL>(usage&(X509v3_KU_DATA_ENCIPHERMENT
|
.from<CK_BBOOL>(usage&(X509v3_KU_DATA_ENCIPHERMENT
|
||||||
|usage&X509v3_KU_KEY_ENCIPHERMENT)
|
|(usage&X509v3_KU_KEY_ENCIPHERMENT))
|
||||||
?TRUE:FALSE)); // instead of CKA_UNWRAP
|
?TRUE:FALSE)); // instead of CKA_UNWRAP
|
||||||
attrs.push_back(Attribute(CKA_SIGN)
|
attrs.push_back(Attribute(CKA_SIGN)
|
||||||
.from<CK_BBOOL>(usage&(X509v3_KU_DIGITAL_SIGNATURE
|
.from<CK_BBOOL>(usage&(X509v3_KU_DIGITAL_SIGNATURE
|
||||||
|
|||||||
+276
-260
@@ -54,7 +54,7 @@
|
|||||||
#if __GNUC__ >= 2
|
#if __GNUC__ >= 2
|
||||||
//! Cryptoki Error Message Formatting
|
//! Cryptoki Error Message Formatting
|
||||||
/*! If you want to change cryptoki error formatting, just
|
/*! 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>.
|
<cryptoki.hxx></code>.
|
||||||
#return std::String */
|
#return std::String */
|
||||||
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
|
#define CRYPTOKI_FN_LOG(X) (std::string(X " failed in ") \
|
||||||
@@ -64,19 +64,15 @@
|
|||||||
#define CRYPTOKI_QUOTE2(X) #X
|
#define CRYPTOKI_QUOTE2(X) #X
|
||||||
//! Cryptoki Error Message Formatting
|
//! Cryptoki Error Message Formatting
|
||||||
/*! If you want to change cryptoki error formatting, just
|
/*! 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>.
|
<cryptoki.hxx></code>.
|
||||||
#return std::String */
|
@return string */
|
||||||
#define CRYPTOKI_FN_LOG(X) X " failed in \
|
#define CRYPTOKI_FN_LOG(X) X " failed in \
|
||||||
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__)
|
" __FILE__ ":" CRYPTOKI_QUOTE(__LINE__)
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
namespace pcsc {
|
|
||||||
std::string version();
|
|
||||||
}
|
|
||||||
|
|
||||||
//! @ref gcryptoki @copydoc gcryptoki
|
//! @ref gcryptoki @copydoc gcryptoki
|
||||||
namespace cryptoki {
|
namespace cryptoki {
|
||||||
|
|
||||||
@@ -261,7 +257,7 @@ namespace cryptoki {
|
|||||||
std::string res(indent, ' ');
|
std::string res(indent, ' ');
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CKA_CLASS:
|
case CKA_CLASS:
|
||||||
switch (*((CK_OBJECT_CLASS*)&value[0])) {
|
switch (*((const CK_OBJECT_CLASS*)&value[0])) {
|
||||||
case CKO_DATA: return res+"DATA";
|
case CKO_DATA: return res+"DATA";
|
||||||
case CKO_CERTIFICATE: return res+"CERTIFICATE";
|
case CKO_CERTIFICATE: return res+"CERTIFICATE";
|
||||||
case CKO_PUBLIC_KEY: return res+"PUBLIC_KEY";
|
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
|
/** To use this method, you must know what type the attribute
|
||||||
represents. */
|
represents. */
|
||||||
template<typename TYPE> Attribute& from(const TYPE& v) {
|
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;
|
return *this;
|
||||||
}
|
}
|
||||||
/// Convert to a given type.
|
/// Convert to a given type.
|
||||||
@@ -1107,9 +1103,9 @@ namespace cryptoki {
|
|||||||
shared library. Normally you need only one instance.
|
shared library. Normally you need only one instance.
|
||||||
|
|
||||||
@param library name of the shared library that supports pkcs#11
|
@param library name of the shared library that supports pkcs#11
|
||||||
@param exc wether exceptions should be thrown */
|
@param exceptions whether exceptions should be thrown */
|
||||||
Library(const std::string& library, bool exc=true):
|
Library(const std::string& library, bool exceptions=true):
|
||||||
_init(new Init(library, exc)) {
|
_init(new Init(library, exceptions)) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1545,7 +1541,8 @@ namespace cryptoki {
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
//! Opens a new session.
|
//! 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):
|
Session(const Slot& slot, bool rw=false):
|
||||||
_slot(slot), _session(0), _res(CKR_OK) {
|
_slot(slot), _session(0), _res(CKR_OK) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
@@ -1553,8 +1550,7 @@ namespace cryptoki {
|
|||||||
//! @todo pass parameter
|
//! @todo pass parameter
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Opens a new session.
|
//! Copy session.
|
||||||
/*! @param slot slot to open a session on */
|
|
||||||
Session(const Session& o):
|
Session(const Session& o):
|
||||||
_slot(o._slot), _session(o._session), _res(CKR_OK) {
|
_slot(o._slot), _session(o._session), _res(CKR_OK) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
@@ -1822,6 +1818,26 @@ namespace cryptoki {
|
|||||||
CRYPTOKI_FN_LOG("C_GetSessionInfo"));
|
CRYPTOKI_FN_LOG("C_GetSessionInfo"));
|
||||||
return info;
|
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:
|
/*! @todo Not implemented:
|
||||||
@code
|
@code
|
||||||
@@ -1833,6 +1849,13 @@ namespace cryptoki {
|
|||||||
}
|
}
|
||||||
@endcode */
|
@endcode */
|
||||||
|
|
||||||
|
//@}
|
||||||
|
|
||||||
|
/** @name login with pin
|
||||||
|
|
||||||
|
Unlock access with pin (login) and unlock after use (logout). */
|
||||||
|
//@{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
class Login {
|
class Login {
|
||||||
@@ -1846,8 +1869,8 @@ namespace cryptoki {
|
|||||||
//! calls @c C_Login
|
//! calls @c C_Login
|
||||||
_session.check(_session._slot.library()->C_Login
|
_session.check(_session._slot.library()->C_Login
|
||||||
(_session._session, userType,
|
(_session._session, userType,
|
||||||
(CK_CHAR*)pin.c_str(),
|
const_cast<CK_CHAR*>((const CK_CHAR*)pin.c_str()),
|
||||||
pin.size()),
|
(int)pin.size()),
|
||||||
CRYPTOKI_FN_LOG("C_Login"));
|
CRYPTOKI_FN_LOG("C_Login"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1874,37 +1897,26 @@ namespace cryptoki {
|
|||||||
|
|
||||||
public:
|
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");
|
CRYPTOLOG("log");
|
||||||
_login = new Login(*this, pin, userType);
|
_login = new Login(*this, pin, userType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Logout from card
|
||||||
|
/** Undo the last login. */
|
||||||
void logout() {
|
void logout() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
_login.reset();
|
_login.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
mrw::Shared<Login> _login;
|
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 {
|
class Object {
|
||||||
@@ -1985,6 +1997,218 @@ namespace cryptoki {
|
|||||||
//! @todo don't call verifyfinal()?
|
//! @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
|
/*! @name C Like Error Handling
|
||||||
@@ -2046,13 +2270,15 @@ namespace cryptoki {
|
|||||||
//! calls @c C_Decrypt
|
//! calls @c C_Decrypt
|
||||||
check(_session._slot.library()->C_Decrypt
|
check(_session._slot.library()->C_Decrypt
|
||||||
(_session._session,
|
(_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"));
|
CRYPTOKI_FN_LOG("C_Decrypt"));
|
||||||
CRYPTOLOG("maximum size is "<<size<<"Bytes");
|
CRYPTOLOG("maximum size is "<<size<<"Bytes");
|
||||||
res.resize(size, 0);
|
res.resize(size, 0);
|
||||||
check(_session._slot.library()->C_Decrypt
|
check(_session._slot.library()->C_Decrypt
|
||||||
(_session._session,
|
(_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),
|
(unsigned char*)&res[0], &size),
|
||||||
CRYPTOKI_FN_LOG("C_Decrypt"));
|
CRYPTOKI_FN_LOG("C_Decrypt"));
|
||||||
CRYPTOLOG("exact size is "<<size<<"Bytes");
|
CRYPTOLOG("exact size is "<<size<<"Bytes");
|
||||||
@@ -2068,7 +2294,7 @@ namespace cryptoki {
|
|||||||
//! calls @c C_DecryptDigestUpdate
|
//! calls @c C_DecryptDigestUpdate
|
||||||
check(_session._slot.library()->C_DecryptDigestUpdate
|
check(_session._slot.library()->C_DecryptDigestUpdate
|
||||||
(_session._session,
|
(_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),
|
(unsigned char*)&res[0], &size),
|
||||||
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate"));
|
CRYPTOKI_FN_LOG("C_DecryptDigestUpdate"));
|
||||||
res.resize(size);
|
res.resize(size);
|
||||||
@@ -2230,7 +2456,6 @@ namespace cryptoki {
|
|||||||
CRYPTOKI_FN_LOG("C_VerifyUpdate"));
|
CRYPTOKI_FN_LOG("C_VerifyUpdate"));
|
||||||
}
|
}
|
||||||
@endcode */
|
@endcode */
|
||||||
//@}
|
|
||||||
|
|
||||||
/*! @todo Not implemented:
|
/*! @todo Not implemented:
|
||||||
@code
|
@code
|
||||||
@@ -2243,15 +2468,6 @@ namespace cryptoki {
|
|||||||
}
|
}
|
||||||
@endcode */
|
@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:
|
/*! @todo Not implemented:
|
||||||
@code
|
@code
|
||||||
bool digestkey() {
|
bool digestkey() {
|
||||||
@@ -2265,7 +2481,8 @@ namespace cryptoki {
|
|||||||
bool encryptinit(CK_MECHANISM_TYPE type, const std::string& param) {
|
bool encryptinit(CK_MECHANISM_TYPE type, const std::string& param) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
CK_MECHANISM mech = {
|
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
|
CRYPTOLOG("encryptinit: type="<<type<<"; mech=("<<mech.mechanism
|
||||||
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
|
<<", "<<mech.pParameter<<", "<<mech.ulParameterLen<<')');
|
||||||
@@ -2283,13 +2500,14 @@ namespace cryptoki {
|
|||||||
//! calls @c C_Encrypt
|
//! calls @c C_Encrypt
|
||||||
check(_session._slot.library()->C_Encrypt
|
check(_session._slot.library()->C_Encrypt
|
||||||
(_session._session,
|
(_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"));
|
CRYPTOKI_FN_LOG("C_Decrypt"));
|
||||||
CRYPTOLOG("maximum size is "<<size<<"Bytes");
|
CRYPTOLOG("maximum size is "<<size<<"Bytes");
|
||||||
res.resize(size, 0);
|
res.resize(size, 0);
|
||||||
check(_session._slot.library()->C_Encrypt
|
check(_session._slot.library()->C_Encrypt
|
||||||
(_session._session,
|
(_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),
|
(unsigned char*)&res[0], &size),
|
||||||
CRYPTOKI_FN_LOG("C_Encrypt"));
|
CRYPTOKI_FN_LOG("C_Encrypt"));
|
||||||
res.resize(size);
|
res.resize(size);
|
||||||
@@ -2345,211 +2563,6 @@ namespace cryptoki {
|
|||||||
}
|
}
|
||||||
@endcode */
|
@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:
|
/*! @todo Not implemented:
|
||||||
@code
|
@code
|
||||||
bool getobjectsize() {
|
bool getobjectsize() {
|
||||||
@@ -2660,8 +2673,9 @@ namespace cryptoki {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! @groupadd cryptokitypes
|
//! @addtogroup cryptokitypes
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
/// Append a cryptoki::Attribute to a cryptoki::AttributeList.
|
/// Append a cryptoki::Attribute to a cryptoki::AttributeList.
|
||||||
inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
|
inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
|
||||||
const cryptoki::Attribute& attr) {
|
const cryptoki::Attribute& attr) {
|
||||||
@@ -2669,6 +2683,7 @@ inline cryptoki::AttributeList& operator<<(cryptoki::AttributeList& list,
|
|||||||
list.push_back(attr);
|
list.push_back(attr);
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList.
|
/// Append a cryptoki::Attribute to a new copy of a cryptoki::AttributeList.
|
||||||
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
|
inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
|
||||||
const cryptoki::Attribute& attr) {
|
const cryptoki::Attribute& attr) {
|
||||||
@@ -2677,6 +2692,7 @@ inline cryptoki::AttributeList operator<<(const cryptoki::AttributeList& list,
|
|||||||
res.push_back(attr);
|
res.push_back(attr);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
//@}
|
//@}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+50
-12
@@ -38,9 +38,26 @@
|
|||||||
#if __GNUC__ >= 2
|
#if __GNUC__ >= 2
|
||||||
//! Macro for internal OpenSSL checks.
|
//! Macro for internal OpenSSL checks.
|
||||||
/*! You can define a different implementation in your compile call */
|
/*! 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
|
#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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -98,13 +115,13 @@ namespace openssl {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual int rsaEncrypt() {
|
virtual std::string rsaEncrypt(const std::string&, int) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return 1;
|
throw std::runtime_error("rsaEncrypt not implemented");
|
||||||
}
|
}
|
||||||
virtual int rsaDecrypt() {
|
virtual std::string rsaDecrypt(const std::string&, int) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return 1;
|
throw std::runtime_error("rsaDecrypt not implemented");
|
||||||
}
|
}
|
||||||
virtual std::string rsaSign(const std::string&, unsigned int) {
|
virtual std::string rsaSign(const std::string&, unsigned int) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
@@ -166,7 +183,7 @@ namespace openssl {
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
static int destroy(ENGINE* e) {
|
static int destroy(ENGINE*) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@@ -195,17 +212,38 @@ namespace openssl {
|
|||||||
Map::iterator it(_map.find(e));
|
Map::iterator it(_map.find(e));
|
||||||
return it!=_map.end()?it->second->privkey(c, u, d):0;
|
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,
|
unsigned char *to,
|
||||||
RSA *rsa, int padding) {
|
RSA *rsa, int padding) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
Map::iterator it(_map.find(rsa->engine));
|
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");
|
CRYPTOLOG("log");
|
||||||
Map::iterator it(_map.find(rsa->engine));
|
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,
|
static int rsaSign(int type, const unsigned char *from,
|
||||||
unsigned int flen,
|
unsigned int flen,
|
||||||
@@ -221,7 +259,7 @@ namespace openssl {
|
|||||||
type));
|
type));
|
||||||
CRYPTOLOG("to="<<(void*)to<<"; len="<<*tlen);
|
CRYPTOLOG("to="<<(void*)to<<"; len="<<*tlen);
|
||||||
CRYPTOLOG("siglen="<<res.size());
|
CRYPTOLOG("siglen="<<res.size());
|
||||||
*tlen = res.size();
|
*tlen = (unsigned int)res.size();
|
||||||
std::copy(res.begin(), res.end(), to);
|
std::copy(res.begin(), res.end(), to);
|
||||||
return 1;
|
return 1;
|
||||||
} catch (const std::exception& e) {
|
} catch (const std::exception& e) {
|
||||||
|
|||||||
+42
-32
@@ -62,10 +62,6 @@
|
|||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
|
||||||
namespace pcsc {
|
|
||||||
std::string version();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API
|
/*! @defgroup gopenssl C++ Wrapper around OpenSSL API
|
||||||
Support for SSL-connections, engines, keys and certificates. */
|
Support for SSL-connections, engines, keys and certificates. */
|
||||||
//@{
|
//@{
|
||||||
@@ -371,11 +367,11 @@ namespace openssl {
|
|||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
class ssl_verification_failed: public ssl_error {
|
class ssl_verification_failed: public ssl_error {
|
||||||
public:
|
public:
|
||||||
ssl_verification_failed(int num) throw():
|
ssl_verification_failed(long num) throw():
|
||||||
ssl_error("certificate verification failed: "+reason(num)) {
|
ssl_error("certificate verification failed: "+reason(num)) {
|
||||||
CRYPTOLOG("**** exception ****");
|
CRYPTOLOG("**** exception ****");
|
||||||
}
|
}
|
||||||
static std::string reason(int num) {
|
static std::string reason(long num) {
|
||||||
switch (num) {
|
switch (num) {
|
||||||
case X509_V_OK:
|
case X509_V_OK:
|
||||||
return "X509_V_OK: Ok the operation was successful.";
|
return "X509_V_OK: Ok the operation was successful.";
|
||||||
@@ -534,7 +530,7 @@ namespace openssl {
|
|||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
BigNum(const std::string& num):
|
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");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
~BigNum() {
|
~BigNum() {
|
||||||
@@ -603,7 +599,7 @@ namespace openssl {
|
|||||||
return &_cb;
|
return &_cb;
|
||||||
}
|
}
|
||||||
operator std::string() const {
|
operator std::string() const {
|
||||||
return std::string((char*)_cb, 8);
|
return std::string((const std::string::value_type*)_cb, 8);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
DES_cblock _cb;
|
DES_cblock _cb;
|
||||||
@@ -654,9 +650,11 @@ namespace openssl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! DES CBC Encryption
|
//! DES CBC Encryption
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
bytes, it is zero filled. The output is always an
|
||||||
integral multiple of eight bytes. */
|
integral multiple of eight bytes.
|
||||||
|
@param key block key
|
||||||
|
@param ivec vector */
|
||||||
inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) {
|
inline std::string desCbcEnc(std::string txt, CBlock8 key, CBlock8& ivec) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
|
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
|
//! DES CBC Encryption with empty vector
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
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 desCbcEnc(const std::string& txt, const CBlock8& key) {
|
inline std::string desCbcEnc(const std::string& txt, const CBlock8& key) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
CBlock8 ivec;
|
CBlock8 ivec;
|
||||||
@@ -679,9 +678,11 @@ namespace openssl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//! DES CBC Decryption
|
//! DES CBC Decryption
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
bytes, it is zero filled. The output is always an
|
||||||
integral multiple of eight bytes. */
|
integral multiple of eight bytes.
|
||||||
|
@param key block key
|
||||||
|
@param ivec vector */
|
||||||
inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) {
|
inline std::string desCbcDec(std::string txt, CBlock8 key, CBlock8& ivec) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
if (txt.size()%8!=0) txt.resize((txt.size()/8+1)*8, 0);
|
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
|
//! DES CBC Decryption with empty vector
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
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) {
|
inline std::string desCbcDec(const std::string& txt, const CBlock8& key) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
CBlock8 ivec;
|
CBlock8 ivec;
|
||||||
return desCbcDec(txt, key, ivec);
|
return desCbcDec(txt, key, ivec);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
bytes, it is zero filled. The output is always an
|
||||||
integral multiple of eight bytes. */
|
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,
|
inline std::string des2edeCbcEnc(std::string txt,
|
||||||
CBlock8 key1, CBlock8 key2,
|
CBlock8 key1, CBlock8 key2,
|
||||||
CBlock8 ivec = CBlock8()) {
|
CBlock8 ivec = CBlock8()) {
|
||||||
@@ -720,9 +725,12 @@ namespace openssl {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*! @param txt If the length is not an integral multiple of eight
|
/*! @param txt If the length is not an integral multiple of eight
|
||||||
bytes, it is zero filled. The output is always an
|
bytes, it is zero filled. The output is always an
|
||||||
integral multiple of eight bytes. */
|
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,
|
inline std::string des2edeCbcDec(std::string txt,
|
||||||
CBlock8 key1, CBlock8 key2,
|
CBlock8 key1, CBlock8 key2,
|
||||||
CBlock8 ivec = CBlock8()) {
|
CBlock8 ivec = CBlock8()) {
|
||||||
@@ -785,7 +793,8 @@ namespace openssl {
|
|||||||
//! Initialize from DER encoded cerificate.
|
//! Initialize from DER encoded cerificate.
|
||||||
X509(const std::string& der): _x509(0) {
|
X509(const std::string& der): _x509(0) {
|
||||||
CRYPTOLOG("log");
|
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())) ||
|
if (!(_x509=d2i_X509(0, &c, der.size())) ||
|
||||||
(const char*)c!=der.begin().operator->()+der.size())
|
(const char*)c!=der.begin().operator->()+der.size())
|
||||||
throw x509_decoding_failed(der);
|
throw x509_decoding_failed(der);
|
||||||
@@ -1121,13 +1130,13 @@ namespace openssl {
|
|||||||
try {
|
try {
|
||||||
EVP_PKEY *pkey(0);
|
EVP_PKEY *pkey(0);
|
||||||
::X509 *cert(0);
|
::X509 *cert(0);
|
||||||
STACK_OF(X509) *ca(0);
|
STACK_OF(X509) *cal(0);
|
||||||
if (!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &ca))
|
if (!PKCS12_parse(p12, password.c_str(), &pkey, &cert, &cal))
|
||||||
throw pkcs12_parsing_failed(filename);
|
throw pkcs12_parsing_failed(filename);
|
||||||
if (pkey) _key = new PrivateKey(pkey);
|
if (pkey) _key = new PrivateKey(pkey);
|
||||||
if (cert) _cert = new X509(cert);
|
if (cert) _cert = new X509(cert);
|
||||||
for (int i(sk_num(CV_STACK ca)); i>0; --i)
|
for (int i(sk_num(CV_STACK cal)); i>0; --i)
|
||||||
_ca.push_back(new X509((::X509*)sk_pop(CV_STACK ca)));
|
_ca.push_back(new X509((::X509*)sk_pop(CV_STACK cal)));
|
||||||
PKCS12_free(p12);
|
PKCS12_free(p12);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
PKCS12_free(p12);
|
PKCS12_free(p12);
|
||||||
@@ -1210,7 +1219,8 @@ namespace openssl {
|
|||||||
//! Read PKCS#7 from memory.
|
//! Read PKCS#7 from memory.
|
||||||
PKCS7(const std::string& memory) {
|
PKCS7(const std::string& memory) {
|
||||||
CRYPTOLOG("log");
|
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));
|
::PKCS7 *p7(d2i_PKCS7_bio(mem, 0));
|
||||||
BIO_free(mem);
|
BIO_free(mem);
|
||||||
if (!p7) throw pkcs7_parsing_failed();
|
if (!p7) throw pkcs7_parsing_failed();
|
||||||
@@ -1327,7 +1337,7 @@ namespace openssl {
|
|||||||
TCP& write(const std::string& s) {
|
TCP& write(const std::string& s) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
if (!_bio) throw tcp_closed_connection();
|
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 (x<=0)
|
||||||
if (BIO_should_retry(_bio)) return write(s);
|
if (BIO_should_retry(_bio)) return write(s);
|
||||||
else {
|
else {
|
||||||
@@ -1432,7 +1442,7 @@ namespace openssl {
|
|||||||
void verify() {
|
void verify() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
if (!_ssl) throw ssl_no_connection();
|
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);
|
if (res!=X509_V_OK) throw ssl_verification_failed(res);
|
||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@
|
|||||||
For special documentations, such as global overviews and
|
For special documentations, such as global overviews and
|
||||||
tutorials, please refere to [Pages](pages.html).
|
tutorials, please refere to [Pages](pages.html).
|
||||||
|
|
||||||
@chapter mainoverview Overview of the Components
|
@section mainoverview Overview of the Components
|
||||||
|
|
||||||
@dot
|
@dot
|
||||||
digraph g {
|
digraph g {
|
||||||
|
|||||||
+12
-12
@@ -77,10 +77,6 @@
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace pcsc {
|
|
||||||
std::string version();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*! @defgroup gpcsc C++ Wrapper around pcsc-lite API
|
/*! @defgroup gpcsc C++ Wrapper around pcsc-lite API
|
||||||
|
|
||||||
This library is a C++ wrapper to the awful pcsc-lite interface.
|
This library is a C++ wrapper to the awful pcsc-lite interface.
|
||||||
@@ -250,7 +246,7 @@ namespace pcsc {
|
|||||||
DWORD dummy(0);
|
DWORD dummy(0);
|
||||||
DWORD s;
|
DWORD s;
|
||||||
DWORD len(MAX_ATR_SIZE);
|
DWORD len(MAX_ATR_SIZE);
|
||||||
unsigned char a[len];
|
unsigned char a[MAX_ATR_SIZE];
|
||||||
check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len),
|
check(SCardStatus(_id, 0, &dummy, &s, &_protocol, a, &len),
|
||||||
"query smartcard status");
|
"query smartcard status");
|
||||||
return Status(s, std::string((char*)a, len));
|
return Status(s, std::string((char*)a, len));
|
||||||
@@ -316,15 +312,17 @@ namespace pcsc {
|
|||||||
@note Prefer the transmit methods that passes @c cla, @c
|
@note Prefer the transmit methods that passes @c cla, @c
|
||||||
ins, @c p1 and @c p2 separate.*/
|
ins, @c p1 and @c p2 separate.*/
|
||||||
std::string transmit(std::string in) {
|
std::string transmit(std::string in) {
|
||||||
DWORD len(1024); // arbitrary
|
const DWORD bufflen(1024);
|
||||||
unsigned char buff[len];
|
DWORD len(bufflen); // arbitrary
|
||||||
|
unsigned char buff[bufflen];
|
||||||
SCARD_IO_REQUEST rPci;
|
SCARD_IO_REQUEST rPci;
|
||||||
rPci.dwProtocol = pci()->dwProtocol;
|
rPci.dwProtocol = pci()->dwProtocol;
|
||||||
rPci.cbPciLength = sizeof(rPci);
|
rPci.cbPciLength = sizeof(rPci);
|
||||||
// log only in verbose debuggung; could log pins
|
// log only in verbose debuggung; could log pins
|
||||||
CRYPTOLOG_VERBOSE("SCardTransmit: "<<crypto::hex(in));
|
CRYPTOLOG_VERBOSE("SCardTransmit: "<<crypto::hex(in));
|
||||||
check(SCardTransmit(_id, &rPci,
|
check(SCardTransmit(_id, &rPci,
|
||||||
(unsigned char*)in.c_str(), in.size(),
|
(LPCBYTE)in.c_str(),
|
||||||
|
in.size(),
|
||||||
0, buff, &len),
|
0, buff, &len),
|
||||||
"smartcard transmit message "+crypto::hex(in));
|
"smartcard transmit message "+crypto::hex(in));
|
||||||
//CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
|
//CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
|
||||||
@@ -342,7 +340,7 @@ namespace pcsc {
|
|||||||
CRYPTOLOG("SCardControl: "<<"Command: "<<controlCode);
|
CRYPTOLOG("SCardControl: "<<"Command: "<<controlCode);
|
||||||
CRYPTOLOG(" -> "<<crypto::hex(in));
|
CRYPTOLOG(" -> "<<crypto::hex(in));
|
||||||
check(SCardControl(_id, controlCode,
|
check(SCardControl(_id, controlCode,
|
||||||
(unsigned char*)in.c_str(), in.size(),
|
(LPCBYTE)in.c_str(), in.size(),
|
||||||
dataBuffer, sizeof(dataBuffer), &len),
|
dataBuffer, sizeof(dataBuffer), &len),
|
||||||
"smartcard control message sent");
|
"smartcard control message sent");
|
||||||
CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)dataBuffer, len)));
|
CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)dataBuffer, len)));
|
||||||
@@ -498,6 +496,8 @@ namespace pcsc {
|
|||||||
|
|
||||||
//! Find all readers with a given ATR.
|
//! Find all readers with a given ATR.
|
||||||
/*! @param atr full or partial ATR to match to the reader's 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 */
|
@returns list of readers that contain @c atr in their ATR */
|
||||||
static Strings getReadersWithAtr(const std::string& atr,
|
static Strings getReadersWithAtr(const std::string& atr,
|
||||||
Scope s=USER, bool exceptions=true) {
|
Scope s=USER, bool exceptions=true) {
|
||||||
@@ -593,9 +593,9 @@ namespace pcsc {
|
|||||||
//! Throws an exception if neccessary.
|
//! Throws an exception if neccessary.
|
||||||
/*! @throw access_error if it is instanciated for exceptions and
|
/*! @throw access_error if it is instanciated for exceptions and
|
||||||
an error occured in the last command. */
|
an error occured in the last command. */
|
||||||
bool check(long state, const std::string& context="") {
|
bool check(long s, const std::string& context="") {
|
||||||
_state = state;
|
_state = s;
|
||||||
check(context);
|
return check(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
//! Throws an exception if neccessary.
|
//! Throws an exception if neccessary.
|
||||||
|
|||||||
+28
-8
@@ -67,7 +67,7 @@ namespace suisseid {
|
|||||||
pukRetries
|
pukRetries
|
||||||
[URL="\ref cardos::Commands::pukRetries"];
|
[URL="\ref cardos::Commands::pukRetries"];
|
||||||
changePin
|
changePin
|
||||||
[URL="\ref cardos::Commands::changePin"];
|
[URL="\ref cardos::Commands::changePins"];
|
||||||
broken [label="replace card"];
|
broken [label="replace card"];
|
||||||
|
|
||||||
start -> transportState;
|
start -> transportState;
|
||||||
@@ -201,7 +201,7 @@ namespace suisseid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get the reader, needed for example to lock a transaction
|
/// Get the reader, needed for example to lock a transaction
|
||||||
/** @begincode
|
/** @code
|
||||||
pcsc::Connection::Reader::Transaction lock(card.reader());
|
pcsc::Connection::Reader::Transaction lock(card.reader());
|
||||||
[... do some low level stuff ...]
|
[... do some low level stuff ...]
|
||||||
@endcode */
|
@endcode */
|
||||||
@@ -292,7 +292,7 @@ namespace suisseid {
|
|||||||
/// @copydoc Card::Card
|
/// @copydoc Card::Card
|
||||||
Post(mrw::Shared<pcsc::Connection::Reader> reader,
|
Post(mrw::Shared<pcsc::Connection::Reader> reader,
|
||||||
const cryptoki::Library& cryptoki):
|
const cryptoki::Library& cryptoki):
|
||||||
Card(reader, cryptoki), _minPinLen(0), _maxPinLen(-1) {
|
Card(reader, cryptoki), _minPinLen(0), _maxPinLen(0) {
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned int minimalPinLength() {
|
virtual unsigned int minimalPinLength() {
|
||||||
@@ -301,7 +301,7 @@ namespace suisseid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
virtual unsigned int maximalPinLength() {
|
virtual unsigned int maximalPinLength() {
|
||||||
if (_maxPinLen==-1) evaluatePinLengths();
|
if (_maxPinLen==0) evaluatePinLengths();
|
||||||
return _maxPinLen;
|
return _maxPinLen;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,9 +411,12 @@ namespace suisseid {
|
|||||||
// By now, scan only for PostSuisseID; in future use factory pattern
|
// By now, scan only for PostSuisseID; in future use factory pattern
|
||||||
pcsc::Connection::Strings readers
|
pcsc::Connection::Strings readers
|
||||||
(pcsc::Connection::getReadersWithAtr("4b53776973735369676e"));
|
(pcsc::Connection::getReadersWithAtr("4b53776973735369676e"));
|
||||||
|
CRYPTOLOG("number of pcsc-readers: "<<readers.size());
|
||||||
for (pcsc::Connection::Strings::iterator reader(readers.begin());
|
for (pcsc::Connection::Strings::iterator reader(readers.begin());
|
||||||
reader!=readers.end(); ++reader) {
|
reader!=readers.end(); ++reader) {
|
||||||
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
|
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
|
||||||
|
CRYPTOLOG("number of cryptoki-readers for "<<*reader
|
||||||
|
<<": "<<slots.size());
|
||||||
if (slots.size()==1)
|
if (slots.size()==1)
|
||||||
res.push_back(dynamic_cast<Card*>
|
res.push_back(dynamic_cast<Card*>
|
||||||
(new Post(pcsc::Connection::reader(*reader),
|
(new Post(pcsc::Connection::reader(*reader),
|
||||||
@@ -452,7 +455,8 @@ namespace suisseid {
|
|||||||
|
|
||||||
/// @name Slots
|
/// @name Slots
|
||||||
//@{
|
//@{
|
||||||
|
|
||||||
|
/// Structure to provide old and new pin
|
||||||
struct PinPukChange {
|
struct PinPukChange {
|
||||||
std::string oldpin;
|
std::string oldpin;
|
||||||
std::string newpin;
|
std::string newpin;
|
||||||
@@ -460,49 +464,65 @@ namespace suisseid {
|
|||||||
return oldpin.size() && newpin.size();
|
return oldpin.size() && newpin.size();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Pin change required - get pins from user
|
||||||
virtual PinPukChange pinChange() {
|
virtual PinPukChange pinChange() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return PinPukChange();
|
return PinPukChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transport pin change required - get pins from user
|
||||||
virtual PinPukChange pinChangeTransportPin() {
|
virtual PinPukChange pinChangeTransportPin() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return pinChange();
|
return pinChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Puk change required - get pins from user
|
||||||
virtual PinPukChange pinChangePuk() {
|
virtual PinPukChange pinChangePuk() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return pinChange();
|
return pinChange();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Transport pin locked - you may show an error message
|
||||||
virtual void transportPinLocked() {
|
virtual void transportPinLocked() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PKCS#15 pin locked - you may show an error message
|
||||||
virtual void pkcs15PinLocked() {
|
virtual void pkcs15PinLocked() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// SigG pin locked - you may show an error message
|
||||||
virtual void sigGPinLocked() {
|
virtual void sigGPinLocked() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Puk locked - you may show an error message
|
||||||
virtual void pukLocked() {
|
virtual void pukLocked() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Certificates will expire soon - you may show an error message
|
||||||
virtual void certsExpireSoon() {
|
virtual void certsExpireSoon() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Certificates are expired soon - you may show an error message
|
||||||
virtual void certsExpired() {
|
virtual void certsExpired() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Certificates have been revoked - you may show an error message
|
||||||
virtual void certsRevoked() {
|
virtual void certsRevoked() {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// install certificates on the card
|
/// 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 */
|
@return @c true on success */
|
||||||
virtual bool installCerts(bool = true) {
|
virtual bool installCerts(bool reinstall = true) {
|
||||||
CRYPTOLOG("log");
|
CRYPTOLOG("log");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user