|
|
@ -15,8 +15,12 @@ |
|
|
|
#include <stdexcept> |
|
|
|
#include <stdexcept> |
|
|
|
|
|
|
|
|
|
|
|
#ifndef CARDOS_LOG |
|
|
|
#ifndef CARDOS_LOG |
|
|
|
#define CARDOS_LOG(X) // no logging by default
|
|
|
|
# ifdef DEBUG_SECRETS |
|
|
|
|
|
|
|
# define CARDOS_LOG(X) std::clog<<X<<std::endl |
|
|
|
|
|
|
|
# else |
|
|
|
|
|
|
|
# define CARDOS_LOG(X) // no logging by default
|
|
|
|
// use e.g. #define CARDOS_LOG(X) std::clog<<X<<std::endl
|
|
|
|
// use e.g. #define CARDOS_LOG(X) std::clog<<X<<std::endl
|
|
|
|
|
|
|
|
# endif |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
/** @defgroup gcardos C++ Access to Siemens CardOS 4.4
|
|
|
|
/** @defgroup gcardos C++ Access to Siemens CardOS 4.4
|
|
|
@ -98,6 +102,13 @@ namespace cardos { |
|
|
|
} |
|
|
|
} |
|
|
|
}; |
|
|
|
}; |
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
class too_large_for_tlv: public wrong_dataformat { |
|
|
|
|
|
|
|
public: |
|
|
|
|
|
|
|
too_large_for_tlv(const std::string& data) throw(): |
|
|
|
|
|
|
|
wrong_dataformat(data, "data size too long for TLV") { |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
class array_range: public exception { |
|
|
|
class array_range: public exception { |
|
|
|
public: |
|
|
|
public: |
|
|
|
array_range(unsigned int i, unsigned int j) throw(): |
|
|
|
array_range(unsigned int i, unsigned int j) throw(): |
|
|
@ -193,6 +204,9 @@ namespace cardos { |
|
|
|
|
|
|
|
|
|
|
|
BerValue(unsigned char tag, const std::vector<BerValue>& values): |
|
|
|
BerValue(unsigned char tag, const std::vector<BerValue>& values): |
|
|
|
_tag(tag), _sequence(values) { |
|
|
|
_tag(tag), _sequence(values) { |
|
|
|
|
|
|
|
if (!isContainer()) |
|
|
|
|
|
|
|
throw runtime_error("BER tag 0x"+crypto::binToHex(tag) |
|
|
|
|
|
|
|
+" is not a container"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
unsigned char tagClass() { |
|
|
|
unsigned char tagClass() { |
|
|
@ -224,16 +238,22 @@ namespace cardos { |
|
|
|
return _sequence[i]; |
|
|
|
return _sequence[i]; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
operator std::string() { |
|
|
|
std::string binary() { |
|
|
|
std::string res; |
|
|
|
std::string res; |
|
|
|
res.push_back(_tag); |
|
|
|
res.push_back(_tag); |
|
|
|
if (isContainer()) { |
|
|
|
if (isContainer()) { |
|
|
|
|
|
|
|
std::string seq; |
|
|
|
for (std::vector<BerValue>::iterator it(_sequence.begin()); |
|
|
|
for (std::vector<BerValue>::iterator it(_sequence.begin()); |
|
|
|
it!=_sequence.end(); ++it) { |
|
|
|
it!=_sequence.end(); ++it) { |
|
|
|
res += *it; |
|
|
|
seq += it->binary(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (seq.size()>255) throw too_large_for_tlv(seq); |
|
|
|
|
|
|
|
res += (char)seq.size(); |
|
|
|
|
|
|
|
res += seq; |
|
|
|
} else { |
|
|
|
} else { |
|
|
|
(res += (char)_value.size()) += _value; |
|
|
|
if (_value.size()>255) throw too_large_for_tlv(_value); |
|
|
|
|
|
|
|
res += (char)_value.size(); |
|
|
|
|
|
|
|
res += _value; |
|
|
|
} |
|
|
|
} |
|
|
|
return res; |
|
|
|
return res; |
|
|
|
} |
|
|
|
} |
|
|
@ -345,10 +365,20 @@ namespace cardos { |
|
|
|
while (contentCopy.size()) push_back(BerValue(contentCopy)); |
|
|
|
while (contentCopy.size()) push_back(BerValue(contentCopy)); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
BerValues& operator+=(const BerValue& value) { |
|
|
|
|
|
|
|
push_back(value); |
|
|
|
|
|
|
|
return *this; |
|
|
|
|
|
|
|
} |
|
|
|
BerValues& operator+=(const BerValues& values) { |
|
|
|
BerValues& operator+=(const BerValues& values) { |
|
|
|
insert(end(), values.begin(), values.end()); |
|
|
|
insert(end(), values.begin(), values.end()); |
|
|
|
return *this; |
|
|
|
return *this; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
std::string binary() { |
|
|
|
|
|
|
|
std::string res; |
|
|
|
|
|
|
|
for (BerValues::iterator it(begin()); it!=end(); ++it) |
|
|
|
|
|
|
|
res += it->binary(); |
|
|
|
|
|
|
|
return res; |
|
|
|
|
|
|
|
} |
|
|
|
std::string print(int indent=0, int indentStep = 4) { |
|
|
|
std::string print(int indent=0, int indentStep = 4) { |
|
|
|
std::stringstream ss; |
|
|
|
std::stringstream ss; |
|
|
|
if (size()==1) { |
|
|
|
if (size()==1) { |
|
|
@ -639,10 +669,14 @@ namespace cardos { |
|
|
|
if (path.size()) select(path); |
|
|
|
if (path.size()) select(path); |
|
|
|
BerValues c; |
|
|
|
BerValues c; |
|
|
|
c += BerValue(0x80, crypto::toBinary(data.size())); |
|
|
|
c += BerValue(0x80, crypto::toBinary(data.size())); |
|
|
|
|
|
|
|
c += BerValue(0x82, crypto::hexToBin("01")); |
|
|
|
std::string idbin(crypto::hexToBin(id)); |
|
|
|
std::string idbin(crypto::hexToBin(id)); |
|
|
|
if (idbin.size()!=2) throw runtime_error("file id must be two bytes"); |
|
|
|
if (idbin.size()!=2) throw runtime_error("file id must be two bytes"); |
|
|
|
c += BerValue(0x83, idbin); |
|
|
|
c += BerValue(0x83, idbin); |
|
|
|
check(send(0x00, 0xE0, 0x00, 0x00, BerValue(82, c))); |
|
|
|
c += BerValue(0x85, std::string(1, (char)(1<<7))); |
|
|
|
|
|
|
|
c += BerValue(0x86, crypto::hexToBin("00000000000000")); |
|
|
|
|
|
|
|
check(send(0x00, 0xE0, 0x00, 0x00, BerValue(0x62, c).binary())); |
|
|
|
|
|
|
|
updateBinary(data); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//! Deactivates a file or a file tree
|
|
|
|
//! Deactivates a file or a file tree
|
|
|
@ -853,7 +887,7 @@ namespace cardos { |
|
|
|
|
|
|
|
|
|
|
|
//! Changes from life cycle phase ADMINISTRATION to OPERATIONAL
|
|
|
|
//! Changes from life cycle phase ADMINISTRATION to OPERATIONAL
|
|
|
|
//! and vice versa.
|
|
|
|
//! and vice versa.
|
|
|
|
/*! The command changes theglobal life cycle phase of the smart
|
|
|
|
/*! The command changes the global life cycle phase of the smart
|
|
|
|
card from ADMINISTRATION to OPERATIONAL. This change is |
|
|
|
card from ADMINISTRATION to OPERATIONAL. This change is |
|
|
|
permanently valid for all DFs and will be stored in EEPROM, |
|
|
|
permanently valid for all DFs and will be stored in EEPROM, |
|
|
|
i.e. this life cycle phase is still valid after a reset of |
|
|
|
i.e. this life cycle phase is still valid after a reset of |
|
|
@ -1187,7 +1221,7 @@ namespace cardos { |
|
|
|
|
|
|
|
|
|
|
|
/// Generic select file
|
|
|
|
/// Generic select file
|
|
|
|
void select(std::string path) { |
|
|
|
void select(std::string path) { |
|
|
|
CRYPTOLOG("log"); |
|
|
|
CRYPTOLOG("log: select "<<path); |
|
|
|
check(send(0x00, 0xA4, 0x08, 0x0C, crypto::hexToBin(path))); |
|
|
|
check(send(0x00, 0xA4, 0x08, 0x0C, crypto::hexToBin(path))); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|