From da028032e7134e846a529a8f60f74c1602d1919d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20W=C3=A4ckerlin?= Date: Fri, 7 Mar 2014 15:53:22 +0000 Subject: [PATCH] preparations for writing a file; refs #28 --- doc/examples/cardos-demo.cxx | 12 +-- doc/examples/makefile.am | 4 +- doc/examples/suisse-id-demo.cxx | 2 +- src/cardos.hxx | 154 +++++++++++++++++++++++--------- src/cryptaux.hxx | 19 ++++ src/suisseid.hxx | 14 +-- 6 files changed, 148 insertions(+), 57 deletions(-) diff --git a/doc/examples/cardos-demo.cxx b/doc/examples/cardos-demo.cxx index 15a6a05..49fca02 100644 --- a/doc/examples/cardos-demo.cxx +++ b/doc/examples/cardos-demo.cxx @@ -40,6 +40,7 @@ class Commands: public cardos::Commands { <<" (s)elect(f)ile Select file below master"< Select file below PKCS#15"< Select file below SigG"< sequence): + protected: // use BerValues instead + + friend class BerValues; + + BerValue(const std::vector& sequence): _tag(PRIVATE|CONSTRUCTED|SEQUENCE), - _length(0), _sequence(sequence) { } - BerValue(const std::string& content) { + BerValue(std::string& content) { if (content.size()<2) throw wrong_dataformat(content, "not a BER, header size too small: \"" +crypto::binToHex(content)+"\""); _tag = content[0]; - _length = content[1]; - _value = content.substr(2, _length); - if (std::string::size_type(_length)+2>content.size()) + unsigned char length = content[1]; + _value = content.substr(2, length); + if (content.size()& values): + _tag(tag), _sequence(values) { + } + unsigned char tagClass() { return _tag&0xC0; } @@ -213,21 +224,31 @@ namespace cardos { return _sequence[i]; } - std::string value() { + operator std::string() { + std::string res; + res.push_back(_tag); + if (isContainer()) { + for (std::vector::iterator it(_sequence.begin()); + it!=_sequence.end(); ++it) { + res += *it; + } + } else { + (res += (char)_value.size()) += _value; + } + return res; + } + + std::string string() { return _value; } - unsigned long toULong() { - unsigned long res(0); - for (std::string::reverse_iterator it(_value.rbegin()); - it!=_value.rend(); ++it) - (res<<=8)+=(unsigned)*it; - return res; + unsigned long ulong() { + return crypto::ulongFromBinary(_value); } std::string print(int indent=0, int indentStep = 4) { std::stringstream ss; - ss<print(indent+2, indentStep) < _sequence; @@ -309,13 +329,24 @@ namespace cardos { /// Store a sequence of BerValue class BerValues: public std::vector { public: - BerValues& operator=(const std::string& content) { + BerValues() {} + BerValues(const std::string& content) { + std::string contentCopy(content); + while (contentCopy.size()) push_back(BerValue(contentCopy)); + } + BerValues& operator=(std::string& content) { clear(); - push_back(BerValue(content)); + std::string contentCopy(content); + while (contentCopy.size()) push_back(BerValue(contentCopy)); + return *this; + } + BerValues& operator+=(const std::string& content) { + std::string contentCopy(content); + while (contentCopy.size()) push_back(BerValue(contentCopy)); return *this; } - BerValues& operator+=(const BerValue& value) { - push_back(value); + BerValues& operator+=(const BerValues& values) { + insert(end(), values.begin(), values.end()); return *this; } std::string print(int indent=0, int indentStep = 4) { @@ -327,7 +358,7 @@ namespace cardos { ss<<"{"<print(indent+2, indentStep) <>8, offset&0xFF)); } @@ -855,14 +915,15 @@ namespace cardos { } /// Read all records from a record oriented file - BerValues readBerFile() { + BerValues readBerFile(std::string path="") { CRYPTOLOG("log"); BerValues content; pcsc::Connection::Reader::Transaction lock(_reader); + if (path.size()) select(path); while (true) { std::string res(send(0x00, 0xB2, 0, NEXT_RECORD)); if (cardos::Commands::retCode(res)!=0x9000) break; - content += BerValue(retData(res).substr(2)); + content += retData(res).substr(2); } return content; } @@ -896,13 +957,13 @@ namespace cardos { }; //! Selects a file - BerValue selectFile(std::string file, + BerValues selectFile(std::string file, FileSelectionMode mode = DF_OR_EF_USING_PATH_FROM_MF, FileSelectionReturn ret = RETURN_NOTHING) { CRYPTOLOG("log"); - return BerValue(check(send(0x00, 0xA4, mode, ret, file))); + return BerValues(check(send(0x00, 0xA4, mode, ret, file))); } //! Sets the so-called Data_Field_Length parameter relevant for @@ -932,11 +993,12 @@ namespace cardos { assert(!"not implemented"); } - /// Read the previously file from smart card - std::string readBinFile() { - CRYPTOLOG("log"); - return check(send(0x00, 0xB0, 0x00, 0x00)); - } + // same as readBinary + // /// Read the previously file from smart card + // std::string readBinFile() { + // CRYPTOLOG("log"); + // return check(send(0x00, 0xB0, 0x00, 0x00)); + // } //! Updates a BINARY file void updateBinary(std::string data, unsigned short offset=0) { @@ -1123,6 +1185,12 @@ namespace cardos { check(send(0x00, 0xA4, 0x08, 0x0C, crypto::hexToBin("3f00"+file))); } + /// Generic select file + void select(std::string path) { + CRYPTOLOG("log"); + check(send(0x00, 0xA4, 0x08, 0x0C, crypto::hexToBin(path))); + } + /// Select the PKCS#15 part on the smart card void selectPkcs15() { CRYPTOLOG("log"); diff --git a/src/cryptaux.hxx b/src/cryptaux.hxx index 0209844..8421e3e 100644 --- a/src/cryptaux.hxx +++ b/src/cryptaux.hxx @@ -163,6 +163,25 @@ namespace crypto { } return res; } + + /// convert integer to binary of given size + inline std::string toBinary(unsigned long data, int bytes=2) { + std::string res(0, bytes); + for (int i(0); i>=8; + } + } + + /// convert integer from binary of given size + inline unsigned long ulongFromBinary(const std::string& data) { + unsigned long res(0); + for (std::string::const_reverse_iterator it(data.rbegin()); + it!=data.rend(); ++it) + (res<<=8)+=(unsigned)*it; + return res; + } + } //@} diff --git a/src/suisseid.hxx b/src/suisseid.hxx index afc4a33..4060ead 100644 --- a/src/suisseid.hxx +++ b/src/suisseid.hxx @@ -337,12 +337,12 @@ namespace suisseid { selectPkcs15File("4408"); cardos::BerValues res(readBerFile()); for (cardos::BerValues::iterator it(res.begin()); it!=res.end(); ++it) - if ((*it)[0][0].value()=="PIN" || - (*it)[0][0].value()=="Digital Signature PIN") { - if ((*it)[2][0][2].toULong()>_minPinLen) - _minPinLen = (*it)[2][0][2].toULong(); - if ((*it)[2][0][4].toULong()<_maxPinLen) - _maxPinLen = (*it)[2][0][4].toULong(); + if ((*it)[0][0].string()=="PIN" || + (*it)[0][0].string()=="Digital Signature PIN") { + if ((*it)[2][0][2].ulong()>_minPinLen) + _minPinLen = (*it)[2][0][2].ulong(); + if ((*it)[2][0][4].ulong()<_maxPinLen) + _maxPinLen = (*it)[2][0][4].ulong(); } } @@ -350,7 +350,7 @@ namespace suisseid { pcsc::Connection::Reader::Transaction lock(_reader); try { selectMfFile(file); - return _version = cardos::BerValue(readBinary())[0].value(); + return _version = cardos::BerValues(readBinary())[0].string(); } catch (...) { return _version = ""; }