Added all SuisseID Functionality except certificate import from server, which shall remain closed; refs #28
This commit is contained in:
87
src/pcsc.hxx
87
src/pcsc.hxx
@@ -10,25 +10,6 @@
|
||||
#ifndef PCSC_HXX
|
||||
#define PCSC_HXX
|
||||
|
||||
#ifndef PCSC_LOG
|
||||
//! Declare PCSC_LOG before #include in your de, if you want logging.
|
||||
/*! PCSC_LOG passes its argument to a stream, so your definition must
|
||||
behave so that the argument can be streamed.
|
||||
|
||||
Example, use std::log:
|
||||
@code
|
||||
#define PCSC_LOG(x) std::clog<<x<<" ("<<__PRETTY_FUNCTION__<<')'<<std::endl
|
||||
#include <pcsc.hxx>
|
||||
@endcode
|
||||
|
||||
Example, use qDebug():
|
||||
@code
|
||||
#define PCSC_LOG(x) qDebug()<<x
|
||||
#include <pcsc.hxx>
|
||||
@endcode */
|
||||
#define PCSC_LOG(x) // if unset, do nothing
|
||||
#endif
|
||||
|
||||
#include <cryptaux.hxx>
|
||||
|
||||
#include <mrw/shared.hxx>
|
||||
@@ -132,7 +113,9 @@ namespace pcsc {
|
||||
//----------------------------------------------------------------------------
|
||||
class exception: public std::exception {
|
||||
public:
|
||||
exception(const std::string& reason) throw(): _what("pcsc: "+reason) {}
|
||||
exception(const std::string& reason) throw(): _what("pcsc: "+reason) {
|
||||
CRYPTOLOG("ERROR: "<<what());
|
||||
}
|
||||
~exception() throw() {}
|
||||
const char* what() const throw() {
|
||||
return _what.c_str();
|
||||
@@ -144,21 +127,28 @@ namespace pcsc {
|
||||
class not_implemented: public exception {
|
||||
public:
|
||||
not_implemented(const std::string& reason) throw():
|
||||
exception("feature is not implemented:\n"+reason) {
|
||||
exception("feature is not implemented: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class access_error: public exception {
|
||||
public:
|
||||
access_error(const std::string& reason) throw():
|
||||
exception("smardcard access error:\n"+reason) {
|
||||
exception("smardcard access error: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class wrong_pin: public access_error {
|
||||
public:
|
||||
wrong_pin(const std::string& reason) throw():
|
||||
access_error("wrong pin: "+reason) {
|
||||
}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class runtime_error: public exception {
|
||||
public:
|
||||
runtime_error(const std::string& reason, const std::string& data) throw():
|
||||
exception("runtime error,\n"+reason+":\n"+crypto::hex(data)) {}
|
||||
exception("runtime error, "+reason+": "+crypto::hex(data)) {}
|
||||
};
|
||||
//----------------------------------------------------------------------------
|
||||
class neesting_error: public exception {
|
||||
@@ -216,10 +206,12 @@ namespace pcsc {
|
||||
destructor und must therefore live longer than the
|
||||
Transaction instance. */
|
||||
Transaction(mrw::Shared<Reader> r): _reader(r), _running(true) {
|
||||
CRYPTOLOG("log");
|
||||
_reader->beginTransaction();
|
||||
}
|
||||
//! Cancels the transaction if not yet finished.
|
||||
~Transaction() try {
|
||||
CRYPTOLOG("log");
|
||||
end();
|
||||
} catch (...) {
|
||||
if (!std::uncaught_exception()) throw;
|
||||
@@ -247,6 +239,7 @@ namespace pcsc {
|
||||
|
||||
//! Disconnects connection.
|
||||
~Reader() {
|
||||
CRYPTOLOG("Disconnect Reader");
|
||||
_state = SCardDisconnect(_id, SCARD_RESET_CARD);
|
||||
if (!std::uncaught_exception())
|
||||
_connection->check("disconnect smartcard");
|
||||
@@ -328,13 +321,13 @@ namespace pcsc {
|
||||
SCARD_IO_REQUEST rPci;
|
||||
rPci.dwProtocol = pci()->dwProtocol;
|
||||
rPci.cbPciLength = sizeof(rPci);
|
||||
// don't log; could log pins
|
||||
//PCSC_LOG("SCardTransmit: "<<crypto::hex(in));
|
||||
// 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(),
|
||||
0, buff, &len),
|
||||
"smartcard transmit message "+crypto::hex(in));
|
||||
//PCSC_LOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
|
||||
//CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)buff, len)));
|
||||
return std::string((char*)buff, len);
|
||||
}
|
||||
|
||||
@@ -346,13 +339,13 @@ namespace pcsc {
|
||||
std::string in) {
|
||||
DWORD len(256); // arbitrary
|
||||
UCHAR dataBuffer[256];
|
||||
PCSC_LOG("SCardControl: "<<"Command: "<<controlCode);
|
||||
PCSC_LOG(" -> "<<crypto::hex(in));
|
||||
CRYPTOLOG("SCardControl: "<<"Command: "<<controlCode);
|
||||
CRYPTOLOG(" -> "<<crypto::hex(in));
|
||||
check(SCardControl(_id, controlCode,
|
||||
(unsigned char*)in.c_str(), in.size(),
|
||||
dataBuffer, sizeof(dataBuffer), &len),
|
||||
"smartcard control message sent");
|
||||
PCSC_LOG(" -> "<<crypto::hex(std::string((char*)dataBuffer, len)));
|
||||
CRYPTOLOG(" -> "<<crypto::hex(std::string((char*)dataBuffer, len)));
|
||||
return std::string((char*)dataBuffer, len);
|
||||
}
|
||||
|
||||
@@ -387,8 +380,10 @@ namespace pcsc {
|
||||
/*! Calls @c SCardBeginTransaction unless it's already inside
|
||||
a transaction. */
|
||||
void beginTransaction() {
|
||||
if (++_neesting==1)
|
||||
if (++_neesting==1) {
|
||||
CRYPTOLOG("open transaction");
|
||||
check(SCardBeginTransaction(_id), "smartcard begin transaction");
|
||||
}
|
||||
}
|
||||
|
||||
//! Use scoped transactions with @ref Transaction
|
||||
@@ -397,10 +392,11 @@ namespace pcsc {
|
||||
@throws neesting_error if there are more calls to @c
|
||||
endTransaction than to @c beginTransaction. */
|
||||
void endTransaction() {
|
||||
if (--_neesting==0)
|
||||
if (--_neesting==0) {
|
||||
CRYPTOLOG("close transaction");
|
||||
check(SCardEndTransaction(_id, SCARD_LEAVE_CARD),
|
||||
"smartcard end transaction");
|
||||
else if (_neesting<0) {
|
||||
} else if (_neesting<0) {
|
||||
_neesting = 0;
|
||||
throw neesting_error();
|
||||
}
|
||||
@@ -432,6 +428,7 @@ namespace pcsc {
|
||||
DWORD mode=SCARD_SHARE_SHARED,
|
||||
DWORD protocol=SCARD_PROTOCOL_T1):
|
||||
name(nm), _connection(c) {
|
||||
CRYPTOLOG("Connect Reader");
|
||||
check(SCardConnect(_connection->id(), strconv(name).c_str(),
|
||||
mode, protocol,
|
||||
&_id, &_protocol),
|
||||
@@ -513,7 +510,7 @@ namespace pcsc {
|
||||
&num),
|
||||
"smartcard get size of readers of groups "+grp))
|
||||
return res;
|
||||
PCSC_LOG("size of readers: "<<num);
|
||||
CRYPTOLOG("size of readers: "<<num);
|
||||
if (!num) return res;
|
||||
std::auto_ptr<char_t> nm(new char_t[num]);
|
||||
if (!check(SCardListReaders(_connectionlifetime->id(),
|
||||
@@ -521,9 +518,9 @@ namespace pcsc {
|
||||
nm.get(), &num),
|
||||
"smartcard list reader names of groups "+grp))
|
||||
return res;
|
||||
PCSC_LOG("got all readers, size is "<<num);
|
||||
CRYPTOLOG("got all readers, size is "<<num);
|
||||
if (!num) return res;
|
||||
PCSC_LOG("list of readers: "
|
||||
CRYPTOLOG("list of readers: "
|
||||
<<crypto::readable(std::string(nm.get(), num-1)));
|
||||
return res = split(strconv(string(nm.get(), num-1)));
|
||||
}
|
||||
@@ -620,10 +617,12 @@ namespace pcsc {
|
||||
ConnectionLifetime(Scope s, bool exc):
|
||||
_exc(exc), _id(0),
|
||||
_state(SCardEstablishContext(s, 0, 0, &_id)) {
|
||||
CRYPTOLOG("Open Connection");
|
||||
check("establish smartcard context");
|
||||
}
|
||||
//! Closes the connection (releases the smartcard context)
|
||||
~ConnectionLifetime() {
|
||||
CRYPTOLOG("Close Connection");
|
||||
_state = SCardReleaseContext(_id);
|
||||
if (!std::uncaught_exception()) check("smartcard release context");
|
||||
}
|
||||
@@ -641,9 +640,15 @@ namespace pcsc {
|
||||
bool check(const std::string& context="") {
|
||||
if (_exc&&!*this)
|
||||
if (context.size())
|
||||
throw access_error(context+": "+error());
|
||||
if (_state==SCARD_W_WRONG_CHV)
|
||||
throw wrong_pin(context+": "+error());
|
||||
else
|
||||
throw access_error(context+": "+error());
|
||||
else
|
||||
throw access_error(error());
|
||||
if (_state==SCARD_W_WRONG_CHV)
|
||||
throw wrong_pin(error());
|
||||
else
|
||||
throw access_error(error());
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -721,8 +726,8 @@ namespace pcsc {
|
||||
ss<<"The smart card resource manager has shut down.";
|
||||
break;
|
||||
case SCARD_E_SHARING_VIOLATION:
|
||||
ss<<"The smart card cannot be accessed because of other outstanding"
|
||||
<<" connections.";
|
||||
ss<<"The smart card cannot be accessed because of other"
|
||||
<<" outstanding connections.";
|
||||
break;
|
||||
case SCARD_E_SYSTEM_CANCELLED:
|
||||
ss<<"The action was cancelled by the system, presumably to log"
|
||||
@@ -757,8 +762,8 @@ namespace pcsc {
|
||||
ss<<"No error was encountered.";
|
||||
break;
|
||||
case SCARD_W_REMOVED_CARD:
|
||||
ss<<"The smart card has been removed, so that further communication"
|
||||
<<" is not possible.";
|
||||
ss<<"The smart card has been removed, so that further"
|
||||
<<" communication is not possible.";
|
||||
break;
|
||||
case SCARD_W_RESET_CARD:
|
||||
ss<<"The smart card was reset.";
|
||||
|
Reference in New Issue
Block a user