From 4fb393e6ea5b36c81b7adefc9131fd77e4cbeaf4 Mon Sep 17 00:00:00 2001 From: kukutyin Date: Wed, 27 May 2026 16:05:38 +0200 Subject: [PATCH] fix(ts_51_011): fix lifecycle decoding - implement proper LCS decoding per TS 102 221 / TS 31.101 - previous implementation misclassified multiple states Related: OS#7018 Change-Id: I8a3bd820b9fbc13c025f8302d1d2eac21686c541 --- pySim/ts_51_011.py | 17 ++++++++++++++--- tests/unittests/test_decode_select_resp.py | 4 ++-- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/pySim/ts_51_011.py b/pySim/ts_51_011.py index 24cf5c5f..af7a4331 100644 --- a/pySim/ts_51_011.py +++ b/pySim/ts_51_011.py @@ -1306,12 +1306,23 @@ class CardProfileSIM(CardProfile): ret['file_descriptor']['record_len'] = record_len ret['file_descriptor']['num_of_rec'] = ret['file_size'] // record_len ret['access_conditions'] = b2h(resp_bin[8:11]) - if resp_bin[11] & 0x01 == 0: + + # Life cycle status integer, see also ETSI TS 102 221, table 11.7b + lcsi = resp_bin[11] + if lcsi == 0x00: + ret['life_cycle_status_int'] = 'no_information' + elif lcsi == 0x01: + ret['life_cycle_status_int'] = 'creation' + elif lcsi == 0x03: + ret['life_cycle_status_int'] = 'initialization' + elif lcsi & 0xFD == 0x05: ret['life_cycle_status_int'] = 'operational_activated' - elif resp_bin[11] & 0x04: + elif lcsi & 0xFD == 0x04: ret['life_cycle_status_int'] = 'operational_deactivated' + elif lcsi & 0xFC == 0x0C: + ret['life_cycle_status_int'] = 'termination' else: - ret['life_cycle_status_int'] = 'terminated' + ret['life_cycle_status_int'] = lcsi return ret @classmethod diff --git a/tests/unittests/test_decode_select_resp.py b/tests/unittests/test_decode_select_resp.py index 72fb077c..4961ec9c 100644 --- a/tests/unittests/test_decode_select_resp.py +++ b/tests/unittests/test_decode_select_resp.py @@ -47,10 +47,10 @@ class TestDecodeSelectResponse_CardProfile(unittest.TestCase): "decoded" : {'file_descriptor': {'file_descriptor_byte': {'file_type': 'df'}}, 'proprietary_info': {'available_memory': 0}, 'file_id': '7f10', 'file_characteristics': '81', 'num_direct_child_df': 0, 'num_direct_child_ef': 13, 'num_chv_unblock_adm_codes': 4}}, # EF.MSISDN {"resp_hex" : "000000346f40040011ffff0102011a", - "decoded" : {'file_descriptor': {'file_descriptor_byte': {'file_type': 'working_ef', 'structure': 'linear_fixed'}, 'record_len': 26, 'num_of_rec': 2}, 'proprietary_info': {}, 'file_id': '6f40', 'file_size': 52, 'access_conditions': '11ffff', 'life_cycle_status_int': 'terminated'}}, + "decoded" : {'file_descriptor': {'file_descriptor_byte': {'file_type': 'working_ef', 'structure': 'linear_fixed'}, 'record_len': 26, 'num_of_rec': 2}, 'proprietary_info': {}, 'file_id': '6f40', 'file_size': 52, 'access_conditions': '11ffff', 'life_cycle_status_int': 'creation'}}, # EF.ICCID {"resp_hex" : "0000000a2fe204000cffff01020000", - "decoded" : {'file_descriptor': {'file_descriptor_byte': {'file_type': 'working_ef', 'structure': 'transparent'}}, 'proprietary_info': {}, 'file_id': '2fe2', 'file_size': 10, 'access_conditions': '0cffff', 'life_cycle_status_int': 'terminated'}}, + "decoded" : {'file_descriptor': {'file_descriptor_byte': {'file_type': 'working_ef', 'structure': 'transparent'}}, 'proprietary_info': {}, 'file_id': '2fe2', 'file_size': 10, 'access_conditions': '0cffff', 'life_cycle_status_int': 'creation'}}, ] self.decode_select_response(CardProfileSIM, testcases)