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
|
#!/usr/bin/env python
# -*- coding: utf-8 -*-
""" pySim: SIM Card commands according to ISO 7816-4 and TS 11.11
"""
#
# Copyright (C) 2009-2010 Sylvain Munaut <tnt@246tNt.com>
# Copyright (C) 2010 Harald Welte <laforge@gnumonks.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
from pySim.utils import rpad, b2h
class SimCardCommands(object):
def __init__(self, transport):
self._tp = transport;
self._cla_byte = "a0"
self.sel_ctrl = "0000"
def get_atr(self):
return self._tp.get_atr()
@property
def cla_byte(self):
return self._cla_byte
@cla_byte.setter
def cla_byte(self, value):
self._cla_byte = value
@property
def sel_ctrl(self):
return self._sel_ctrl
@sel_ctrl.setter
def sel_ctrl(self, value):
self._sel_ctrl = value
def select_file(self, dir_list):
rv = []
for i in dir_list:
data, sw = self._tp.send_apdu_checksw(self.cla_byte + "a4" + self.sel_ctrl + "02" + i)
rv.append(data)
return rv
def read_binary_selected(self, length, offset=0):
pdu = self.cla_byte + 'b0%04x%02x' % (offset, (min(256, length) & 0xff))
return self._tp.send_apdu(pdu)
def read_binary(self, ef, length=None, offset=0):
if not hasattr(type(ef), '__iter__'):
ef = [ef]
r = self.select_file(ef)
if length is None:
length = int(r[-1][4:8], 16) - offset
return self.read_binary_selected(length, offset)
def update_binary(self, ef, data, offset=0):
if not hasattr(type(ef), '__iter__'):
ef = [ef]
self.select_file(ef)
pdu = self.cla_byte + 'd6%04x%02x' % (offset, len(data)/2) + data
return self._tp.send_apdu_checksw(pdu)
def read_record_selected(self, rec_length, rec_no):
pdu = self.cla_byte + 'b2%02x04%02x' % (rec_no, rec_length)
return self._tp.send_apdu(pdu)
def read_record(self, ef, rec_no):
if not hasattr(type(ef), '__iter__'):
ef = [ef]
r = self.select_file(ef)
rec_length = int(r[-1][28:30], 16)
return self.read_record_selected(rec_length, rec_no)
def update_record(self, ef, rec_no, data, force_len=False):
if not hasattr(type(ef), '__iter__'):
ef = [ef]
r = self.select_file(ef)
if not force_len:
rec_length = int(r[-1][28:30], 16)
if (len(data)/2 != rec_length):
raise ValueError('Invalid data length (expected %d, got %d)' % (rec_length, len(data)/2))
else:
rec_length = len(data)/2
pdu = (self.cla_byte + 'dc%02x04%02x' % (rec_no, rec_length)) + data
return self._tp.send_apdu_checksw(pdu)
def record_size(self, ef):
r = self.select_file(ef)
return int(r[-1][28:30], 16)
def record_count(self, ef):
r = self.select_file(ef)
return int(r[-1][4:8], 16) // int(r[-1][28:30], 16)
def run_gsm_raw(self, rand):
'''
A3/A8 algorithm in the SIM card using the given RAND.
This function returns a raw result tuple.
'''
if len(rand) != 32:
raise ValueError('Invalid rand')
self.select_file(['3f00', '7f20'])
return self._tp.send_apdu(self.cla_byte + '88000010' + rand)
def run_gsm(self, rand):
'''
A3/A8 algorithm in the SIM card using the given RAND.
This function returns a parsed ((SRES, Kc), sw) tuple.
'''
(res, sw) = self.run_gsm_raw(rand)
if sw != '9000':
return (res, sw)
return ((res[0:8], res[8:]), sw)
def reset_card(self):
return self._tp.reset_card()
def verify_chv(self, chv_no, code):
fc = rpad(b2h(code), 16)
return self._tp.send_apdu_checksw(self.cla_byte + '2000' + ('%02X' % chv_no) + '08' + fc)
|