| #!/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}) |