diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index 71c9108d..30109dda 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -20,13 +20,14 @@ import io import os import re import pprint +import json 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_31_102 import EF_AD, EF_UST, EF_Routing_Indicator, EF_SUCI_Calc_Info from pySim.ts_51_011 import EF_SMSP from pySim.esim.saip import param_source from pySim.esim.saip import ProfileElement, ProfileElementSD, ProfileElementSequence @@ -1194,3 +1195,184 @@ class TuakNumberOfKeccak(IntegerParam, AlgoConfig): max_val = 255 example_input = '1' default_source = param_source.ConstantSource + + +class EfUstServiceParam(EnumParam): + """superclass for EF-UST service flag parameters""" + service_idx = 0 + value_map = { 'enabled': True, 'disabled': False } + default_source = param_source.ConstantSource + example_input = sorted(value_map.keys())[0] + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + for pe in pes.get_pes_for_type('usim'): + f_ust = pe.files['ef-ust'] + ef_ust = EF_UST() + ust = ef_ust.decode_bin(f_ust.body) + + ust[cls.service_idx]['activated'] = val + + f_ust.body = ef_ust.encode_bin(ust) + pe.file2pe(f_ust) + + @classmethod + def get_values_from_pes(cls, pes: ProfileElementSequence): + for pe in pes.get_pes_for_type('usim'): + f_ust = pe.files.get('ef-ust', None) + if not f_ust: + continue + ef_ust = EF_UST() + try: + ust = ef_ust.decode_bin(f_ust.body) + + service_flag = ust[cls.service_idx]['activated'] + yield { cls.name: cls.map_val_to_name(service_flag) } + except: + pass + +class SuciActive(EfUstServiceParam): + """EF-UST service nr 124: enable or disable the SUCI service.""" + service_idx = 124 + name = '5G-SUCI-active' + value_map = { 'SUCI-on': True, 'SUCI-off': False } + example_input = sorted(value_map.keys())[0] + +class SuciInUsim(EfUstServiceParam): + """EF-UST service nr 125: calculate SUCI in UE or in USIM""" + service_idx = 125 + name = '5G-SUCI-in-USIM' + value_map = { 'SUCI-in-UE': False, 'SUCI-in-USIM': True } + example_input = sorted(value_map.keys())[0] + +class SuciRi(ConfigurableParameter): + """SUCI Routing Indicator as in section 4.4.11.11 of 3GPP TS 31.102""" + name = '5G-SUCI-RI' + allow_chars = '0123456789' + min_len = 1 + max_len = 4 + allow_types = (str,) + example_input = '0' + default_source = param_source.ConstantSource + + KEY_RI = "routing_indicator" + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + for pe in pes.get_pes_for_type('df-5gs'): + f_ri = pe.files.get('ef-routing-indicator', None) + if f_ri is None: + continue + ef_ri = EF_Routing_Indicator() + ri = ef_ri.decode_bin(f_ri.body) + + ri[cls.KEY_RI] = str(val) + + f_ri.body = ef_ri.encode_bin(ri) + pe.file2pe(f_ri) + + @classmethod + def get_values_from_pes(cls, pes: ProfileElementSequence): + for pe in pes.get_pes_for_type('df-5gs'): + f_ri = pe.files.get('ef-routing-indicator', None) + if f_ri is None: + continue + ef_ri = EF_Routing_Indicator() + try: + ri = ef_ri.decode_bin(f_ri.body) + yield { cls.name: ri.get(cls.KEY_RI) } + except: + pass + +class SuciCalcInfo(ConfigurableParameter): + """SUCI Calculation Information as in section 4.4.11.8 of 3GPP TS 31.102""" + name = '5G-SUCI-CalcInfo' + example_input = '{}' + default_source = param_source.ConstantSource + allow_types = (str,) + max_len = 2000 + + @classmethod + def validate_val(cls, val): + val = super().validate_val(val) + + if not val: + raise ValueError("SUCI Calc Info value is empty -- should at least be an empty dict like '{}'") + + # check that it is a dict something like + # { + # "prot_scheme_id_list": [ + # {"priority": 0, "identifier": 2, "key_index": 1}, + # {"priority": 1, "identifier": 1, "key_index": 2}, + # ], + # "hnet_pubkey_list": [ + # {"hnet_pubkey_identifier": 27, + # "hnet_pubkey": "0472DA71976234CE833A6907425867B82E074D44EF907DFB4B3E21C1C2256EBCD15A7DED52FCBB097A4ED250E036C7B9C8C7004C4EEDC4F068CD7BF8D3F900E3B4"}, + # {"hnet_pubkey_identifier": 30, + # "hnet_pubkey": "5A8D38864820197C3394B92613B20B91633CBD897119273BF8E4A6F4EEC0A650"}, + # ], + # } + + try: + d = json.loads(val) + except json.decoder.JSONDecodeError as e: + raise ValueError(f"Cannot parse SUCI Calc Info: {e}") from e + + KEY_PSI_LIST = 'prot_scheme_id_list' + KEY_HPK_LIST = 'hnet_pubkey_list' + KEYS_D = set((KEY_HPK_LIST, KEY_PSI_LIST)) + KEYS_PSI = set(('identifier', 'key_index', 'priority')) + KEYS_HPK = set(('hnet_pubkey_identifier', 'hnet_pubkey')) + + if not (isinstance(d, dict) + and set(d.keys()) == KEYS_D): + raise ValueError(f"Unexpected structure in SUCI Calc Info: expected dict with entries {KEYS_D}") + + psi = d.get(KEY_PSI_LIST, None) + if not all((set(e.keys()) == KEYS_PSI) for e in psi): + raise ValueError("Unexpected structure in SUCI Calc Info:" + f" in {KEY_PSI_LIST}, expected dict with entries {KEYS_PSI}") + + hpk = d.get(KEY_HPK_LIST, None) + if not all((set(e.keys()) == KEYS_HPK) for e in hpk): + raise ValueError("Unexpected structure in SUCI Calc Info:" + f" in {KEY_HPK_LIST}, expected dict with entries {KEYS_HPK}") + return d + + @classmethod + def _apply_suci(cls, pes: ProfileElementSequence, val, pe_type="df-5gs", pe_file="ef-suci-calc-info"): + for pe in pes.get_pes_for_type(pe_type): + f_sucici = pe.files.get(pe_file, None) + if not f_sucici: + continue + ef_sucici = EF_SUCI_Calc_Info() + f_sucici.body = ef_sucici.encode_bin(val) + pe.file2pe(f_sucici) + + @classmethod + def apply_val(cls, pes: ProfileElementSequence, val): + cls._apply_suci(pes, val, "df-5gs", "ef-suci-calc-info") + cls._apply_suci(pes, val, "df-saip", "ef-suci-calc-info-usim") + + @classmethod + def _get_suci(cls, pes: ProfileElementSequence, pe_type="df-5gs", pe_file="ef-suci-calc-info"): + for pe in pes.get_pes_for_type(pe_type): + f_sucici = pe.files.get(pe_file, None) + if not f_sucici: + continue + ef_sucici = EF_SUCI_Calc_Info() + sucici = ef_sucici.decode_bin(f_sucici.body) + + # normalize to string (bytes cannot go into json) + for hnet_pubkey in sucici.get('hnet_pubkey_list', ()): + val = hnet_pubkey['hnet_pubkey'] + if isinstance(val, bytes): + val = b2h(val) + hnet_pubkey['hnet_pubkey'] = val + + yield { cls.name: json.dumps(sucici) } + + @classmethod + def get_values_from_pes(cls, pes: ProfileElementSequence): + yield from cls._get_suci(pes, "df-5gs", "ef-suci-calc-info") + yield from cls._get_suci(pes, "df-saip", "ef-suci-calc-info-usim") diff --git a/tests/unittests/test_configurable_parameters.py b/tests/unittests/test_configurable_parameters.py index cc043c15..c9246e5d 100755 --- a/tests/unittests/test_configurable_parameters.py +++ b/tests/unittests/test_configurable_parameters.py @@ -21,6 +21,7 @@ import io import sys import unittest import io +import json from importlib import resources from osmocom.utils import hexstr from pySim.esim.saip import ProfileElementSequence @@ -60,11 +61,14 @@ class ConfigurableParameterTest(unittest.TestCase): ) class Paramtest: - def __init__(self, param_cls, val, expect_val, expect_clean_val=None, iff_present=False): + iff_present_default = False + def __init__(self, param_cls, val, expect_val, expect_clean_val=None, iff_present=None): self.param_cls = param_cls self.val = val self.expect_clean_val = expect_clean_val self.expect_val = expect_val + if iff_present is None: + iff_present = Paramtest.iff_present_default self.iff_present = iff_present param_tests = [ @@ -277,8 +281,56 @@ class ConfigurableParameterTest(unittest.TestCase): val=3, expect_clean_val=3, expect_val='3'), + ] - ] + Paramtest.iff_present_default = True + + sucici = { + "prot_scheme_id_list": [ + {"priority": 0, "identifier": 2, "key_index": 1}, + {"priority": 1, "identifier": 1, "key_index": 2}, + ], + "hnet_pubkey_list": [ + {"hnet_pubkey_identifier": 27, + "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, + {"hnet_pubkey_identifier": 30, + "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}, + ], + } + + param_tests.extend([ + Paramtest(param_cls=p13n.SuciActive, val='SUCI-on', + expect_clean_val=True, + expect_val={'5G-SUCI-active': 'SUCI-on'}), + Paramtest(param_cls=p13n.SuciActive, val='SUCI-off', + expect_clean_val=False, + expect_val={'5G-SUCI-active': 'SUCI-off'}), + + Paramtest(param_cls=p13n.SuciInUsim, val='SUCI-in-UE', + expect_clean_val=False, + expect_val={'5G-SUCI-in-USIM': 'SUCI-in-UE'}), + Paramtest(param_cls=p13n.SuciInUsim, val='SUCI-in-USIM', + expect_clean_val=True, + expect_val={'5G-SUCI-in-USIM': 'SUCI-in-USIM'}), + + Paramtest(param_cls=p13n.SuciRi, val='123', + expect_clean_val='123', + expect_val={'5G-SUCI-RI': '123'}), + Paramtest(param_cls=p13n.SuciRi, val='0', + expect_clean_val='0', + expect_val={'5G-SUCI-RI': '0'}), + Paramtest(param_cls=p13n.SuciRi, val='9999', + expect_clean_val='9999', + expect_val={'5G-SUCI-RI': '9999'}), + + Paramtest(param_cls=p13n.SuciCalcInfo, + val=json.dumps(sucici), + expect_clean_val=sucici, + expect_val={'5G-SUCI-CalcInfo': json.dumps(sucici)}), + + ]) + + Paramtest.iff_present_default = False for sdkey_cls in ( # thin out the number of tests, as a compromise between completeness and test runtime diff --git a/tests/unittests/xo/test_configurable_parameters b/tests/unittests/xo/test_configurable_parameters index 6c958836..a120c714 100644 --- a/tests/unittests/xo/test_configurable_parameters +++ b/tests/unittests/xo/test_configurable_parameters @@ -214,6 +214,46 @@ ok: TS48v5_SAIP2.1A_NoBERTLV.der MncLen(val=3:int) previous value: ['2'] read_back_val={'MNC-LEN': '3'}:{str} +ok: TS48v5_SAIP2.1A_NoBERTLV.der SuciActive(val='SUCI-on':str) + clean_val=True:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-on'}:{str} + +ok: TS48v5_SAIP2.1A_NoBERTLV.der SuciActive(val='SUCI-off':str) + clean_val=False:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-off'}:{str} + +ok: TS48v5_SAIP2.1A_NoBERTLV.der SuciInUsim(val='SUCI-in-UE':str) + clean_val=False:bool + previous value: ['SUCI-in-UE'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-UE'}:{str} + +ok: TS48v5_SAIP2.1A_NoBERTLV.der SuciInUsim(val='SUCI-in-USIM':str) + clean_val=True:bool + previous value: ['SUCI-in-UE'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-USIM'}:{str} + +skip: TS48v5_SAIP2.1A_NoBERTLV.der SuciRi(val='123':str) + clean_val='123':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1A_NoBERTLV.der SuciRi(val='0':str) + clean_val='0':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1A_NoBERTLV.der SuciRi(val='9999':str) + clean_val='9999':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1A_NoBERTLV.der SuciCalcInfo(val='{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}':str) + clean_val={'prot_scheme_id_list': [{'priority': 0, 'identifier': 2, 'key_index': 1}, {'priority': 1, 'identifier': 1, 'key_index': 2}], 'hnet_pubkey_list': [{'hnet_pubkey_identifier': 27, 'hnet_pubkey': '0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4'}, {'hnet_pubkey_identifier': 30, 'hnet_pubkey': '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650'}]}:{list, list} + previous value: [] + skipping, param not in template. + 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 previous value: [] @@ -1049,6 +1089,46 @@ ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MncLen(val=3:int) previous value: ['2'] read_back_val={'MNC-LEN': '3'}:{str} +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciActive(val='SUCI-on':str) + clean_val=True:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-on'}:{str} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciActive(val='SUCI-off':str) + clean_val=False:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-off'}:{str} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciInUsim(val='SUCI-in-UE':str) + clean_val=False:bool + previous value: ['SUCI-in-USIM'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-UE'}:{str} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciInUsim(val='SUCI-in-USIM':str) + clean_val=True:bool + previous value: ['SUCI-in-USIM'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-USIM'}:{str} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciRi(val='123':str) + clean_val='123':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '123'}:{hexstr} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciRi(val='0':str) + clean_val='0':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '0'}:{hexstr} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciRi(val='9999':str) + clean_val='9999':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '9999'}:{hexstr} + +ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SuciCalcInfo(val='{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}':str) + clean_val={'prot_scheme_id_list': [{'priority': 0, 'identifier': 2, 'key_index': 1}, {'priority': 1, 'identifier': 1, 'key_index': 2}], 'hnet_pubkey_list': [{'hnet_pubkey_identifier': 27, 'hnet_pubkey': '0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4'}, {'hnet_pubkey_identifier': 30, 'hnet_pubkey': '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650'}]}:{list, list} + previous value: ['{"prot_scheme_id_list": [{"priority": 0, "identifier": 0, "key_index": 0}], "hnet_pubkey_list": []}'] + read_back_val={'5G-SUCI-CalcInfo': '{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}'}:{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 previous value: [] @@ -1884,6 +1964,46 @@ ok: TS48v5_SAIP2.1B_NoBERTLV.der MncLen(val=3:int) previous value: ['2'] read_back_val={'MNC-LEN': '3'}:{str} +ok: TS48v5_SAIP2.1B_NoBERTLV.der SuciActive(val='SUCI-on':str) + clean_val=True:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-on'}:{str} + +ok: TS48v5_SAIP2.1B_NoBERTLV.der SuciActive(val='SUCI-off':str) + clean_val=False:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-off'}:{str} + +ok: TS48v5_SAIP2.1B_NoBERTLV.der SuciInUsim(val='SUCI-in-UE':str) + clean_val=False:bool + previous value: ['SUCI-in-UE'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-UE'}:{str} + +ok: TS48v5_SAIP2.1B_NoBERTLV.der SuciInUsim(val='SUCI-in-USIM':str) + clean_val=True:bool + previous value: ['SUCI-in-UE'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-USIM'}:{str} + +skip: TS48v5_SAIP2.1B_NoBERTLV.der SuciRi(val='123':str) + clean_val='123':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1B_NoBERTLV.der SuciRi(val='0':str) + clean_val='0':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1B_NoBERTLV.der SuciRi(val='9999':str) + clean_val='9999':str + previous value: [] + skipping, param not in template. + +skip: TS48v5_SAIP2.1B_NoBERTLV.der SuciCalcInfo(val='{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}':str) + clean_val={'prot_scheme_id_list': [{'priority': 0, 'identifier': 2, 'key_index': 1}, {'priority': 1, 'identifier': 1, 'key_index': 2}], 'hnet_pubkey_list': [{'hnet_pubkey_identifier': 27, 'hnet_pubkey': '0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4'}, {'hnet_pubkey_identifier': 30, 'hnet_pubkey': '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650'}]}:{list, list} + previous value: [] + skipping, param not in template. + 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 previous value: [] @@ -2719,6 +2839,46 @@ ok: TS48v5_SAIP2.3_NoBERTLV.der MncLen(val=3:int) previous value: ['2'] read_back_val={'MNC-LEN': '3'}:{str} +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciActive(val='SUCI-on':str) + clean_val=True:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-on'}:{str} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciActive(val='SUCI-off':str) + clean_val=False:bool + previous value: ['SUCI-on'] + read_back_val={'5G-SUCI-active': 'SUCI-off'}:{str} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciInUsim(val='SUCI-in-UE':str) + clean_val=False:bool + previous value: ['SUCI-in-USIM'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-UE'}:{str} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciInUsim(val='SUCI-in-USIM':str) + clean_val=True:bool + previous value: ['SUCI-in-USIM'] + read_back_val={'5G-SUCI-in-USIM': 'SUCI-in-USIM'}:{str} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciRi(val='123':str) + clean_val='123':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '123'}:{hexstr} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciRi(val='0':str) + clean_val='0':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '0'}:{hexstr} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciRi(val='9999':str) + clean_val='9999':str + previous value: ['0'] + read_back_val={'5G-SUCI-RI': '9999'}:{hexstr} + +ok: TS48v5_SAIP2.3_NoBERTLV.der SuciCalcInfo(val='{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}':str) + clean_val={'prot_scheme_id_list': [{'priority': 0, 'identifier': 2, 'key_index': 1}, {'priority': 1, 'identifier': 1, 'key_index': 2}], 'hnet_pubkey_list': [{'hnet_pubkey_identifier': 27, 'hnet_pubkey': '0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4'}, {'hnet_pubkey_identifier': 30, 'hnet_pubkey': '5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650'}]}:{list, list} + previous value: ['{"prot_scheme_id_list": [{"priority": 0, "identifier": 0, "key_index": 0}], "hnet_pubkey_list": []}'] + read_back_val={'5G-SUCI-CalcInfo': '{"prot_scheme_id_list": [{"priority": 0, "identifier": 2, "key_index": 1}, {"priority": 1, "identifier": 1, "key_index": 2}], "hnet_pubkey_list": [{"hnet_pubkey_identifier": 27, "hnet_pubkey": "0472da71976234ce833a6907425867b82e074d44ef907dfb4b3e21c1c2256ebcd15a7ded52fcbb097a4ed250e036c7b9c8c7004c4eedc4f068cd7bf8d3f900e3b4"}, {"hnet_pubkey_identifier": 30, "hnet_pubkey": "5a8d38864820197c3394b92613b20b91633cbd897119273bf8e4a6f4eec0a650"}]}'}:{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 previous value: []