diff --git a/pySim/esim/saip/personalization.py b/pySim/esim/saip/personalization.py index d4251241..dd82e546 100644 --- a/pySim/esim/saip/personalization.py +++ b/pySim/esim/saip/personalization.py @@ -1179,11 +1179,18 @@ class UppAudit(dict): """ @classmethod - def from_der(cls, der: bytes, params: List): + def from_der(cls, der: bytes, params: List, additional_sd_keys=True): '''return a dict of parameter name and set of parameter values found in a DER encoded profile. Read all parameters listed in params. This calls only classmethods, so each entry in params can either be a class or an instance of a class, of a (non-abstract) ConfigurableParameter subclass. For example, params = [Imsi, ] is - equivalent to params = [Imsi(), ].''' + equivalent to params = [Imsi(), ]. + + For additional_sd_keys=True, audit also all Security Domain KVN that there are *no* ConfigurableParameter + subclasses for. For example, SCP80 has reserved kvn 0x01..0x0f, but we offer only Scp80Kvn01, Scp80Kvn02, + Scp80Kvn03. So we would not show kvn 0x03..0x0f in an audit. additional_sd_keys=True includes audits of all SD + key KVN there may be in the UPP. This helps to spot SD keys that may already be present in a UPP template, with + unexpected / unusual kvn. + ''' upp_audit = cls() upp_audit['der_size'] = set((len(der), )) @@ -1199,6 +1206,20 @@ class UppAudit(dict): upp_audit.add_values(valdict) except (TypeError, ValueError) as e: raise ValueError(f'Error during audit for parameter {key}: {e}') from e + + if not additional_sd_keys: + return upp_audit + + # additional_sd_keys + for pe in pes.pe_list: + if pe.type != 'securityDomain': + continue + assert isinstance(pe, ProfileElementSD) + + for key in pe.keys: + audit_key = f'SdKey_KVN{key.key_version_number:02x}_ID{key.key_identifier:02x}' + audit_val = f'{key.key_components!r} {key.key_usage_qualifier!r}' + upp_audit[audit_key] = audit_val return upp_audit def get_single_val(self, param, validate=True, allow_absent=False, absent_val=None):