added basic suisse id functions; refs #28

This commit is contained in:
Marc Wäckerlin
2013-10-21 07:10:46 +00:00
parent 1de9676582
commit cbef3c6e8c
10 changed files with 2646 additions and 285 deletions

View File

@@ -0,0 +1,164 @@
/*! @file
@id $Id$
*/
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
// #include <pcsc.hxx>
// #include <cryptaux.hxx>
// #include <openssl.hxx>
#include <string>
#include <memory>
#include <cctype>
#include <stdexcept>
#include <sstream>
#include <iostream>
#include <iomanip>
#define CARDOS_LOG(X) std::cout<<X<<std::endl
#include <cardos.hxx>
class Commands: public cardos::Commands {
public:
void help() {
std::cout
<<"Commands: "<<std::endl
<<" COMMAND DATA PURPOSE"<<std::endl
<<" (h)elp Show this help"<<std::endl
<<" (q)quit Quit"<<std::endl
<<" (l)ist List all reader"<<std::endl
<<" (r)eader <num> Select reader by number"<<std::endl
<<" (s)erial Show token serial number"<<std::endl
<<" (a)pdu <hex> Send APDU hex data"<<std::endl
<<" (m)aster(f)ile Select master file"<<std::endl
<<" (p)kcs(15) Select PKCS#15 file"<<std::endl
<<" (s)ig(g) Select SigG file"<<std::endl
<<" (s)elect(f)ile <hex> Select file below master"<<std::endl
<<" (s)elect(p)15(f)ile <hex> Select file below PKCS#15"<<std::endl
<<" (s)elect(s)igg(f)ile <hex> Select file below SigG"<<std::endl
<<" (r)ead(b)in(f)ile Read selected binary file"<<std::endl
<<" (r)ead(a)bsolute(r)ecord Read absolute record"<<std::endl
<<" (r)ead(f)irst(r)ecord Read first record"<<std::endl
<<" (r)ead(n)ext(r)ecord Read next record"<<std::endl
<<" (p)in(s)status <id> Query status of PIN <id>"<<std::endl
<<" (l)ogon <id> <pin> logon to key with PIN"<<std::endl
<<" (l)ogon(p)15 <pin> logon with user PIN"<<std::endl
<<" (l)ogonpu(k) <pin> logon with user PUK"<<std::endl
<<" (l)ogon(s)igg <pin> logon with SigG PIN"<<std::endl
<<" (l)ogon(t)transport <pin> logon with transport PIN"<<std::endl
<<" (g)et(p)in(l)engths get PIN min max lengths"<<std::endl
<<"Note: \"(h)elp\" means: type \"help\" or simply \"h\""<<std::endl;
}
int run() {
std::string cmd;
while (std::cout<<"cmd> ", std::cin>>cmd) try {
if (cmd=="help"||cmd=="h") help();
else if (cmd=="quit"||cmd=="q") return 0;
else if (cmd=="list"||cmd=="l") listReader();
else if (cmd=="reader"||cmd=="r") selectReader();
else if (cmd=="serial"||cmd=="s") serial();
else if (cmd=="apdu"||cmd=="a") sendAPDU(apdu());
else if (cmd=="masterfile"||cmd=="mf") selectMF();
else if (cmd=="pkcs15"||cmd=="p15") selectPkcs15();
else if (cmd=="sigg"||cmd=="sg") selectSigG();
else if (cmd=="selectfile"||cmd=="sf") selectMfFile(apdu());
else if (cmd=="selectp15file"||cmd=="spf") selectPkcs15File(apdu());
else if (cmd=="selectsiggfile"||cmd=="ssf") selectSigGFile(apdu());
else if (cmd=="readbinfile"||cmd=="rbf") _ber=readBinFile();
else if (cmd=="readabsoluterecord"||cmd=="rar") _ber=readRecord();
else if (cmd=="readfirstrecord"||cmd=="rfr")
_ber=readRecord(0, 0, FIRST_RECORD);
else if (cmd=="readnextrecord"||cmd=="rnr")
_ber=readRecord(0, 0, NEXT_RECORD);
else if (cmd=="pinstatus"||cmd=="ps") pinStatus(id());
else if (cmd=="logon"||cmd=="l") logon(id(), pin());
else if (cmd=="logonp15"||cmd=="lp") logonPkcs15(pin());
else if (cmd=="logonppuk"||cmd=="lk") logonPuk(pin());
else if (cmd=="logonsigg"||cmd=="ls") logonSigG(pin());
else if (cmd=="logontransport"||cmd=="lt") logonTransport(pin());
else if (cmd=="getpinlengths"||cmd=="gpl") getPinLengths();
else if (cmd=="print"||cmd=="p") std::cout<<_ber.print()<<std::endl;
else help();
} catch (const std::exception& e) {
std::cout<<"**** Error: "<<e.what()<<std::endl;
}
return 0;
}
void listReader() {
_readers = _c.scan();
std::cout<<"Found "<<_readers.size()<<" readers"
<<(_readers.size()?":":".")<<std::endl;
int i(0);
for (pcsc::Connection::Strings::const_iterator it(_readers.begin());
it!=_readers.end(); ++it, ++i)
std::cout<<" "<<i<<". "<<*it<<std::endl;
}
void selectReader() {
listReader();
if (_readers.size()<0) return;
int num(-1);
if (std::cin>>num && num>=0 && num<_readers.size()) {
_reader = _c.reader(_readers[num]);
std::cout<<"Active Reader: "<<_readers[num]<<std::endl;
} else throw std::runtime_error("no valid reader selected");
}
void getPinLengths() {
selectPkcs15File("4408");
_ber.clear();
while (true) {
std::string res(send(0x00, 0xB2, 0, NEXT_RECORD));
if (cardos::Commands::retCode(res)!=0x9000) break;
cardos::BerValue record(cardos::Commands::retData(res).substr(2));
_ber += record;
std::cout<<record[0][0].value()
<<": len="
<<record[2][0][2].toULong()
<<"-"<<record[2][0][4].toULong()<<std::endl;
}
}
private:
std::string apdu() {
std::string data;
if (!(std::cin>>data))
throw std::runtime_error("please enter bytes in hex");
return data;
}
std::string pin() {
std::string data;
if (!(std::cin>>data))
throw std::runtime_error("please enter pin");
return data;
}
unsigned char id() {
std::string data;
if (!(std::cin>>data) || data.size()!=2 ||
data.find_first_not_of("0123456789abcdef")!=std::string::npos)
throw std::runtime_error("please enter one byte in hex");
return crypto::hexToBin(data)[0];
}
private:
pcsc::Connection _c;
pcsc::Connection::Strings _readers;
cardos::BerValues _ber;
};
int main(int, char**) {
std::cout<<"Type \"help\" for help."<<std::endl;
return Commands().run();
}

