changed for new libpcscxx interface version 3; refs #176

This commit is contained in:
Marc Wäckerlin
2014-04-04 11:29:41 +00:00
parent d02ef2ff55
commit fbb3150285
11 changed files with 381 additions and 483 deletions

View File

@@ -12,10 +12,8 @@
#include <pinentry.hxx>
#include <cryptoki.hxx>
#include <pcsc.hxx>
#include <suisseid.hxx>
#include <openssl-engine.hxx>
#include <openssl.hxx>
#include <memory>
@@ -29,8 +27,7 @@ class CryptokiEngine: public QObject, public openssl::Engine {
public:
CryptokiEngine(std::string lib):
_cryptoki(lib) {
CryptokiEngine() {
TRC;
}
@@ -41,10 +38,6 @@ class CryptokiEngine: public QObject, public openssl::Engine {
return _privateKey.get();
}
cryptoki::Library& cryptoki() {
return _cryptoki;
}
void cert(cryptoki::Object& privateKey, const std::string& certVal) {
TRC;
_privateKey = std::auto_ptr<cryptoki::Object>
@@ -110,12 +103,12 @@ class CryptokiEngine: public QObject, public openssl::Engine {
virtual const char* id() {
TRC;
return "CryptokiEngine_ID";
return "SuisseID Engine ID";
}
virtual const char* name() {
TRC;
return "CryptokiEngine_NAME";
return "SuisseID Engine NAME";
}
virtual std::string rsaSign(const std::string& in, unsigned int type) try {
@@ -139,7 +132,6 @@ class CryptokiEngine: public QObject, public openssl::Engine {
private:
cryptoki::Library _cryptoki;
std::auto_ptr<cryptoki::Object> _privateKey;
};
@@ -149,8 +141,8 @@ class SmartCardAuth: public QObject {
public:
SmartCardAuth(const QString& lib, QWidget* p=0, bool loginAtStart=true):
_parent(p), _e(new CryptokiEngine(lib.toStdString())), _reg(_e) {
SmartCardAuth(suisseid::Cards cards, QWidget* p=0, bool loginAtStart=true):
_parent(p), _e(new CryptokiEngine()), _reg(_e), _cards(cards) {
TRC;
if (loginAtStart) login();
assert(connect(_e, SIGNAL(certRequired()), SLOT(login())));
@@ -160,84 +152,37 @@ class SmartCardAuth: public QObject {
void login(bool force=true) {
TRC;
Lock lock;
LOG<<"got lock";
if (!_e || (!force && *_e)) return; // no smartcard or already logged in
LOG<<"get new certificate";
try {
Lock lock;
LOG<<"got lock";
if (!_e || (!force && *_e)) return; // no smartcard or already logged in
LOG<<"start login to smartcard";
QList<CertInfo> authcerts;
QList<CertInfo> allcerts;
QSslConfiguration sslConfig(QSslConfiguration::defaultConfiguration());
_slots = _e->cryptoki().slotList();
LOG<<"number of slots"<<_slots.size();
// look for login certificates ----------------------------------------
for (cryptoki::SlotList::iterator slot(_slots.begin());
slot!=_slots.end(); ++slot) {
cryptoki::Session session(*slot);
cryptoki::ObjectList certs(session.find
(cryptoki::Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_CERTIFICATE)));
for (cryptoki::ObjectList::iterator cert(certs.begin());
cert!=certs.end(); ++cert) {
cryptoki::Attribute label(cert->attribute(CKA_LABEL));
cryptoki::Attribute id(cert->attribute(CKA_ID));
LOG<<"**** FOUND CERTIFICATE: "<<label.value.c_str();
cryptoki::ObjectList keys
(session.find(cryptoki::Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_PUBLIC_KEY),
id));
LOG<<"**** with keys: "<<keys.size();
std::string data(cert->attribute(CKA_VALUE).value);
if (!keys.size()) { // add CA-certificate
LOG<<"**** add to CA-certificates";
} else {
LOG<<"**** user cert, check for authentictaion";
if (label.value.find("auth")==0 ||
label.value.find("Authentication")!=std::string::npos) {
LOG<<"**** it's our authentication cert";
authcerts.push_back(CertInfo(data, slot, id));
} else {
LOG<<"**** it's an unknown cert";
allcerts.push_back(CertInfo(data, slot, id));
}
}
}
}
// get pin and install client certificate ------------------------------
LOG<<"00000000000000000000000000000000000000000000000000";
if (!authcerts.isEmpty() || !allcerts.isEmpty()) {
LOG<<"11111111111111111111111111111111111111111111111111";
CertInfo c(authcerts.size()?authcerts[0]:allcerts[0]);
PinEntry pinEntry(QSslCertificate(QByteArray(c.data.data(),
c.data.size()),
for (suisseid::Cards::iterator card(_cards.begin());
card!=_cards.end(); ++card) {
suisseid::Certificate cert((*card)->authenticationCertificate());
PinEntry pinEntry(QSslCertificate(QByteArray(cert.data(),
cert.size()),
QSsl::Der), _parent);
while (true) try {
LOG<<"******************************************1*******";
pinEntry.tokeninfo(c.slot->tokeninfo())
.retries(retries(c.slot->slotinfo().slotDescription));
LOG<<"******************************************2*******";
int res(pinEntry.myexec());
LOG<<"******************************************3*******";
if (res!=PinEntry::Accepted) return;
LOG<<"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
if (pinEntry
.tokeninfo((*card)->minimalPinLength(),
(*card)->maximalPinLength())
.retries((*card)->pkcs15PinRetries())
.myexec()
!=PinEntry::Accepted)
return;
_session = // session login with pin
std::auto_ptr<cryptoki::Session>
(new cryptoki::Session(*c.slot));
LOG<<"BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB";
std::shared_ptr<cryptoki::Session>
(new cryptoki::Session((*card)->session()));
_session->login(pinEntry.pin().toStdString());
LOG<<"CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC";
cryptoki::ObjectList keys
(_session->find(cryptoki::Attribute(CKA_CLASS)
.from<CK_OBJECT_CLASS>(CKO_PRIVATE_KEY),
c.id));
LOG<<"DDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD";
cert.id()));
if (keys.size()==1) {
LOG<<"**** found one private key";
_e->cert(keys[0], c.data); // install client cert
LOG<<"==================================================";
_e->cert(keys[0], cert); // install client cert
break;
}
LOG<<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
} catch (std::exception& x) {
pinEntry.pin().clear();
LOG<<"**** ERROR"<<x.what();
@@ -246,150 +191,16 @@ class SmartCardAuth: public QObject {
" please try again."));
}
}
LOG<<"YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY";
} catch (std::exception& x) {
LOG<<"**** ERROR"<<x.what();
throw;
}
LOG<<"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ";
}
private:
int minPinLen(const std::string& name) {
TRC; LOG<<name.c_str();
try {
pcsc::Connection pcsc;
mrw::Shared<pcsc::Connection::Reader> reader(pcsc.reader(name));
#ifndef Q_OS_MAC
pcsc::Connection::Reader::Transaction lock(reader);
#endif
// first try to read version info
if (reader->transmit(0x00, 0xA4, 0x08, 0x0C, "\x3f\x00\x56\x49", 4)
!= std::string("\x90\x00", 2) || !reader) {
LOG<<"Select File failed";
return -2;
}
std::string res(reader->transmit(0x00, 0xB0, 0x00, 0x00));
if (res.substr(res.size()-2)!=std::string("\x90\x00", 2)) {
LOG<<"read error";
return -2;
}
LOG<<"version text is: "<<res.substr(4, res[3]).c_str();
// if (res.substr(4, res[3]) != "RAPost 2009" &&
// res.substr(4, res[3]) != "RAPost 2010") {
// LOG<<"unsupported card";
// return -2;
// }
if (retCode(reader->transmit(0x00, 0xA4, 0x00, 0x0C)) == 0x9000) {
int value(retCode(reader->transmit(0x00, 0x20, 0x00, 0x81)));
if ((value&0x63C0)==0x63C0) return value&0x0F;
} else {
LOG<<"**** ERROR in select MF while reading pin status";
}
return -1; // locked
} catch (const std::exception& x) {
LOG<<"**** ERROR while reading pin status: "<<x.what();
return -2;
}
}
int maxPinLen(const std::string& name) {
TRC; LOG<<name.c_str();
try {
pcsc::Connection pcsc;
mrw::Shared<pcsc::Connection::Reader> reader(pcsc.reader(name));
#ifndef Q_OS_MAC
pcsc::Connection::Reader::Transaction lock(reader);
#endif
// first try to read version info
if (reader->transmit(0x00, 0xA4, 0x08, 0x0C, "\x3f\x00\x56\x49", 4)
!= std::string("\x90\x00", 2) || !reader) {
LOG<<"Select File failed";
return -2;
}
std::string res(reader->transmit(0x00, 0xB0, 0x00, 0x00));
if (res.substr(res.size()-2)!=std::string("\x90\x00", 2)) {
LOG<<"read error";
return -2;
}
LOG<<"version text is: "<<res.substr(4, res[3]).c_str();
// if (res.substr(4, res[3]) != "RAPost 2009" &&
// res.substr(4, res[3]) != "RAPost 2010") {
// LOG<<"unsupported card";
// return -2;
// }
if (retCode(reader->transmit(0x00, 0xA4, 0x00, 0x0C)) == 0x9000) {
int value(retCode(reader->transmit(0x00, 0x20, 0x00, 0x81)));
if ((value&0x63C0)==0x63C0) return value&0x0F;
} else {
LOG<<"**** ERROR in select MF while reading pin status";
}
return -1; // locked
} catch (const std::exception& x) {
LOG<<"**** ERROR while reading pin status: "<<x.what();
return -2;
}
}
int retries(const std::string& name) {
TRC; LOG<<name.c_str();
try {
pcsc::Connection pcsc;
mrw::Shared<pcsc::Connection::Reader> reader(pcsc.reader(name));
#ifndef Q_OS_MAC
pcsc::Connection::Reader::Transaction lock(reader);
#endif
// first try to read version info
if (reader->transmit(0x00, 0xA4, 0x08, 0x0C, "\x3f\x00\x56\x49", 4)
!= std::string("\x90\x00", 2) || !reader) {
LOG<<"Select File failed";
return -2;
}
std::string res(reader->transmit(0x00, 0xB0, 0x00, 0x00));
if (res.substr(res.size()-2)!=std::string("\x90\x00", 2)) {
LOG<<"read error";
return -2;
}
LOG<<"version text is: "<<res.substr(4, res[3]).c_str();
// if (res.substr(4, res[3]) != "RAPost 2009" &&
// res.substr(4, res[3]) != "RAPost 2010") {
// LOG<<"unsupported card";
// return -2;
// }
if (retCode(reader->transmit(0x00, 0xA4, 0x00, 0x0C)) == 0x9000) {
int value(retCode(reader->transmit(0x00, 0x20, 0x00, 0x81)));
if ((value&0x63C0)==0x63C0) return value&0x0F;
} else {
LOG<<"**** ERROR in select MF while reading pin status";
}
return -1; // locked
} catch (const std::exception& x) {
LOG<<"**** ERROR while reading pin status: "<<x.what();
return -2;
}
}
int retCode(const std::string& res) {
if (res.size()>=2)
return ((((unsigned int)(unsigned char)res[res.size()-2])*256)
+((unsigned int)(unsigned char)res[res.size()-1]));
else
return -1;
}
private:
struct CertInfo {
CertInfo(std::string d, cryptoki::SlotList::iterator s,
cryptoki::Attribute i):
data(d), slot(s), id(i) {
}
std::string data;
cryptoki::SlotList::iterator slot;
cryptoki::Attribute id;
};
class Lock {
public:
Lock() {
@@ -416,8 +227,8 @@ class SmartCardAuth: public QObject {
QWidget* _parent;
CryptokiEngine* _e;
openssl::RegisterEngine<CryptokiEngine> _reg;
cryptoki::SlotList _slots;
std::auto_ptr<cryptoki::Session> _session;
suisseid::Cards _cards;
std::shared_ptr<cryptoki::Session> _session;
};