diff --git a/pySim/apdu/ts_102_221.py b/pySim/apdu/ts_102_221.py index ea456021..cd246b11 100644 --- a/pySim/apdu/ts_102_221.py +++ b/pySim/apdu/ts_102_221.py @@ -201,7 +201,7 @@ class ReadRecord(ApduCommand, n='READ RECORD', ins=0xB2, cla=['0X', '4X', '6X']) return b2h(self.rsp_data) method = getattr(self.file, 'decode_record_bin', None) if self.successful and callable(method): - return method(self.rsp_data) + return method(self.rsp_data, self.cmd_dict['record_number']) # TS 102 221 Section 11.1.6 class UpdateRecord(ApduCommand, n='UPDATE RECORD', ins=0xDC, cla=['0X', '4X', '6X']): @@ -217,7 +217,7 @@ class UpdateRecord(ApduCommand, n='UPDATE RECORD', ins=0xDC, cla=['0X', '4X', '6 return b2h(self.cmd_data) method = getattr(self.file, 'decode_record_bin', None) if self.successful and callable(method): - return method(self.cmd_data) + return method(self.cmd_data, self.cmd_dict['record_number']) # TS 102 221 Section 11.1.7 class SearchRecord(ApduCommand, n='SEARCH RECORD', ins=0xA2, cla=['0X', '4X', '6X']): diff --git a/pySim/filesystem.py b/pySim/filesystem.py index a3d1122d..6dd1db72 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -945,7 +945,7 @@ class LinFixedEF(CardEF): self._construct = None self._tlv = None - def decode_record_hex(self, raw_hex_data: str) -> dict: + def decode_record_hex(self, raw_hex_data: str, record_nr: int) -> dict: """Decode raw (hex string) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() @@ -954,16 +954,17 @@ class LinFixedEF(CardEF): Args: raw_hex_data : hex-encoded data + record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data """ method = getattr(self, '_decode_record_hex', None) if callable(method): - return method(raw_hex_data) + return method(raw_hex_data, record_nr=record_nr) raw_bin_data = h2b(raw_hex_data) method = getattr(self, '_decode_record_bin', None) if callable(method): - return method(raw_bin_data) + return method(raw_bin_data, record_nr=record_nr) if self._construct: return parse_construct(self._construct, raw_bin_data) elif self._tlv: @@ -972,7 +973,7 @@ class LinFixedEF(CardEF): return t.to_dict() return {'raw': raw_bin_data.hex()} - def decode_record_bin(self, raw_bin_data: bytearray) -> dict: + def decode_record_bin(self, raw_bin_data: bytearray, record_nr: int) -> dict: """Decode raw (binary) data into abstract representation. A derived class would typically provide a _decode_record_bin() or _decode_record_hex() @@ -981,16 +982,17 @@ class LinFixedEF(CardEF): Args: raw_bin_data : binary encoded data + record_nr : record number (1 for first record, ...) Returns: abstract_data; dict representing the decoded data """ method = getattr(self, '_decode_record_bin', None) if callable(method): - return method(raw_bin_data) + return method(raw_bin_data, record_nr=record_nr) raw_hex_data = b2h(raw_bin_data) method = getattr(self, '_decode_record_hex', None) if callable(method): - return method(raw_hex_data) + return method(raw_hex_data, record_nr=record_nr) if self._construct: return parse_construct(self._construct, raw_bin_data) elif self._tlv: @@ -999,7 +1001,7 @@ class LinFixedEF(CardEF): return t.to_dict() return {'raw': raw_hex_data} - def encode_record_hex(self, abstract_data: dict) -> str: + def encode_record_hex(self, abstract_data: dict, record_nr: int) -> str: """Encode abstract representation into raw (hex string) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() @@ -1008,15 +1010,16 @@ class LinFixedEF(CardEF): Args: abstract_data : dict representing the decoded data + record_nr : record number (1 for first record, ...) Returns: hex string encoded data """ method = getattr(self, '_encode_record_hex', None) if callable(method): - return method(abstract_data) + return method(abstract_data, record_nr=record_nr) method = getattr(self, '_encode_record_bin', None) if callable(method): - raw_bin_data = method(abstract_data) + raw_bin_data = method(abstract_data, record_nr=record_nr) return b2h(raw_bin_data) if self._construct: return b2h(self._construct.build(abstract_data)) @@ -1027,7 +1030,7 @@ class LinFixedEF(CardEF): raise NotImplementedError( "%s encoder not yet implemented. Patches welcome." % self) - def encode_record_bin(self, abstract_data: dict) -> bytearray: + def encode_record_bin(self, abstract_data: dict, record_nr : int) -> bytearray: """Encode abstract representation into raw (binary) data. A derived class would typically provide an _encode_record_bin() or _encode_record_hex() @@ -1036,15 +1039,16 @@ class LinFixedEF(CardEF): Args: abstract_data : dict representing the decoded data + record_nr : record number (1 for first record, ...) Returns: binary encoded data """ method = getattr(self, '_encode_record_bin', None) if callable(method): - return method(abstract_data) + return method(abstract_data, record_nr=record_nr) method = getattr(self, '_encode_record_hex', None) if callable(method): - return h2b(method(abstract_data)) + return h2b(method(abstract_data, record_nr=record_nr)) if self._construct: return self._construct.build(abstract_data) elif self._tlv: @@ -1681,7 +1685,7 @@ class RuntimeLchan: abstract data contained in record """ (data, sw) = self.read_record(rec_nr) - return (self.selected_file.decode_record_hex(data), sw) + return (self.selected_file.decode_record_hex(data, rec_nr), sw) def update_record(self, rec_nr: int, data_hex: str): """Update a record with given binary data @@ -1702,7 +1706,7 @@ class RuntimeLchan: rec_nr : Record number to read data_hex : Abstract data to be written """ - data_hex = self.selected_file.encode_record_hex(data) + data_hex = self.selected_file.encode_record_hex(data, rec_nr) return self.update_record(rec_nr, data_hex) def retrieve_data(self, tag: int = 0): diff --git a/pySim/sysmocom_sja2.py b/pySim/sysmocom_sja2.py index a78318ed..49677011 100644 --- a/pySim/sysmocom_sja2.py +++ b/pySim/sysmocom_sja2.py @@ -87,7 +87,7 @@ class EF_0348_KEY(LinFixedEF): def __init__(self, fid='6f22', name='EF.0348_KEY', desc='TS 03.48 OTA Keys'): super().__init__(fid, name=name, desc=desc, rec_len=(27, 35)) - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): u = unpack('!BBB', raw_bin_data[0:3]) key_algo = (u[2] >> 6) & 1 key_length = ((u[2] >> 3) & 3) * 8 @@ -105,7 +105,7 @@ class EF_0348_COUNT(LinFixedEF): def __init__(self, fid='6f23', name='EF.0348_COUNT', desc='TS 03.48 OTA Counters'): super().__init__(fid, name=name, desc=desc, rec_len=(7, 7)) - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): u = unpack('!BB5s', raw_bin_data) return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2]} @@ -120,7 +120,7 @@ class EF_GP_COUNT(LinFixedEF): def __init__(self, fid='6f26', name='EF.GP_COUNT', desc='GP SCP02 Counters'): super().__init__(fid, name=name, desc=desc, rec_len=(5, 5)) - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): u = unpack('!BBHB', raw_bin_data) return {'sec_domain': u[0], 'key_set_version': u[1], 'counter': u[2], 'rfu': u[3]} @@ -129,7 +129,7 @@ class EF_GP_DIV_DATA(LinFixedEF): def __init__(self, fid='6f27', name='EF.GP_DIV_DATA', desc='GP SCP02 key diversification data'): super().__init__(fid, name=name, desc=desc, rec_len=(12, 12)) - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): u = unpack('!BB8s', raw_bin_data) return {'sec_domain': u[0], 'key_set_version': u[1], 'key_div_data': u[2].hex()} diff --git a/pySim/ts_102_221.py b/pySim/ts_102_221.py index 83ddb85a..e180b28e 100644 --- a/pySim/ts_102_221.py +++ b/pySim/ts_102_221.py @@ -608,13 +608,13 @@ class EF_PL(TransRecEF): super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=2, size=(2, None)) - def _decode_record_bin(self, bin_data): + def _decode_record_bin(self, bin_data, **kwargs): if bin_data == b'\xff\xff': return None else: return bin_data.decode('ascii') - def _encode_record_bin(self, in_json): + def _encode_record_bin(self, in_json, **kwargs): if in_json is None: return b'\xff\xff' else: @@ -665,7 +665,7 @@ class EF_ARR(LinFixedEF): raise ValueError return by_mode - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): # we can only guess if we should decode for EF or DF here :( arr_seq = DataObjectSequence('arr', sequence=[AM_DO_EF, SC_DO]) dec = arr_seq.decode_multi(raw_bin_data) @@ -673,7 +673,7 @@ class EF_ARR(LinFixedEF): # 'un-flattening' decoder, and hence would be unable to encode :( return dec[0] - def _encode_record_bin(self, in_json): + def _encode_record_bin(self, in_json, **kwargs): # we can only guess if we should decode for EF or DF here :( arr_seq = DataObjectSequence('arr', sequence=[AM_DO_EF, SC_DO]) return arr_seq.encode_multi(in_json) diff --git a/pySim/ts_31_102.py b/pySim/ts_31_102.py index 65a2afe7..e68866c4 100644 --- a/pySim/ts_31_102.py +++ b/pySim/ts_31_102.py @@ -515,14 +515,14 @@ class EF_LI(TransRecEF): desc='Language Indication'): super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len) - def _decode_record_bin(self, in_bin): + def _decode_record_bin(self, in_bin, **kwargs): if in_bin == b'\xff\xff': return None else: # officially this is 7-bit GSM alphabet with one padding bit in each byte return in_bin.decode('ascii') - def _encode_record_bin(self, in_json): + def _encode_record_bin(self, in_json, **kwargs): if in_json == None: return b'\xff\xff' else: @@ -604,7 +604,7 @@ class EF_ECC(LinFixedEF): desc='Emergency Call Codes'): super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(4, 20)) - def _decode_record_bin(self, in_bin): + def _decode_record_bin(self, in_bin, **kwargs): # mandatory parts code = in_bin[:3] if code == b'\xff\xff\xff': @@ -618,7 +618,7 @@ class EF_ECC(LinFixedEF): ret['alpha_id'] = parse_construct(EF_ECC.alpha_construct, alpha_id) return ret - def _encode_record_bin(self, in_json): + def _encode_record_bin(self, in_json, **kwargs): if in_json is None: return b'\xff\xff\xff\xff' code = EF_ECC.cc_construct.build(in_json['call_code']) @@ -753,7 +753,7 @@ class EF_RPLMNAcT(TransRecEF): def __init__(self, fid='6f65', sfid=None, name='EF.RPLMNAcTD', size=(2, 4), rec_len=2, desc='RPLMN Last used Access Technology', **kwargs): super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs) - def _decode_record_hex(self, in_hex): + def _decode_record_hex(self, in_hex, **kwargs): return dec_act(in_hex) # TODO: Encode diff --git a/pySim/ts_31_103.py b/pySim/ts_31_103.py index 30df0b79..ee50ddba 100644 --- a/pySim/ts_31_103.py +++ b/pySim/ts_31_103.py @@ -142,11 +142,11 @@ class EF_PCSCF(LinFixedEF): def __init__(self, fid='6f09', sfid=None, name='EF.P-CSCF', desc='P-CSCF Address', **kwargs): super().__init__(fid=fid, sfid=sfid, name=name, desc=desc, **kwargs) - def _decode_record_hex(self, raw_hex): + def _decode_record_hex(self, raw_hex, **kwargs): addr, addr_type = dec_addr_tlv(raw_hex) return {"addr": addr, "addr_type": addr_type} - def _encode_record_hex(self, json_in): + def _encode_record_hex(self, json_in, **kwargs): addr = json_in['addr'] addr_type = json_in['addr_type'] return enc_addr_tlv(addr, addr_type) diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index d16ea729..bb49f13b 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -356,7 +356,7 @@ class EF_SMS(LinFixedEF): def __init__(self, fid='6f3c', sfid=None, name='EF.SMS', desc='Short messages', **kwargs): super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(176, 176), **kwargs) - def _decode_record_bin(self, raw_bin_data): + def _decode_record_bin(self, raw_bin_data, **kwargs): def decode_status(status): if status & 0x01 == 0x00: return (None, 'free_space') @@ -387,10 +387,10 @@ class EF_MSISDN(LinFixedEF): def __init__(self, fid='6f40', sfid=None, name='EF.MSISDN', desc='MSISDN', **kwargs): super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(15, 34), **kwargs) - def _decode_record_hex(self, raw_hex_data): + def _decode_record_hex(self, raw_hex_data, **kwargs): return {'msisdn': dec_msisdn(raw_hex_data)} - def _encode_record_hex(self, abstract): + def _encode_record_hex(self, abstract, **kwargs): msisdn = abstract['msisdn'] if type(msisdn) == str: encoded_msisdn = enc_msisdn(msisdn) @@ -516,10 +516,10 @@ class EF_LP(TransRecEF): desc='Language Preference'): super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len) - def _decode_record_bin(self, in_bin): + def _decode_record_bin(self, in_bin, **kwargs): return b2h(in_bin) - def _encode_record_bin(self, in_json): + def _encode_record_bin(self, in_json, **kwargs): return h2b(in_json) # TS 51.011 Section 10.3.2 @@ -566,13 +566,13 @@ class EF_PLMNsel(TransRecEF): size=(24, None), rec_len=3, **kwargs): super().__init__(fid, name=name, sfid=sfid, desc=desc, size=size, rec_len=rec_len, **kwargs) - def _decode_record_hex(self, in_hex): + def _decode_record_hex(self, in_hex, **kwargs): if in_hex[:6] == "ffffff": return None else: return dec_plmn(in_hex) - def _encode_record_hex(self, in_json): + def _encode_record_hex(self, in_json, **kwargs): if in_json == None: return "ffffff" else: @@ -772,7 +772,7 @@ class EF_CNL(TransRecEF): desc='Co-operative Network List', **kwargs): super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs) - def _decode_record_hex(self, in_hex): + def _decode_record_hex(self, in_hex, **kwargs): (in_plmn, sub, svp, corp) = unpack('!3sBBB', h2b(in_hex)) res = dec_plmn(b2h(in_plmn)) res['network_subset'] = sub @@ -780,7 +780,7 @@ class EF_CNL(TransRecEF): res['corporate_id'] = corp return res - def _encode_record_hex(self, in_json): + def _encode_record_hex(self, in_json, **kwargs): plmn = enc_plmn(in_json['mcc'], in_json['mnc']) return b2h(pack('!3sBBB', h2b(plmn), @@ -815,13 +815,13 @@ class EF_xPLMNwAcT(TransRecEF): def __init__(self, fid, sfid=None, name=None, desc=None, size=(40, None), rec_len=5, **kwargs): super().__init__(fid, sfid=sfid, name=name, desc=desc, size=size, rec_len=rec_len, **kwargs) - def _decode_record_hex(self, in_hex): + def _decode_record_hex(self, in_hex, **kwargs): if in_hex[:6] == "ffffff": return None else: return dec_xplmn_w_act(in_hex) - def _encode_record_hex(self, in_json): + def _encode_record_hex(self, in_json, **kwargs): if in_json == None: return "ffffff0000" else: