Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
O
ors-utils
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
ors-utils
Commits
f363bd12
Commit
f363bd12
authored
Mar 07, 2024
by
Thomas Gambier
🚴🏼
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Upgrade uicc to version 3.3
parent
80893308
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
1835 additions
and
1680 deletions
+1835
-1680
uicc/Makefile
uicc/Makefile
+5
-0
uicc/REAME.txt
uicc/REAME.txt
+37
-0
uicc/program_uicc.c
uicc/program_uicc.c
+765
-749
uicc/uicc.h
uicc/uicc.h
+1028
-931
No files found.
uicc/Makefile
View file @
f363bd12
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
uicc/REAME.txt
0 → 100644
View file @
f363bd12
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)
uicc/program_uicc.c
View file @
f363bd12
...
@@ -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
(
"
\n
Need the key (Ki) and the OPc to test Milenage and dispal
y the SQN
\n
"
);
printf
(
"
\n
Need the key (Ki) and the OPc to test Milenage and displa
y the SQN
\n
"
);
else
else
authenticate
(
portName
,
new_vals
);
authenticate
(
portName
,
new_vals
);
}
}
...
...
uicc/uicc.h
View file @
f363bd12
...
@@ -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
"
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment