added basic suisse id functions; refs #28
This commit is contained in:
		
							
								
								
									
										164
									
								
								doc/examples/cardos-demo.cxx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								doc/examples/cardos-demo.cxx
									
									
									
									
									
										Normal 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(); | ||||
| } | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user