Commit f363bd12 authored by Thomas Gambier's avatar Thomas Gambier 🚴🏼

Upgrade uicc to version 3.3

parent 80893308
program_uicc: program_uicc.c uicc.h milenage.h program_uicc: program_uicc.c uicc.h milenage.h
g++ --std=c++11 -g3 -I. -Wall program_uicc.c -o program_uicc g++ --std=c++11 -g3 -I. -Wall program_uicc.c -o program_uicc
program_uicc_pcsc: program_uicc.c uicc.h milenage.h
g++ --std=c++11 -g3 -DPCSC -I. -I/usr/include/PCSC -Wall program_uicc.c -L/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux -lccid -o program_uicc_pcsc
clean:
rm program_uicc program_uicc_pcsc
To compile
================
# make
For raw protocol reader
or
# make program_uicc_pcsc
For raw and pc/sc readers support
You may have to adapt Makefile to your directories for the libccid.so file and the PCSC include directory
The package, on debian style can be installed with
#apt install libccid
To use
===============
*** With raw reader, full options (set all values in the card)
# sudo program_uicc --port /dev/ttyUSB0 --adm 12345678 --iccid 89860061100000000123 --imsi 208920100001123 --isdn 00000$i --acc 0001 --key 6874736969202073796d4b2079650a73 --opc 504f20634f6320504f50206363500a4f -spn OpenCells --authenticate
*** If you use PC/SC reader
# apt install libpcsclite-dev
# LD_LIBRARY_PATH=/lib/pcsc/drivers/ifd-ccid.bundle/Contents/Linux ./program_uicc_pcsc --port usb:08e6/3437 --adm 12345678 --iccid 89860061100000000123 --imsi 208920100001123 --isdn 00000$i --acc 0001 --key 6874736969202073796d4b2079650a73 --opc 504f20634f6320504f50206363500a4f -spn OpenCells --authenticate
The library path may change on your linux distrbution
*** The port value setting is:
For raw readers
If you have no other serial, it should be /dev/ttyUSB0 (default). Else, the tty number will be in "dmesg" command result for example
For PC/SC readers
#lsusb
You will recognize your reader like:
Bus 001 Device 011: ID 08e6:3437 Gemalto (was Gemplus) GemPC Twin SmartCard Reader
The --port value for this example is usb:08e6/3437 (note the ":" is replaced by "/" in libccid)
...@@ -31,6 +31,7 @@ struct uicc_vals { ...@@ -31,6 +31,7 @@ struct uicc_vals {
string acc=""; string acc="";
string key=""; string key="";
string spn="open cells"; string spn="open cells";
string act="7c00";
string ust="866F1F1C231E0000400050"; string ust="866F1F1C231E0000400050";
int mncLen=2; int mncLen=2;
bool authenticate=false; bool authenticate=false;
...@@ -38,10 +39,6 @@ struct uicc_vals { ...@@ -38,10 +39,6 @@ struct uicc_vals {
string rand=""; string rand="";
}; };
#define sc(in, out) \
USIMcard.send_check( string( (char*)in +37 ,sizeof(in) -37), \
string( (char*)out+37 ,sizeof(out)-37) )
bool readSIMvalues(char *port) { bool readSIMvalues(char *port) {
SIM SIMcard; SIM SIMcard;
string ATR; string ATR;
...@@ -62,7 +59,11 @@ int readUSIMvalues(char *port) { ...@@ -62,7 +59,11 @@ int readUSIMvalues(char *port) {
Assert((ATR=USIMcard.open(port))!="", "Failed to open %s", port); Assert((ATR=USIMcard.open(port))!="", "Failed to open %s", port);
//dump_hex("ATR", ATR); //dump_hex("ATR", ATR);
res=USIMcard.readFile("ICCID"); res=USIMcard.readFile("ICCID");
string iccid=to_hex(res[0], true); string iccid="No iccid readable";
if (res.size() )
iccid=to_hex(res[0], true);
cout << "ICCID: " << iccid <<endl; cout << "ICCID: " << iccid <<endl;
if (!luhn( iccid)) if (!luhn( iccid))
...@@ -71,9 +72,22 @@ int readUSIMvalues(char *port) { ...@@ -71,9 +72,22 @@ int readUSIMvalues(char *port) {
USIMcard.openUSIM(); USIMcard.openUSIM();
string imsi=USIMcard.readFile("IMSI")[0]; string imsi=USIMcard.readFile("IMSI")[0];
cout << "USIM IMSI: " << USIMcard.decodeIMSI(imsi) << endl; cout << "USIM IMSI: " << USIMcard.decodeIMSI(imsi) << endl;
res=USIMcard.readFile("PLMN selector with Access Technology"); res=USIMcard.readFile("PLMN selector with Access Technology");
//cout << "USIM PLMN selector: " << bcdToAscii(res[0]) <<endl; auto last=res[0].find_last_not_of(string(u8"\xff",1));
// Show only the first isdn (might be several) if (last!=std::string::npos)
dump_hex("PLMN selector: ", res[0].substr(0,last));
res=USIMcard.readFile("Operator controlled PLMN selector with Access Technology");
last=res[0].find_last_not_of(string(u8"\xff",1));
if (last!=std::string::npos)
dump_hex("Operator Control PLMN selector: ", res[0].substr(0,last));
res=USIMcard.readFile("Home PLMN selector with Access Technology");
last=res[0].find_last_not_of(string(u8"\xff",1));
if (last!=std::string::npos)
dump_hex("Home PLMN selector: ", res[0].substr(0,last));
string msisdn=USIMcard.readFile("MSISDN")[0]; string msisdn=USIMcard.readFile("MSISDN")[0];
cout << "USIM MSISDN: " << USIMcard.decodeISDN(msisdn) <<endl; cout << "USIM MSISDN: " << USIMcard.decodeISDN(msisdn) <<endl;
string spn=USIMcard.readFile("Service Provider Name")[0]; string spn=USIMcard.readFile("Service Provider Name")[0];
...@@ -213,9 +227,6 @@ bool writeSIMv2values(char *port, struct uicc_vals &values) { ...@@ -213,9 +227,6 @@ bool writeSIMv2values(char *port, struct uicc_vals &values) {
card.encodeISDN("9" + values.isdn, card.fileRecordSize("MSISDN"))), card.encodeISDN("9" + values.isdn, card.fileRecordSize("MSISDN"))),
"can't set msisdn %s",values.isdn.c_str()); "can't set msisdn %s",values.isdn.c_str());
Assert(card.writeFile("SMSC",
makeBcdVect("FFFFFFFFFFFFFFFFFFFFFFFFFFF1FFFFFFFFFFFFFFFFFFFFFFFF0191"),true),
"can't set SMS center");
// //
// Set USIM values, from GSM APDU CLA, proprietary method but regular file names // Set USIM values, from GSM APDU CLA, proprietary method but regular file names
// //
...@@ -241,8 +252,7 @@ bool writeSIMv2values(char *port, struct uicc_vals &values) { ...@@ -241,8 +252,7 @@ bool writeSIMv2values(char *port, struct uicc_vals &values) {
vector<string> VectMccMnc; vector<string> VectMccMnc;
VectMccMnc.push_back(MccMnc); VectMccMnc.push_back(MccMnc);
vector<string> MccMncWithAct=VectMccMnc; vector<string> MccMncWithAct=VectMccMnc;
// Add EUTRAN access techno only MccMncWithAct[0]+=makeBcd(values.act,false,2);
MccMncWithAct[0]+=string(u8"\x40\x00",2);
Assert(card.writeFile("USIM PLMN selector with Access Technology", Assert(card.writeFile("USIM PLMN selector with Access Technology",
MccMncWithAct, true), "Can't write PLMN Selector"); MccMncWithAct, true), "Can't write PLMN Selector");
Assert(card.writeFile("USIM Operator controlled PLMN selector with Access Technology", Assert(card.writeFile("USIM Operator controlled PLMN selector with Access Technology",
...@@ -372,7 +382,8 @@ bool writeSIMvalues(char *port, struct uicc_vals &values) { ...@@ -372,7 +382,8 @@ bool writeSIMvalues(char *port, struct uicc_vals &values) {
card.encodeISDN(values.isdn, card.fileRecordSize("MSISDN"))), card.encodeISDN(values.isdn, card.fileRecordSize("MSISDN"))),
"can't set msisdn %s",values.isdn.c_str()); "can't set msisdn %s",values.isdn.c_str());
Assert(card.writeFile("SMSC", makeBcdVect(""),true), "can't set SMS center"); Assert(card.writeFile("Short Message Service Parameters", makeBcdVect("FFFFFFFFFFFFFFFFFFFFFFFFFFF1FFFFFFFFFFFFFFFFFFFFFFFF 0191",true,40)),
"can't set SMSC");
return true; return true;
} }
...@@ -417,7 +428,7 @@ bool writeUSIMvalues(char *port, struct uicc_vals &values) { ...@@ -417,7 +428,7 @@ bool writeUSIMvalues(char *port, struct uicc_vals &values) {
ad[0]+=(char) values.mncLen; ad[0]+=(char) values.mncLen;
Assert(card.writeFile("Administrative data", ad), Assert(card.writeFile("Administrative data", ad),
"can't set Administrative data"); "can't set Administrative data");
Assert(card.writeFile("SMSC", makeBcdVect("",true,40)), Assert(card.writeFile("Short Message Service Parameters", makeBcdVect("FFFFFFFFFFFFFFFFFFFFFFFFFFF1FFFFFFFFFFFFFFFFFFFFFFFF 0191",true,40)),
"can't set SMSC"); "can't set SMSC");
if (values.isdn.size() > 0) if (values.isdn.size() > 0)
...@@ -436,8 +447,7 @@ bool writeUSIMvalues(char *port, struct uicc_vals &values) { ...@@ -436,8 +447,7 @@ bool writeUSIMvalues(char *port, struct uicc_vals &values) {
vector<string> VectMccMnc; vector<string> VectMccMnc;
VectMccMnc.push_back(MccMnc); VectMccMnc.push_back(MccMnc);
vector<string> MccMncWithAct=VectMccMnc; vector<string> MccMncWithAct=VectMccMnc;
// Add EUTRAN access techno only MccMncWithAct[0]+=makeBcd(values.act,false,2);
MccMncWithAct[0]+=string(u8"\x40\x00",2);
Assert(card.writeFile("PLMN selector with Access Technology", Assert(card.writeFile("PLMN selector with Access Technology",
MccMncWithAct, true), "Can't write PLMN Selector"); MccMncWithAct, true), "Can't write PLMN Selector");
Assert(card.writeFile("Operator controlled PLMN selector with Access Technology", Assert(card.writeFile("Operator controlled PLMN selector with Access Technology",
...@@ -658,10 +668,11 @@ int main(int argc, char **argv) { ...@@ -658,10 +668,11 @@ int main(int argc, char **argv) {
{"xx", required_argument, 0, 9}, {"xx", required_argument, 0, 9},
{"authenticate", no_argument, 0, 10}, {"authenticate", no_argument, 0, 10},
{"spn", required_argument, 0, 11}, {"spn", required_argument, 0, 11},
{"noreadafter", no_argument, 0, 12}, {"act", required_argument, 0, 12},
{"ust", required_argument, 0, 13}, {"noreadafter", no_argument, 0, 13},
{"sqn", required_argument, 0, 14}, {"ust", required_argument, 0, 14},
{"rand", required_argument, 0, 15}, {"sqn", required_argument, 0, 15},
{"rand", required_argument, 0, 16},
{0, 0, 0, 0} {0, 0, 0, 0}
}; };
static map<string,string> help_text= { static map<string,string> help_text= {
...@@ -673,12 +684,13 @@ int main(int argc, char **argv) { ...@@ -673,12 +684,13 @@ int main(int argc, char **argv) {
{"isdn", "The mobile phone number (not used in simple 4G)"}, {"isdn", "The mobile phone number (not used in simple 4G)"},
{"acc", "One of the defined security codes"}, {"acc", "One of the defined security codes"},
{"key", "The authentication key (called Ki in 3G/4G, Kc in GSM), must be the same in HSS"}, {"key", "The authentication key (called Ki in 3G/4G, Kc in GSM), must be the same in HSS"},
{"MNCsize","Mobile network code size in digits (default to 2)"}, {"MNCsize","Mobile network code size in digits (default 2)"},
{"xx", "OP field: OPerator code: must be also set in HSS (exclusive with OPc)"}, {"xx", "OP field: OPerator code: must be also set in HSS (exclusive with OPc)"},
{"spn", "service provider name: the name that the UE will show as 'network'"}, {"spn", "service provider name: the name that the UE will show as 'network' (default \"open cells\")"},
{"act", "bitmap describing supported RAN technologies (default \"7c00\" see TS31.102 chap 4.2.5)"},
{"authenticate", "Test the milenage authentication and discover the current sequence number"}, {"authenticate", "Test the milenage authentication and discover the current sequence number"},
{"noreadafter", "no read after write"}, {"noreadafter", "no read after write"},
{"ust", "usim service table in hexa decimal (first byte is services 1-8, so 81 enable service 1 and service 8 ...)"}, {"ust", "usim service table in hexa decimal (first byte is services 1-8,\n so 81 enable service 1 and service 8 ...)"},
{"sqn", "only for test, no UICC dialog, prints the generated AUTN for debugging"}, {"sqn", "only for test, no UICC dialog, prints the generated AUTN for debugging"},
{"rand", "only for test, no UICC dialog, prints the generated AUTN for debugging"}, {"rand", "only for test, no UICC dialog, prints the generated AUTN for debugging"},
}; };
...@@ -745,18 +757,22 @@ int main(int argc, char **argv) { ...@@ -745,18 +757,22 @@ int main(int argc, char **argv) {
break; break;
case 12: case 12:
readAfter=false; new_vals.act=optarg;
break; break;
case 13: case 13:
new_vals.ust=optarg; readAfter=false;
break; break;
case 14: case 14:
new_vals.sqn=optarg; new_vals.ust=optarg;
break; break;
case 15: case 15:
new_vals.sqn=optarg;
break;
case 16:
new_vals.rand=optarg; new_vals.rand=optarg;
break; break;
...@@ -827,7 +843,7 @@ int main(int argc, char **argv) { ...@@ -827,7 +843,7 @@ int main(int argc, char **argv) {
if ( new_vals.authenticate) { if ( new_vals.authenticate) {
if ( new_vals.opc.size() == 0 || new_vals.key.size() == 0) if ( new_vals.opc.size() == 0 || new_vals.key.size() == 0)
printf("\nNeed the key (Ki) and the OPc to test Milenage and dispaly the SQN\n"); printf("\nNeed the key (Ki) and the OPc to test Milenage and display the SQN\n");
else else
authenticate(portName, new_vals); authenticate(portName, new_vals);
} }
......
...@@ -39,7 +39,24 @@ ...@@ -39,7 +39,24 @@
#include <numeric> #include <numeric>
#include <string> #include <string>
#include <sstream> #include <sstream>
#ifdef PCSC
extern "C" {
#include "PCSC/ifdhandler.h"
void log_msg(const int priority, const char *fmt, ...) {
(void)priority;
(void)fmt;
}
void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
const int len) {
(void)priority;
(void)msg;
(void)buffer;
(void)len;
}
}
#endif
using namespace std; using namespace std;
/* /*
Copyright: Open cells company Copyright: Open cells company
...@@ -91,7 +108,7 @@ using namespace std; ...@@ -91,7 +108,7 @@ using namespace std;
__FUNCTION__, __FILE__, __LINE__, strerror(errno), ##aRGS); \ __FUNCTION__, __FILE__, __LINE__, strerror(errno), ##aRGS); \
fflush(stdout); \ fflush(stdout); \
fflush(stderr); \ fflush(stderr); \
exit(EXIT_FAILURE); \ abort(); \
} \ } \
} while(0) } while(0)
...@@ -218,9 +235,10 @@ static inline bool luhn( const string &id) { ...@@ -218,9 +235,10 @@ static inline bool luhn( const string &id) {
int s = std::accumulate(id.rbegin(), id.rend(), 0, lambda); int s = std::accumulate(id.rbegin(), id.rend(), 0, lambda);
return 0 == s%10; return 0 == s%10;
} }
bool pcscOpen=false;
class UICC { class UICC {
public: public:
UICC() { UICC() {
char *debug_env=getenv("DEBUG"); char *debug_env=getenv("DEBUG");
...@@ -350,6 +368,50 @@ class UICC { ...@@ -350,6 +368,50 @@ class UICC {
// Returns the ATR (answer to reset) string // Returns the ATR (answer to reset) string
string open(char *portname) { string open(char *portname) {
#ifdef PCSC
RESPONSECODE res;
if (strncmp(portname, "usb:",4) == 0) {
if (!pcscOpen) {
res=IFDHCreateChannelByName(0, portname);
if (res!=0) {
printf("reader not detected\n");
return "";
}
pcscOpen=true;
}
res=IFDHICCPresence(0);
switch (res) {
case IFD_ICC_PRESENT:
printf("found card in the reader\n");
break;
case IFD_ICC_NOT_PRESENT:
printf("no card found card in the reader\n");
break;
default:
printf("bad answer from detect card in the reader\n");
break;
}
unsigned char atr[MAX_ATR_SIZE];
size_t atrSz=0;
res=IFDHPowerICC(0,IFD_RESET,atr, &atrSz);
if (res!=0) {
printf("error powering up the card\n");
return "";
}
ATR.assign((const char *)atr, atrSz);
} else
#endif
{
Assert( (fd=::open(portname, O_RDWR | O_NOCTTY | O_SYNC)) >=0, Assert( (fd=::open(portname, O_RDWR | O_NOCTTY | O_SYNC)) >=0,
"Failed to open %s", portname); "Failed to open %s", portname);
struct termios tty; struct termios tty;
...@@ -378,6 +440,8 @@ class UICC { ...@@ -378,6 +440,8 @@ class UICC {
//iFlags = TIOCM_CTS ; //iFlags = TIOCM_CTS ;
//ioctl(fd, TIOCMSET, &iFlags); //ioctl(fd, TIOCMSET, &iFlags);
ATR=this->read(200,3); ATR=this->read(200,3);
}
this->init(); this->init();
return ATR; return ATR;
} }
...@@ -416,9 +480,34 @@ class UICC { ...@@ -416,9 +480,34 @@ class UICC {
fd=-1; fd=-1;
} }
bool send_check( string in, string out, int timeout = 1) { string send_noCheck(string in, int responseSize, int timeout = 1) {
string answer="";
#ifdef PCSC
if (fd == -1) {
unsigned char rx[1024];
size_t rxSz=sizeof(rx);
SCARD_IO_HEADER recv= {0};
RESPONSECODE res=IFDHTransmitToICC(0, recv, (unsigned char *)in.c_str(), in.size(), rx, &rxSz,&recv);
if (res != 0) {
printf("send with iccid driver error\n");
return answer;
}
answer.assign((const char *)rx, rxSz);
} else
#endif
{
Assert( write(in) == (int)in.size(), ""); Assert( write(in) == (int)in.size(), "");
string answer=read(out.size(), timeout); answer=read( responseSize, timeout);
}
return answer;
}
bool send_check( string in, string out, int timeout = 1) {
string answer=send_noCheck(in, out.size(), timeout);
if (answer.size() != out.size()) { if (answer.size() != out.size()) {
printf("ret is not right size\n"); printf("ret is not right size\n");
...@@ -501,6 +590,8 @@ class UICC { ...@@ -501,6 +590,8 @@ class UICC {
} }
string decodeISDN(string raw) { string decodeISDN(string raw) {
// ISDN is in last 14 bytes // ISDN is in last 14 bytes
if (raw.size() < 14)
return "Invalid ISDN";
string isdn=raw.substr(raw.size()-14); string isdn=raw.substr(raw.size()-14);
char isdnLength=isdn[0]-1; char isdnLength=isdn[0]-1;
//char TON=isdn[1]; // should be 0x81 //char TON=isdn[1]; // should be 0x81
...@@ -525,16 +616,36 @@ class UICC { ...@@ -525,16 +616,36 @@ class UICC {
} }
string decodeIMSI(string raw) { string decodeIMSI(string raw) {
//int l=raw.c_str()[0]; //int l=raw.c_str()[0];
string imsi=to_hex(raw.substr(1),true); // First byte is length string imsi;
if (raw.size() > 1)
imsi=to_hex(raw.substr(1),true); // First byte is length
else
return "Invalid read";
//IMSI length bytes, then parity is second byte //IMSI length bytes, then parity is second byte
return imsi.substr(1); return imsi.substr(1);
} }
string encodeMccMnc(string Mcc, string Mnc, int len=0) {
string out; string encodeMccMnc(string Mcc, string Mnc) {
out=makeBcd(Mcc); string plmn;
out+=makeBcd(Mnc, true, len>2?len-2:0);
return out; if (Mnc.size() == 2) {
plmn.insert(0, 1, Mcc[1]);
plmn.insert(1, 1, Mcc[0]);
plmn.insert(2, 1, 'f');
plmn.insert(3, 1, Mcc[2]);
plmn.insert(4, 1, Mnc[1]);
plmn.insert(5, 1, Mnc[0]);
} else {
plmn.insert(0, 1, Mcc[1]);
plmn.insert(1, 1, Mcc[0]);
plmn.insert(2, 1, Mnc[2]);
plmn.insert(3, 1, Mcc[2]);
plmn.insert(4, 1, Mnc[1]);
plmn.insert(5, 1, Mnc[0]);
} }
return makeBcd(plmn, false, 2);
}
vector<string> encodeIMSI(string imsi) { vector<string> encodeIMSI(string imsi) {
vector<string> encoded; vector<string> encoded;
encoded.push_back(""); encoded.push_back("");
...@@ -577,15 +688,15 @@ class UICC { ...@@ -577,15 +688,15 @@ class UICC {
} }
bool debug=false; bool debug=false;
int GRver=1; int GRver=1;
protected: protected:
string ATR=""; string ATR="";
int fd=-1; int fd=-1;
private: private:
int lastTimeout=0; int lastTimeout=0;
}; };
class SIM: public UICC { class SIM: public UICC {
public: public:
typedef struct fileChar_s { typedef struct fileChar_s {
uint16_t rfu; uint16_t rfu;
...@@ -626,7 +737,7 @@ class SIM: public UICC { ...@@ -626,7 +737,7 @@ class SIM: public UICC {
{"Phase identification", string(u8"\x7f\x20\x6f\xae",4)}, {"Phase identification", string(u8"\x7f\x20\x6f\xae",4)},
{"HPLMN Selector with Access Technology", string(u8"\x7f\x20\x6f\x62",4)}, {"HPLMN Selector with Access Technology", string(u8"\x7f\x20\x6f\x62",4)},
{"MSISDN", string(u8"\x7f\x10\x6f\x40",4)}, {"MSISDN", string(u8"\x7f\x10\x6f\x40",4)},
{"SMSC", string(u8"\x7f\x10\x6f\x42",4)}, {"Short Message Service Parameters", string(u8"\x7f\x10\x6f\x42",4)},
{"GR OPc", string(u8"\x7f\xf0\xff\x01",4)}, {"GR OPc", string(u8"\x7f\xf0\xff\x01",4)},
{"GR Ki", string(u8"\x7f\xf0\xff\x02",4)}, {"GR Ki", string(u8"\x7f\xf0\xff\x02",4)},
{"GR R", string(u8"\x7f\xf0\xff\x03",4)}, {"GR R", string(u8"\x7f\xf0\xff\x03",4)},
...@@ -674,12 +785,11 @@ class SIM: public UICC { ...@@ -674,12 +785,11 @@ class SIM: public UICC {
} }
} }
public: public:
bool readFileInfo() { bool readFileInfo() {
string order(u8"\xa0\xc0\x00\x00\x0f",5); string order(u8"\xa0\xc0\x00\x00\x0f",5);
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
write(order); string values=send_noCheck(order, 17);
string values=read(17);
memcpy(&curFile,values.c_str(), memcpy(&curFile,values.c_str(),
min(values.size(),sizeof(curFile)) ); min(values.size(),sizeof(curFile)) );
...@@ -751,8 +861,7 @@ class SIM: public UICC { ...@@ -751,8 +861,7 @@ class SIM: public UICC {
string good=hexa("9000"); string good=hexa("9000");
char s=size&0xFF; char s=size&0xFF;
command+=string(&s,1); command+=string(&s,1);
write(command); string answ=send_noCheck(command, size+good.size());
string answ=read(size+good.size());
if ( answ.size()==(size_t)size+2 && if ( answ.size()==(size_t)size+2 &&
answ.substr(answ.size()-2) == good ) answ.substr(answ.size()-2) == good )
...@@ -764,14 +873,14 @@ class SIM: public UICC { ...@@ -764,14 +873,14 @@ class SIM: public UICC {
string command(u8"\xa0\xb2\x00\x02",4); string command(u8"\xa0\xb2\x00\x02",4);
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
command+=string((char *)&curFile.record_length,1); command+=string((char *)&curFile.record_length,1);
write(command); string answ=send_noCheck(command, size+good.size());
string answ=read(size+good.size());
if ( answ.size()==(size_t)curFile.record_length+good.size() && if ( answ.size()==(size_t)curFile.record_length+good.size() &&
answ.substr(answ.size()-2) == good ) answ.substr(answ.size()-2) == good )
content.push_back(answ.substr(0,answ.size()-good.size())); content.push_back(answ.substr(0,answ.size()-good.size()));
} }
if (content.size() == 0)
content.push_back("Error");
return content; return content;
} }
} }
...@@ -803,8 +912,7 @@ class SIM: public UICC { ...@@ -803,8 +912,7 @@ class SIM: public UICC {
command+=sizeToWrite; command+=sizeToWrite;
command+=fileContent.substr(wroteBytes, sizeToWrite); command+=fileContent.substr(wroteBytes, sizeToWrite);
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
write(command); string answ=send_noCheck(command, good.size());
string answ=read(good.size());
if (answ != good) { if (answ != good) {
printf("Write in file: %s failed\n", filename.c_str()); printf("Write in file: %s failed\n", filename.c_str());
...@@ -827,8 +935,7 @@ class SIM: public UICC { ...@@ -827,8 +935,7 @@ class SIM: public UICC {
for (int j=content[i].size(); j< curFile.record_length ; j++) for (int j=content[i].size(); j< curFile.record_length ; j++)
command+=u8"\xff"; command+=u8"\xff";
write(command); string answ=send_noCheck(command, good.size());
string answ=read(good.size());
if ( answ != good ) if ( answ != good )
return false; return false;
...@@ -1016,14 +1123,14 @@ void decodeServiceTable(string ST) { ...@@ -1016,14 +1123,14 @@ void decodeServiceTable(string ST) {
} }
class USIM: public UICC { class USIM: public UICC {
private: private:
string UICCFile(string name) { string UICCFile(string name) {
static const map<string,string> UICCFiles = { static const map<string,string> UICCFiles = {
{"EFDIR", string(u8"\x2f\x00",2)}, {"EFDIR", string(u8"\x2f\x00",2)},
{"ICCID", string(u8"\x2f\xe2",2)}, {"ICCID", string(u8"\x2f\xe2",2)},
{"Maximum Power Consumption", string(u8"\x2f\x08",2)}, //Not available in present cards
{"Extended language preference", string(u8"\x2f\x05",2)}, {"Extended language preference", string(u8"\x2f\x05",2)},
{"language preference", string(u8"\x7f\x20\x6f\x05",4)}, {"language preference", string(u8"\x7f\x20\x6f\x05",4)},
{"SMSC", string(u8"\x7f\x10\x6f\x42",4)},
{"IMSI", string(u8"\x7f\xf0\x6f\x07",4)}, {"IMSI", string(u8"\x7f\xf0\x6f\x07",4)},
{"Access control class", string(u8"\x7f\xf0\x6f\x78",4)}, {"Access control class", string(u8"\x7f\xf0\x6f\x78",4)},
{"PS Location information", string(u8"\x7f\xf0\x6f\x73",4)}, {"PS Location information", string(u8"\x7f\xf0\x6f\x73",4)},
...@@ -1065,13 +1172,12 @@ class USIM: public UICC { ...@@ -1065,13 +1172,12 @@ class USIM: public UICC {
string fileDesc; string fileDesc;
int fileSize; int fileSize;
public: public:
bool readFileInfo(string size) { bool readFileInfo(string size) {
string order(u8"\x00\xc0\x00\x00",4); string order(u8"\x00\xc0\x00\x00",4);
order+=size; order+=size;
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
write(order); string values=send_noCheck(order, size[0] +good.size());
string values=read(size[0] +good.size());
if ( values[0] != '\x62' || values.substr(values.size()-2) != good) if ( values[0] != '\x62' || values.substr(values.size()-2) != good)
return false; return false;
...@@ -1089,17 +1195,13 @@ class USIM: public UICC { ...@@ -1089,17 +1195,13 @@ class USIM: public UICC {
bool openFile(string filename) { bool openFile(string filename) {
string order(u8"\x00\xa4\x08\x04",4); string order(u8"\x00\xa4\x08\x04",4);
string answer(u8"\x61",1);
string filenameBin=UICCFile(filename); string filenameBin=UICCFile(filename);
string answer=send_noCheck(order+(char)(filenameBin.size())+filenameBin, 2, 1);
if (! send_check(order+(char)(filenameBin.size())+filenameBin, answer)) if (answer.size() != 2 || answer[0] != '\x61')
return false;
string size=read(1);
if (size.size() !=1)
return false; return false;
string size=answer.substr(1,1);
return readFileInfo(size); return readFileInfo(size);
} }
...@@ -1130,8 +1232,7 @@ class USIM: public UICC { ...@@ -1130,8 +1232,7 @@ class USIM: public UICC {
command+=string((char *)&P1,1); command+=string((char *)&P1,1);
command+=string((char *)&P2,1); command+=string((char *)&P2,1);
command+=string((char *)&s,1); command+=string((char *)&s,1);
write(command); string answ=send_noCheck(command,s+2);
string answ=read(s+2);
if ( answ.size()==(size_t)s+good.size() && if ( answ.size()==(size_t)s+good.size() &&
answ.substr(answ.size()-good.size()) == good ) answ.substr(answ.size()-good.size()) == good )
...@@ -1158,8 +1259,7 @@ class USIM: public UICC { ...@@ -1158,8 +1259,7 @@ class USIM: public UICC {
command+=(unsigned char) 4; command+=(unsigned char) 4;
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
command+=fileDesc.substr(3,1); command+=fileDesc.substr(3,1);
write(command); string answ=send_noCheck(command,(unsigned char)fileDesc[3]+2);
string answ=read( (unsigned char)fileDesc[3]+2);
if ( answ.size()== ((unsigned char)fileDesc[3]+good.size()) && if ( answ.size()== ((unsigned char)fileDesc[3]+good.size()) &&
answ.substr(answ.size()-good.size()) == good ) answ.substr(answ.size()-good.size()) == good )
...@@ -1195,8 +1295,7 @@ class USIM: public UICC { ...@@ -1195,8 +1295,7 @@ class USIM: public UICC {
j++) j++)
command+=u8"\xff"; command+=u8"\xff";
write(command); string answ=send_noCheck(command, good.size());
string answ=read(good.size());
if (answ == good) if (answ == good)
return true; return true;
...@@ -1216,8 +1315,7 @@ class USIM: public UICC { ...@@ -1216,8 +1315,7 @@ class USIM: public UICC {
j++) j++)
command+=u8"\xff"; command+=u8"\xff";
write(command); string answ=send_noCheck(command, good.size());
string answ=read(good.size());
if ( answ != good ) if ( answ != good )
return false; return false;
...@@ -1274,27 +1372,26 @@ class USIM: public UICC { ...@@ -1274,27 +1372,26 @@ class USIM: public UICC {
order+=autn; order+=autn;
string answerKeys(u8"\x61",1); string answerKeys(u8"\x61",1);
string answerAUTS(u8"\x9f",1); string answerAUTS(u8"\x9f",1);
Assert(write(order)==(int)order.size(),"");
// Cards need CPU procesing, so delay to check Milenage // Cards need CPU procesing, so delay to check Milenage
usleep(100); string answer=send_noCheck(order, 2, 100);
string answer=read(1);
string size=read(1);
if ( answer != answerKeys && answer != answerAUTS) { if (answer.size() < 2) {
printf("Not possible answer to milenage challenge: %x, %02x\n", answer[0], size[0]); printf("Not answer to milenage challenge\n");
//return ret; return ret;
} }
if (size.size() !=1) { string res=answer.substr(0,1);
printf("No answer to mileange challenge\n"); string size=answer.substr(1,1);
return ret;
if ( res != answerKeys && res != answerAUTS) {
printf("Not possible answer to milenage challenge: %x, %02x\n", res[0], size[1]);
//return ret;
} }
string getData(u8"\x00\xc0\x00\x00",4); string getData(u8"\x00\xc0\x00\x00",4);
getData+=size; getData+=size;
string good(u8"\x90\x00",2); string good(u8"\x90\x00",2);
write(getData); string values=send_noCheck(getData,answer[1] + good.size(),100);
string values=read(size[0] + good.size(),100);
if ( values.substr(values.size()-2) != good) { if ( values.substr(values.size()-2) != good) {
printf("Can't get APDU in return of millenage challenge\n"); printf("Can't get APDU in return of millenage challenge\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment