laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/42672?usp=email )
Change subject: saip/personalization: add MncLen configurable parameter ......................................................................
saip/personalization: add MncLen configurable parameter
Add a new ConfigurableParameter that represents the MNC length (2 or 3 digits) in EF.AD (Administrative Data).
Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3 Co-authored-by: Vadim Yanitskiy vyanitskiy@sysmocom.de Jenkins: skip-card-test --- M pySim/esim/saip/personalization.py M tests/unittests/test_configurable_parameters.py M tests/unittests/xo/test_configurable_parameters 3 files changed, 109 insertions(+), 0 deletions(-)
Approvals: laforge: Looks good to me, approved Jenkins Builder: Verified
diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index efde37a..a73678f 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -21,9 +21,11 @@ import re from typing import List, Tuple, Generator, Optional
+from construct.core import StreamError from osmocom.tlv import camel_to_snake from osmocom.utils import hexstr from pySim.utils import enc_iccid, dec_iccid, enc_imsi, dec_imsi, h2b, b2h, rpad, sanitize_iccid +from pySim.ts_31_102 import EF_AD from pySim.ts_51_011 import EF_SMSP from pySim.esim.saip import param_source from pySim.esim.saip import ProfileElement, ProfileElementSD, ProfileElementSequence @@ -660,6 +662,72 @@ yield { cls.name: cls.tuple_to_str((international, digits)) }
+class MncLen(EnumParam): + """MNC length. Sets only the MNC length field in EF.AD (Administrative Data). + Accepted values: integer 2 or 3, digit strings '2' or '3', or enum names 'MNC2'/'MNC3'. + """ + name = 'MNC-LEN' + example_input = '2' + default_source = param_source.ConstantSource + + class Values(enum.IntEnum): + MNC2 = 2 + MNC3 = 3 + + @classmethod + def validate_val(cls, val): + if isinstance(val, str) and val.isdigit(): + val = int(val) + return super().validate_val(val) + + @classmethod + def _get_f_ad(cls, pe: ProfileElement): + if not hasattr(pe, 'files'): + return None + f_ad = pe.files.get('ef-ad', None) + if f_ad and f_ad.body: + return f_ad + return None + + @classmethod + def _decode_f_ad(cls, f_ad): + try: + ef_ad_dec = EF_AD().decode_bin(f_ad.body) + except StreamError: + return None + if 'mnc_len' not in ef_ad_dec: + return None + return ef_ad_dec + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val: int): + for pe in pes.get_pes_for_type('usim'): + f_ad = cls._get_f_ad(pe) + if f_ad is None: + continue + # decode existing values + ef_ad_dec = cls._decode_f_ad(f_ad) + if ef_ad_dec is None: + continue + # change mnc_len + ef_ad_dec['mnc_len'] = val + # re-encode into the File body + f_ad.body = EF_AD().encode_bin(ef_ad_dec) + pe.file2pe(f_ad) + + @classmethod + def get_values_from_pes(cls, pes: ProfileElementSequence): + for pe in pes.get_pes_for_type('usim'): + f_ad = cls._get_f_ad(pe) + if f_ad is None: + continue + ef_ad_dec = cls._decode_f_ad(f_ad) + if ef_ad_dec is None: + continue + mnc_len = ef_ad_dec.get('mnc_len') + yield { cls.name: str(mnc_len) } + + class SdKey(BinaryParam): """Configurable Security Domain (SD) Key. Value is presented as bytes. Non-abstract implementations are generated in SdKey.generate_sd_key_classes""" diff --git a/tests/unittests/test_configurable_parameters.py b/tests/unittests/test_configurable_parameters.py index 7f9c8b0..0ffc4b4 100755 --- a/tests/unittests/test_configurable_parameters.py +++ b/tests/unittests/test_configurable_parameters.py @@ -267,6 +267,15 @@ '11111111111111111111111111111111' '22222222222222222222222222222222'),
+ Paramtest(param_cls=p13n.MncLen, + val='2', + expect_clean_val=2, + expect_val='2'), + Paramtest(param_cls=p13n.MncLen, + val=3, + expect_clean_val=3, + expect_val='3'), + ]
for sdkey_cls in ( diff --git a/tests/unittests/xo/test_configurable_parameters b/tests/unittests/xo/test_configurable_parameters index d64e7ba..9ab6073 100644 --- a/tests/unittests/xo/test_configurable_parameters +++ b/tests/unittests/xo/test_configurable_parameters @@ -163,6 +163,14 @@ clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
+ok: TS48v5_SAIP2.1A_NoBERTLV.der MncLen(val= '2':str) + clean_val= 2:int + read_back_val= {'MNC-LEN': '2'}:{str} + +ok: TS48v5_SAIP2.1A_NoBERTLV.der MncLen(val= 3:int) + clean_val= 3:int + read_back_val= {'MNC-LEN': '3'}:{str} + ok: TS48v5_SAIP2.1A_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str) clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr} @@ -855,6 +863,14 @@ clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
+ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MncLen(val= '2':str) + clean_val= 2:int + read_back_val= {'MNC-LEN': '2'}:{str} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MncLen(val= 3:int) + clean_val= 3:int + read_back_val= {'MNC-LEN': '3'}:{str} + ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str) clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr} @@ -1547,6 +1563,14 @@ clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
+ok: TS48v5_SAIP2.1B_NoBERTLV.der MncLen(val= '2':str) + clean_val= 2:int + read_back_val= {'MNC-LEN': '2'}:{str} + +ok: TS48v5_SAIP2.1B_NoBERTLV.der MncLen(val= 3:int) + clean_val= 3:int + read_back_val= {'MNC-LEN': '3'}:{str} + ok: TS48v5_SAIP2.1B_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str) clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr} @@ -2239,6 +2263,14 @@ clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
+ok: TS48v5_SAIP2.3_NoBERTLV.der MncLen(val= '2':str) + clean_val= 2:int + read_back_val= {'MNC-LEN': '2'}:{str} + +ok: TS48v5_SAIP2.3_NoBERTLV.der MncLen(val= 3:int) + clean_val= 3:int + read_back_val= {'MNC-LEN': '3'}:{str} + ok: TS48v5_SAIP2.3_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str) clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}