aboutsummaryrefslogtreecommitdiffstats
path: root/execute_ipr.py
blob: 715ad18fe29a013b07a09700614ad890e3b34883 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#!/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})