diff options
-rw-r--r-- | pySim/commands.py | 62 |
1 files changed, 56 insertions, 6 deletions
diff --git a/pySim/commands.py b/pySim/commands.py index eba915c..9e16b0e 100644 --- a/pySim/commands.py +++ b/pySim/commands.py @@ -23,7 +23,7 @@ # from pySim.utils import rpad, b2h - +from pytlv.TLV import * class SimCardCommands(object): def __init__(self, transport): @@ -31,6 +31,56 @@ class SimCardCommands(object): self._cla_byte = "a0" self.sel_ctrl = "0000" + # Get file size from FCP + def __get_len_from_tlv(self, fcp): + # see also: ETSI TS 102 221, chapter 11.1.1.3.1 Response for MF, + # DF or ADF + tlvparser = TLV(['82', '83', '84', 'A5', '8a', '8b', '8c', '80', 'ab', 'c6', '81', '88']) + + # pytlv is case sensitive! + fcp = fcp.lower() + + if fcp[0:2] != '62': + raise ValueError('Tag of the FCP template does not match, expected 62 but got %s'%fcp[0:2]) + + # Unfortunately the spec is not very clear if the FCP length is + # coded as one or two byte vale, so we have to try it out by + # checking if the length of the remaining TLV string matches + # what we get in the length field. + # See also ETSI TS 102 221, chapter 11.1.1.3.0 Base coding. + exp_tlv_len = int(fcp[2:4], 16) + if len(fcp[4:])/2 == exp_tlv_len: + skip = 4 + else: + exp_tlv_len = int(fcp[2:6], 16) + if len(fcp[4:])/2 == exp_tlv_len: + skip = 6 + + # Skip FCP tag and length + tlv = fcp[skip:] + tlv_parsed = tlvparser.parse(tlv) + + return int(tlv_parsed['80'], 16) + + # Tell the length of a record by the card response + # USIMs respond with an FCP template, which is different + # from what SIMs responds. See also: + # USIM: ETSI TS 102 221, chapter 11.1.1.3 Response Data + # SIM: GSM 11.11, chapter 9.2.1 SELECT + def __record_len(self, r): + if self.sel_ctrl == "0004": + return self.__get_len_from_tlv(r[-1]) + else: + return int(r[-1][28:30], 16) + + # Tell the length of a binary file. See also comment + # above. + def __len(self, r): + if self.sel_ctrl == "0004": + return self.__get_len_from_tlv(r[-1]) + else: + return int(r[-1][4:8], 16) + def get_atr(self): return self._tp.get_atr() @@ -60,7 +110,7 @@ class SimCardCommands(object): ef = [ef] r = self.select_file(ef) if length is None: - length = int(r[-1][4:8], 16) - offset + length = self.__len(r) - offset pdu = self.cla_byte + 'b0%04x%02x' % (offset, (min(256, length) & 0xff)) return self._tp.send_apdu(pdu) @@ -75,7 +125,7 @@ class SimCardCommands(object): if not hasattr(type(ef), '__iter__'): ef = [ef] r = self.select_file(ef) - rec_length = int(r[-1][28:30], 16) + rec_length = self.__record_len(r) pdu = self.cla_byte + 'b2%02x04%02x' % (rec_no, rec_length) return self._tp.send_apdu(pdu) @@ -84,7 +134,7 @@ class SimCardCommands(object): ef = [ef] r = self.select_file(ef) if not force_len: - rec_length = int(r[-1][28:30], 16) + rec_length = self.__record_len(r) if (len(data)/2 != rec_length): raise ValueError('Invalid data length (expected %d, got %d)' % (rec_length, len(data)/2)) else: @@ -94,11 +144,11 @@ class SimCardCommands(object): def record_size(self, ef): r = self.select_file(ef) - return int(r[-1][28:30], 16) + return self.__record_len(r) def record_count(self, ef): r = self.select_file(ef) - return int(r[-1][4:8], 16) // int(r[-1][28:30], 16) + return self.__len(r) // self.__record_len(r) def run_gsm(self, rand): if len(rand) != 32: |