View File

@@ -14,11 +14,12 @@
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <tuple>
#include <sstream>
#include <fstream>
#include <streambuf>
#ifndef MRW__OLD_PRE11_COMPILER
#include <chrono>
#endif
int main(int argc, char** argv) try {

View File

@@ -3,79 +3,36 @@
## 1 2 3 4 5 6 7 8
## 45678901234567890123456789012345678901234567890123456789012345678901234567890
noinst_PROGRAMS = pcsc-demo cryptoki-sign-demo cryptoki-demo \
openssl-tcp-demo openssl-ssl-demo \
openssl-engine-demo suisse-id-demo
noinst_PROGRAMS = pcsc-demo cryptoki-sign-demo cryptoki-demo \
openssl-tcp-demo openssl-ssl-demo \
openssl-engine-demo suisse-id-demo cardos-demo
AM_CPPFLAGS += -I/usr/include/PCSC
AM_CPPFLAGS += -I${top_srcdir}/src -I/usr/include/PCSC
AM_LDFLAGS = -L${top_builddir}/src -lpcscxx
if MINGW32
AM_LDFLAGS += /opt/local/i586-mingw32msvc/lib/winscard.a -leay32
endif
if MAC
AM_CPPFLAGS+=-I/Library/OpenSC/include
LDFLAGS += -F/System/Library/Frameworks/PCSC.framework -framework PCSC -L/opt/local/lib -lcrypto
AM_LDFLAGS += -F/System/Library/Frameworks/PCSC.framework -framework PCSC -L/opt/local/lib -lcrypto
endif
if !MINGW32
if !MAC
LDFLAGS += -lpcsclite
AM_LDFLAGS += -lpcsclite
endif
endif
if !MINGW32
LDFLAGS += -ldl -lpthread -lssl -lcrypto
AM_LDFLAGS += -ldl -lpthread -lssl -lcrypto
endif
pcsc_demo_SOURCES = pcsc-demo.cxx
pcsc_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
pcsc_demo_LDFLAGS = -L${top_builddir}/src
pcsc_demo_LDADD = -lpcscxx
if MINGW32
pcsc_demo_LDADD += /opt/local/i586-mingw32msvc/lib/winscard.a
endif
cryptoki_demo_SOURCES = cryptoki-demo.cxx
cryptoki_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
cryptoki_demo_LDADD = -lpcscxx
cryptoki_demo_LDFLAGS = -L${top_builddir}/src
if MINGW32
cryptoki_demo_LDADD += -leay32
endif
cryptoki_sign_demo_SOURCES = cryptoki-sign-demo.cxx
cryptoki_sign_demo_CPPFLAGS = -std=c++0x -I${top_srcdir}/src -I/usr/include/PCSC
cryptoki_sign_demo_LDADD = -lpcscxx
cryptoki_sign_demo_LDFLAGS = -L${top_builddir}/src
if MINGW32
cryptoki_demo_LDADD += -leay32
endif
openssl_tcp_demo_SOURCES = openssl-tcp-demo.cxx
openssl_tcp_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
openssl_tcp_demo_LDFLAGS = -L${top_builddir}/src
openssl_tcp_demo_LDADD = -lpcscxx
if MINGW32
openssl_tcp_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a
endif
openssl_ssl_demo_SOURCES = openssl-ssl-demo.cxx
openssl_ssl_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
openssl_ssl_demo_LDFLAGS = -L${top_builddir}/src
openssl_ssl_demo_LDADD = -lpcscxx
if MINGW32
openssl_ssl_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a
endif
openssl_engine_demo_SOURCES = openssl-engine-demo.cxx
openssl_engine_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
openssl_engine_demo_LDFLAGS = -L${top_builddir}/src
openssl_engine_demo_LDADD = -lpcscxx
if MINGW32
openssl_engine_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a
endif
suisse_id_demo_SOURCES = suisse-id-demo.cxx
suisse_id_demo_CPPFLAGS = -I${top_srcdir}/src -I/usr/include/PCSC
suisse_id_demo_LDFLAGS = -L${top_builddir}/src
suisse_id_demo_LDADD = -lpcscxx
if MINGW32
suisse_id_demo_LDADD += /opt/local/i586-mingw32msvc/lib/ssleay32.a /opt/local/i586-mingw32msvc/lib/libeay32.a
endif
cardos_demo_SOURCES = cardos-demo.cxx
MAINTAINERCLEANFILES = makefile.in

View File

@@ -5,91 +5,12 @@
// 1 2 3 4 5 6 7 8
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
#include <cryptoki.hxx>
#include <pcsc.hxx>
#include <mrw/args.hxx>
#include <mrw/vector.hxx>
#include <mrw/shared.hxx>
#include <suisseid.hxx>
#include <mrw/args.hxx>
#include <stdexcept>
#include <iostream>
namespace suisseid {
class Card {
public:
Card(mrw::Shared<pcsc::Connection::Reader> reader,
mrw::Shared<cryptoki::Slot> slot):
_reader(reader),
_slot(slot) {
}
virtual ~Card() {}
const std::string& name() {
return _reader->name;
}
private:
mrw::Shared<pcsc::Connection::Reader> _reader;
mrw::Shared<cryptoki::Slot> _slot;
};
class PostSuisseID: public Card {
public:
PostSuisseID(mrw::Shared<pcsc::Connection::Reader> reader,
mrw::Shared<cryptoki::Slot> slot):
Card(reader, slot) {
}
};
class Manager {
public:
Manager(const std::string& lib="libcvP11.so"):
_cryptoki(lib) {
}
Manager(const pcsc::Connection& pcsc,
const std::string& lib="libcvP11.so"):
_pcsc(pcsc),
_cryptoki(lib) {
}
Manager(const cryptoki::Library& cryptoki):
_cryptoki(cryptoki) {
}
Manager(const pcsc::Connection& pcsc,
const cryptoki::Library& cryptoki):
_pcsc(pcsc),
_cryptoki(cryptoki) {
}
typedef std::vector<mrw::Shared<Card> > Cards;
Cards scan() {
Cards res;
// By now, scan only for PostSuisseID; in future use factory pattern
pcsc::Connection::Strings readers
(_pcsc.getReadersWithAtr("4b53776973735369676e"));
for (pcsc::Connection::Strings::iterator reader(readers.begin());
reader!=readers.end(); ++reader) {
cryptoki::SlotList slots(_cryptoki.slotList(true, *reader));
if (slots.size()==1)
res.push_back(dynamic_cast<Card*>
(new PostSuisseID(_pcsc.reader(*reader), slots[0])));
}
return res;
}
private:
pcsc::Connection _pcsc;
cryptoki::Library _cryptoki;
};
}
int main(int argc, char** argv) try {
std::string lib("libcvP11.so");
@@ -105,11 +26,13 @@ int main(int argc, char** argv) try {
mrw::args::decl::param_list()
<<mrw::args::param(lib, "lib")));
suisseid::Manager suisseid;
suisseid::Manager::Cards cards(suisseid.scan());
for (suisseid::Manager::Cards::iterator card(cards.begin());
card!=cards.end(); ++card)
std::cout<<"Found SuisseID: "<<(*card)->name()<<std::endl;
suisseid::Cards cards(suisseid::Scanner(lib).scan());
for (suisseid::Cards::iterator card(cards.begin()); card!=cards.end(); ++card)
std::cout<<"Found SuisseID:"<<std::endl
<<" Reader Name: "<<(*card)->name()<<std::endl
<<" Version: "<<(*card)->version()<<std::endl
<<" PIN-Length: "<<(*card)->minimalPinLength()
<<" - "<<(*card)->maximalPinLength()<<std::endl;
return 0;
} catch (std::exception& x) {
std::cerr<<"**** ERROR in "<<*argv<<": "<<x.what()<<std::endl;