This library provides a simple and nice C++ wrapper around these libraries, so that programmers can concentrate on functionality. It offers general support for PCSC-lite, OpenSSL, PKCS#11, plus specific functionality for the SuisseID.
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
166 lines
6.4 KiB
166 lines
6.4 KiB
11 years ago
|
/*! @file
|
||
|
|
||
|
@id $Id$
|
||
|
*/
|
||
|
// 1 2 3 4 5 6 7 8
|
||
|
// 45678901234567890123456789012345678901234567890123456789012345678901234567890
|
||
|
|
||
|
// #include <pcsc.hxx>
|
||
|
// #include <cryptaux.hxx>
|
||
|
// #include <openssl.hxx>
|
||
|
|
||
|
#include <string>
|
||
11 years ago
|
#include <mrw/checkcxx11.hxx>
|
||
11 years ago
|
#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
|
||
11 years ago
|
<<" (r)ead(b)erfile Read selected BER file"<<std::endl
|
||
11 years ago
|
<<" (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());
|
||
11 years ago
|
else if (cmd=="readberfile"||cmd=="rb") _ber=readBerFile();
|
||
|
else if (cmd=="readbinfile"||cmd=="rbf") readBinary();
|
||
11 years ago
|
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() {
|
||
11 years ago
|
_readers = pcsc::Connection::scan();
|
||
11 years ago
|
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();
|
||
11 years ago
|
pcsc::Connection::Strings::size_type num(0);
|
||
|
if (std::cin>>num && num<_readers.size()) {
|
||
11 years ago
|
_reader = pcsc::Connection::reader(_readers[num]);
|
||
11 years ago
|
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;
|
||
11 years ago
|
cardos::BerValues record(cardos::Commands::retData(res).substr(2));
|
||
11 years ago
|
_ber += record;
|
||
11 years ago
|
std::cout<<record[0][0][0].string()
|
||
11 years ago
|
<<": len="
|
||
11 years ago
|
<<record[0][2][0][2].ulong()
|
||
|
<<"-"<<record[0][2][0][4].ulong()<<std::endl;
|
||
11 years ago
|
}
|
||
|
}
|
||
|
|
||
|
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::Strings _readers;
|
||
|
|
||
|
cardos::BerValues _ber;
|
||
|
|
||
|
};
|
||
|
|
||
|
int main(int, char**) {
|
||
|
std::cout<<"Type \"help\" for help."<<std::endl;
|
||
|
return Commands().run();
|
||
|
}
|