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 <[email protected]>
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}

--
To view, visit https://gerrit.osmocom.org/c/pysim/+/42672?usp=email
To unsubscribe, or for help writing mail filters, visit 
https://gerrit.osmocom.org/settings?usp=email

Gerrit-MessageType: merged
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I6c600faeab00ffb072acbe94c9a8b2d1397c07d3
Gerrit-Change-Number: 42672
Gerrit-PatchSet: 10
Gerrit-Owner: fixeria <[email protected]>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <[email protected]>
Gerrit-CC: neels <[email protected]>

Reply via email to