pySim.esim.saip: Meaningful constructors for [I]SD + SSD

So far the main use case was to read a ProfileElement-SD from
a DER file.  But when we want to construct one from scratch,
we need to have the constructor put some meaningful [default]
values into the class members.

Change-Id: I69e104f1d78165c12291317326dbab05977a1574
This commit is contained in:
Harald Welte
2024-05-29 16:07:25 +02:00
parent bc949649da
commit 0251367ddb

View File

@@ -18,10 +18,11 @@
import abc import abc
import io import io
from typing import Tuple, List, Optional, Dict, Union from typing import Tuple, List, Optional, Dict, Union
from collections import OrderedDict
import asn1tools import asn1tools
from pySim.utils import bertlv_parse_tag, bertlv_parse_len, b2h from pySim.utils import bertlv_parse_tag, bertlv_parse_len, b2h, h2b
from pySim.ts_102_221 import FileDescriptor from pySim.ts_102_221 import FileDescriptor
from pySim.construct import build_construct from pySim.construct import build_construct
from pySim.esim import compile_asn1_subdir from pySim.esim import compile_asn1_subdir
@@ -297,6 +298,35 @@ class ProfileElementSD(ProfileElement):
class C9(BER_TLV_IE, tag=0xC9, nested=UiccSdInstallParams): class C9(BER_TLV_IE, tag=0xC9, nested=UiccSdInstallParams):
pass pass
def __init__(self, decoded: Optional[dict] = None):
if decoded:
self.decoded = decoded
return
# provide some reasonable defaults for a MNO-SD
self.decoded = OrderedDict()
self.decoded['sd-Header'] = { 'mandated': None, 'identification': None }
self.decoded['instance'] = {
'applicationLoadPackageAID': h2b('A0000001515350'),
'classAID': h2b('A000000251535041'),
'instanceAID': h2b('A000000151000000'),
# Optional: extraditeSecurityDomainAID
'applicationPrivileges': h2b('82FC80'),
# Optioal: lifeCycleState
'applicationSpecificParametersC9': h2b('8201f09301f08701f0'), # we assume user uses add_scp()
# Optional: systemSpecificParameters
'applicationParameters': {
# TAR: B20100, MSL: 12
'uiccToolkitApplicationSpecificParametersField': h2b('0100000100000002011203B2010000'),
},
# Optional: processData
# Optional: controlReferenceTemplate
}
self.decoded['keyList'] = [] # we assume user uses add_key() method for all keys
# Optional: sdPersoData
# Optional: openPersoData
# Optional: catTpParameters
self._post_decode()
def _post_decode(self): def _post_decode(self):
self.usip = self.C9() self.usip = self.C9()
self.usip.from_bytes(self.decoded['instance']['applicationSpecificParametersC9']) self.usip.from_bytes(self.decoded['instance']['applicationSpecificParametersC9'])
@@ -343,6 +373,17 @@ class ProfileElementSD(ProfileElement):
self.keys.remove(key) self.keys.remove(key)
self._pre_encode() self._pre_encode()
class ProfileElementSSD(ProfileElementSD):
"""Class representing a securityDomain ProfileElement for a SSD."""
def __init__(self):
super().__init__()
# defaults [overriding ProfileElementSD) taken from SAIP v2.3.1 Section 11.2.12
self.decoded['instance']['instanceAID'] = h2b('A00000055910100102736456616C7565')
self.decoded['instance']['applicationPrivileges'] = h2b('808000')
self.decoded['instance']['applicationParameters'] = {
# TAR: 6C7565, MSL: 12
'uiccToolkitApplicationSpecificParametersField': h2b('01000001000000020112036C756500'),
}
def bertlv_first_segment(binary: bytes) -> Tuple[bytes, bytes]: def bertlv_first_segment(binary: bytes) -> Tuple[bytes, bytes]:
"""obtain the first segment of a binary concatenation of BER-TLV objects. """obtain the first segment of a binary concatenation of BER-TLV objects.
@@ -436,6 +477,35 @@ class ProfileElementSequence:
out += pe.to_der() out += pe.to_der()
return out return out
def renumber_identification(self):
"""Re-generate the 'identification' numbering of all PE headers."""
i = 1
for pe in self.pe_list:
hdr = pe.header
if not hdr:
continue
pe.header['identification'] = i
i += 1
def get_index_by_type(self, petype: str) -> List[int]:
"""Return a list with the indicies of all instances of PEs of petype."""
ret = []
i = 0
for pe in self.pe_list:
if pe.type == petype:
ret.append(i)
i += 1
return ret
def add_ssd(self, ssd: ProfileElementSSD):
"""Add a SSD (Supplementary Security Domain) After MNO-SD/ISD-P."""
# find MNO-SD index
idx = self.get_index_by_type('securityDomain')[0]
# insert _after_ MNO-SD
self.pe_list.insert(idx+1, ssd)
self._process_pelist()
self.renumber_identification()
def __repr__(self) -> str: def __repr__(self) -> str:
return "PESequence(%s)" % ', '.join([str(x) for x in self.pe_list]) return "PESequence(%s)" % ', '.join([str(x) for x in self.pe_list])