forked from sim-card/pysim
142 lines
4.1 KiB
Python
Executable File
142 lines
4.1 KiB
Python
Executable File
#!/usr/bin/python3
|
|
|
|
from pySim.transport.pcsc import PcscSimLink
|
|
from pySim.utils import enc_iccid, enc_imsi
|
|
|
|
from smartcard.Exceptions import NoCardException, CardRequestTimeoutException
|
|
from smartcard.System import readers
|
|
|
|
from lark import Lark, Transformer, Token, Tree
|
|
import sys
|
|
|
|
from format_ipr import ScriptFormatIPR
|
|
|
|
class DataTransform():
|
|
''' Transform raw/logical input data into the format use on the SIM card,
|
|
like encoding the PIN from '1234' -> 3132334 or IMSI encoding'''
|
|
def transform(self, inp):
|
|
outp = {}
|
|
for k in inp.keys():
|
|
f = getattr(self, 'xfrm_'+k, None)
|
|
if f != None:
|
|
outp[k] = f(inp[k])
|
|
else:
|
|
outp[k] = inp[k]
|
|
return outp
|
|
|
|
def xfrm_PIN(self, pin):
|
|
ret = ''
|
|
for c in str(pin):
|
|
ret += '3%c' % c
|
|
return ret
|
|
def xfrm_PIN1(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_PIN2(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_PUK1(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_PUK2(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_ADM1(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_ADM2(self, pin):
|
|
return self.xfrm_PIN(pin)
|
|
def xfrm_IMSI(self, imsi):
|
|
return enc_imsi(imsi)
|
|
def xfrm_ICCID(self, iccid):
|
|
# TODO: calculate luhn check digit
|
|
return enc_iccid(iccid)
|
|
|
|
|
|
def expand_cmd_template(cmd, templates):
|
|
''' Take a single command, supstituting all [] template keys with data from 'template' '''
|
|
ret = ""
|
|
for e in cmd:
|
|
if e[0] == 'hexstr':
|
|
ret += e[1]
|
|
if e[0] == 'key':
|
|
ret += templates[e[1]]
|
|
return ret
|
|
|
|
def match_sw(actual_sw, sw_match):
|
|
''' Check if actual_sw matches any of the templates given in sw_match'''
|
|
def match_sw_single(actual_sw, match):
|
|
match = match.lower()
|
|
if 'x' in match:
|
|
FIXME
|
|
else:
|
|
if actual_sw.lower() == match:
|
|
return True
|
|
return False
|
|
|
|
if sw_match == []:
|
|
return True
|
|
|
|
for m in sw_match:
|
|
if match_sw_single(actual_sw, m):
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def execute_ipr_raw(s, sl, dynamic_data_raw = {}):
|
|
""" translate a single LDR statement to IPR format. """
|
|
if s == None:
|
|
None
|
|
elif s == 'reset':
|
|
print("RESET")
|
|
sl.reset_card()
|
|
elif s[0] == 'rem':
|
|
print("REM %s" % (s[1]))
|
|
elif s[0] == 'cmd':
|
|
d = s[1]
|
|
req = expand_cmd_template(d['req'], dynamic_data_raw)
|
|
rsp = d['rsp']
|
|
print("\tREQ: %s, EXP: %s" % (req, rsp))
|
|
(data, sw) = sl.send_apdu_raw(req)
|
|
if not match_sw(sw, rsp):
|
|
raise ValueError("SW %s doesn't match expected %s" % (sw, rsp))
|
|
print("\tRSP: %s\n" % (sw))
|
|
|
|
def execute_ipr(s, sl, dynamic_data = {}):
|
|
""" translate a single LDR statement to IPR format; optionally substitute dynamic_data. """
|
|
xf = DataTransform()
|
|
return execute_ipr_raw(s, sl, xf.transform(dynamic_data))
|
|
|
|
|
|
'''Dictionaries like this must be generated for each card to be programmed'''
|
|
demo_dict = {
|
|
'PIN1': '1234',
|
|
'PIN2': '1234',
|
|
'PUK1': '12345678',
|
|
'PUK2': '12345678',
|
|
'ADM1': '11111111',
|
|
|
|
'KIC1': '100102030405060708090a0b0c0d0e0f',
|
|
'KID1': '101102030405060708090a0b0c0d0e0f',
|
|
'KIK1': '102102030405060708090a0b0c0d0e0f',
|
|
|
|
'KIC2': '200102030405060708090a0b0c0d0e0f',
|
|
'KID2': '201102030405060708090a0b0c0d0e0f',
|
|
'KIK2': '202102030405060708090a0b0c0d0e0f',
|
|
|
|
'KIC3': '300102030405060708090a0b0c0d0e0f',
|
|
'KID3': '301102030405060708090a0b0c0d0e0f',
|
|
'KIK3': '302102030405060708090a0b0c0d0e0f',
|
|
|
|
'ICCID': '012345678901234567',
|
|
'IMSI': '001010123456789',
|
|
'ACC': '0200',
|
|
'KI': '000102030405060708090a0b0c0d0e0f',
|
|
'OPC': '101112131415161718191a1b1c1d1e1f',
|
|
'VERIFY_ICCID': '0001020304050608090a0b0c0d0e0f',
|
|
}
|
|
|
|
|
|
sl = PcscSimLink(0)
|
|
|
|
infile_name = sys.argv[1]
|
|
|
|
fmt = ScriptFormatIPR()
|
|
fmt.parse_process_file(infile_name, execute_ipr, {'sl':sl, 'dynamic_data':demo_dict})
|