From 37e57e0c45320fe3b855e3ec57ab52145c8b2987 Mon Sep 17 00:00:00 2001 From: Philipp Maier Date: Thu, 7 Sep 2023 12:43:12 +0200 Subject: [PATCH] filesystem: add attribute "leftpad" to class LinFixedEF In some cases, the specs do not specify an absolute record length. Instead there may be only a minimum record length specified. The card vendor may then chose to use larger record length at will. This usually is no problem since the data is usually written from the left and the remaining bytes are padded at the end (right side) of the data. However in some rare cases (EF.MSISDN, see also 3GPP TS 51.011, section 10.5.5) the data must be written right-aligned towards the physical record length. This means that the data is padded from the left in this case. To fix this: Let's add a "leftpad" flag to LinFixedEF, which we set to true in those corner cases. The code that updates the record in commands.py must then check this flag and padd the data accordingly. Change-Id: I241d9fd656f9064a3ebb4e8e01a52b6b030f9923 Related: OS#5714 --- pySim/commands.py | 10 +++++++--- pySim/filesystem.py | 4 +++- pySim/runtime.py | 4 +++- pySim/ts_51_011.py | 5 ++--- 4 files changed, 15 insertions(+), 8 deletions(-) diff --git a/pySim/commands.py b/pySim/commands.py index 477cb2b9..e0720696 100644 --- a/pySim/commands.py +++ b/pySim/commands.py @@ -26,7 +26,7 @@ import typing # construct also has a Union, so we do typing.Union below from construct import * from pySim.construct import LV -from pySim.utils import rpad, b2h, h2b, sw_match, bertlv_encode_len, Hexstr, h2i, str_sanitize, expand_hex +from pySim.utils import rpad, lpad, b2h, h2b, sw_match, bertlv_encode_len, Hexstr, h2i, str_sanitize, expand_hex from pySim.utils import Hexstr, SwHexstr, ResTuple from pySim.exceptions import SwMatchError from pySim.transport import LinkBase @@ -269,7 +269,7 @@ class SimCardCommands: data.lower(), res[0].lower())) def update_record(self, ef: Path, rec_no: int, data: Hexstr, force_len: bool = False, - verify: bool = False, conserve: bool = False) -> ResTuple: + verify: bool = False, conserve: bool = False, leftpad: bool = False) -> ResTuple: """Execute UPDATE RECORD. Args: @@ -279,6 +279,7 @@ class SimCardCommands: force_len : enforce record length by using the actual data length verify : verify data by re-reading the record conserve : read record and compare it with data, skip write on match + leftpad : apply 0xff padding from the left instead from the right side. """ res = self.select_path(ef) @@ -295,7 +296,10 @@ class SimCardCommands: raise ValueError('Data length exceeds record length (expected max %d, got %d)' % ( rec_length, len(data) // 2)) elif (len(data) // 2 < rec_length): - data = rpad(data, rec_length * 2) + if leftpad: + data = lpad(data, rec_length * 2) + else: + data = rpad(data, rec_length * 2) # Save write cycles by reading+comparing before write if conserve: diff --git a/pySim/filesystem.py b/pySim/filesystem.py index 9f3ee174..5950ad14 100644 --- a/pySim/filesystem.py +++ b/pySim/filesystem.py @@ -920,7 +920,7 @@ class LinFixedEF(CardEF): self._cmd.poutput_json(data) def __init__(self, fid: str, sfid: str = None, name: str = None, desc: str = None, - parent: Optional[CardDF] = None, rec_len: Size = (1, None), **kwargs): + parent: Optional[CardDF] = None, rec_len: Size = (1, None), leftpad: bool = False, **kwargs): """ Args: fid : File Identifier (4 hex digits) @@ -929,9 +929,11 @@ class LinFixedEF(CardEF): desc : Description of the file parent : Parent CardFile object within filesystem hierarchy rec_len : Tuple of (minimum_length, recommended_length) + leftpad: On write, data must be padded from the left to fit pysical record length """ super().__init__(fid=fid, sfid=sfid, name=name, desc=desc, parent=parent, **kwargs) self.rec_len = rec_len + self.leftpad = leftpad self.shell_commands = [self.ShellCommands()] self._construct = None self._tlv = None diff --git a/pySim/runtime.py b/pySim/runtime.py index 422e916c..d6c6d19c 100644 --- a/pySim/runtime.py +++ b/pySim/runtime.py @@ -458,7 +458,9 @@ class RuntimeLchan: """ if not isinstance(self.selected_file, LinFixedEF): raise TypeError("Only works with Linear Fixed EF") - return self.rs.card._scc.update_record(self.selected_file.fid, rec_nr, data_hex, conserve=self.rs.conserve_write) + return self.rs.card._scc.update_record(self.selected_file.fid, rec_nr, data_hex, + conserve=self.rs.conserve_write, + leftpad=self.selected_file.leftpad) def update_record_dec(self, rec_nr: int, data: dict): """Update a record with given abstract data. Will encode abstract to binary data diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index c81bfdfb..d8cbabd2 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -181,7 +181,7 @@ class EF_SMS(LinFixedEF): # TS 51.011 Section 10.5.5 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) + super().__init__(fid, sfid=sfid, name=name, desc=desc, rec_len=(15, 34), leftpad=True, **kwargs) def _decode_record_hex(self, raw_hex_data, **kwargs): return {'msisdn': dec_msisdn(raw_hex_data)} @@ -192,8 +192,7 @@ class EF_MSISDN(LinFixedEF): encoded_msisdn = enc_msisdn(msisdn) else: encoded_msisdn = enc_msisdn(msisdn[2], msisdn[0], msisdn[1]) - alpha_identifier = (list(self.rec_len)[ - 0] - len(encoded_msisdn) // 2) * "ff" + alpha_identifier = (list(self.rec_len)[0] - len(encoded_msisdn) // 2) * "ff" return alpha_identifier + encoded_msisdn # TS 51.011 Section 10.5.6