| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  | /*! @file
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     @id $Id$ | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | //       1         2         3         4         5         6         7         8
 | 
					
						
							|  |  |  | // 45678901234567890123456789012345678901234567890123456789012345678901234567890
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // #include <pcsc.hxx>
 | 
					
						
							|  |  |  | // #include <cryptaux.hxx>
 | 
					
						
							|  |  |  | // #include <openssl.hxx>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2014-04-03 11:21:18 +00:00
										 |  |  | #include <mrw/checkcxx11.hxx>
 | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  | #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 | 
					
						
							| 
									
										
										
										
											2014-03-07 15:53:22 +00:00
										 |  |  |         <<"  (r)ead(b)erfile            Read selected BER file"<<std::endl | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |         <<"  (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 | 
					
						
							| 
									
										
										
										
											2018-03-19 10:02:29 +00:00
										 |  |  |         <<"  (g)et(p)in(l)engths        get PIN min max lengths"<<std::endl | 
					
						
							|  |  |  |         <<"  (c)hip                     get chip production data"<<std::endl | 
					
						
							|  |  |  |         <<"  (v)ersion                  get product data"<<std::endl | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |         <<"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()); | 
					
						
							| 
									
										
										
										
											2014-03-07 15:53:22 +00:00
										 |  |  |           else if (cmd=="readberfile"||cmd=="rb") _ber=readBerFile(); | 
					
						
							|  |  |  |           else if (cmd=="readbinfile"||cmd=="rbf") readBinary(); | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |           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; | 
					
						
							| 
									
										
										
										
											2018-03-19 10:02:29 +00:00
										 |  |  |           else if (cmd=="chip"||cmd=="c") printDataChipProduction(); | 
					
						
							|  |  |  |           else if (cmd=="version"||cmd=="v") std::cout<<getDataProductName()<<std::endl; | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |           else help(); | 
					
						
							|  |  |  |         } catch (const std::exception& e) { | 
					
						
							|  |  |  |           std::cout<<"**** Error: "<<e.what()<<std::endl; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |       return 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void listReader() { | 
					
						
							| 
									
										
										
										
											2014-03-26 15:07:54 +00:00
										 |  |  |       _readers = pcsc::Connection::scan(); | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |       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(); | 
					
						
							| 
									
										
										
										
											2014-04-01 13:10:51 +00:00
										 |  |  |       pcsc::Connection::Strings::size_type num(0); | 
					
						
							|  |  |  |       if (std::cin>>num && num<_readers.size()) { | 
					
						
							| 
									
										
										
										
											2014-03-26 15:07:54 +00:00
										 |  |  |         _reader = pcsc::Connection::reader(_readers[num]); | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |         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; | 
					
						
							| 
									
										
										
										
											2014-03-07 15:53:22 +00:00
										 |  |  |         cardos::BerValues record(cardos::Commands::retData(res).substr(2)); | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |         _ber += record; | 
					
						
							| 
									
										
										
										
											2014-03-07 15:53:22 +00:00
										 |  |  |         std::cout<<record[0][0][0].string() | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |                  <<": len=" | 
					
						
							| 
									
										
										
										
											2014-03-07 15:53:22 +00:00
										 |  |  |                  <<record[0][2][0][2].ulong() | 
					
						
							|  |  |  |                  <<"-"<<record[0][2][0][4].ulong()<<std::endl; | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |       } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2018-03-19 10:02:29 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  |     void printDataChipProduction() { | 
					
						
							|  |  |  |       ChipProductionData data=getDataChipProduction(); | 
					
						
							|  |  |  |       std::cout<<"serial: "<<crypto::hex(data.serial)<<std::endl | 
					
						
							|  |  |  |                <<"type: "<<crypto::hex(std::string(1, data.type))<<std::endl | 
					
						
							|  |  |  |                <<"id: "<<crypto::hex(data.id)<<std::endl; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-10-21 07:10:46 +00:00
										 |  |  |          | 
					
						
							|  |  |  |   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(); | 
					
						
							|  |  |  | } |