laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/37010?usp=email )
Change subject: esim.saip: Add ProfileElementSequence.remove_naas_of_type
......................................................................
esim.saip: Add ProfileElementSequence.remove_naas_of_type
This method allows the caller to remove all NAAs of a certain type,
for example to remove all CSIM instances from a given profile.
Change-Id: I64438bf0be58bad7a561c3744b7e9b1338a7857c
---
M pySim/esim/saip/__init__.py
M pySim/esim/saip/oid.py
2 files changed, 98 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/10/37010/1
diff --git a/pySim/esim/saip/__init__.py b/pySim/esim/saip/__init__.py
index 938dc48..4d39b64 100644
--- a/pySim/esim/saip/__init__.py
+++ b/pySim/esim/saip/__init__.py
@@ -27,12 +27,57 @@
from pySim.construct import build_construct
from pySim.esim import compile_asn1_subdir
from pySim.esim.saip import templates
+from pySim.esim.saip import oid
from pySim.tlv import BER_TLV_IE
from pySim.global_platform import KeyType, KeyUsageQualifier
from pySim.global_platform.uicc import UiccSdInstallParams
asn1 = compile_asn1_subdir('saip')
+class Naa:
+ """A class defining a Network Access Application (NAA)."""
+ name = None
+ # AID prefix, as used for ADF and EF.DIR
+ aid = None
+ # the ProfileElement types used specifically in this NAA
+ pe_types = []
+ # we only use the base DN of each OID; there may be subsequent versions underneath it
+ templates = []
+
+ @classmethod
+ def adf_name(cls):
+ return 'adf-' + cls.mandatory_services[0]
+
+class NaaCsim(Naa):
+ name = "csim"
+ aid = h2b("")
+ mandatory_services = ["csim"]
+ pe_types = ["csim", "opt-csim", "cdmaParameter"]
+ templates = [oid.ADF_CSIM_by_default, oid.ADF_CSIM_not_by_default]
+
+class NaaUsim(Naa):
+ name = "usim"
+ aid = h2b("")
+ mandatory_services = ["usim"]
+ pe_types = ["usim", "opt-usim"]
+ templates = [oid.ADF_USIM_by_default, oid.ADF_USIM_not_by_default,
+ oid.DF_PHONEBOOK_ADF_USIM, oid.DF_GSM_ACCESS_ADF_USIM,
+ oid.DF_EAP, oid.DF_5GS, oid.DF_SAIP, oid.DF_SNPN,
+ oid.DF_5GProSe]
+
+class NaaIsim(Naa):
+ name = "isim"
+ aid = h2b("")
+ mandatory_services = ["isim"]
+ pe_types = ["isim", "opt-isim"]
+ templates = [oid.ADF_ISIM_by_default, oid.ADF_ISIM_not_by_default]
+
+NAAs = {
+ NaaCsim.name: NaaCsim,
+ NaaUsim.name: NaaUsim,
+ NaaIsim.name: NaaIsim,
+}
+
class File:
"""Internal representation of a file in a profile filesystem.
@@ -513,6 +558,43 @@
self._process_pelist()
self.renumber_identification()
+ def remove_naas_of_type(self, naa: Naa) -> None:
+ """Remove all instances of NAAs of given type. This can be used, for example,
+ to remove all CSIM NAAs from a profile. Will not just remove the PEs, but also
+ any records in 'eUICC-Mandatory-services' or 'eUICC-Mandatory-GFSTEList'."""
+ hdr = self.pe_by_type['header'][0]
+ # remove any associated mandatory services
+ for service in naa.mandatory_services:
+ if service in hdr.decoded['eUICC-Mandatory-services']:
+ del hdr.decoded['eUICC-Mandatory-services'][service]
+ # remove any associaed mandatory filesystem templates
+ for template in naa.templates:
+ if template in hdr.decoded['eUICC-Mandatory-GFSTEList']:
+ hdr.decoded['eUICC-Mandatory-GFSTEList'] = [x for x in hdr.decoded['eUICC-Mandatory-GFSTEList'] if not template.prefix_match(x)]
+ # determine the ADF names (AIDs) of all NAA ADFs
+ naa_adf_names = []
+ if naa.pe_types[0] in self.pe_by_type:
+ for pe in self.pe_by_type[naa.pe_types[0]]:
+ adf_name = naa.adf_name()
+ adf = File(adf_name, pe.decoded[adf_name])
+ naa_adf_names.append(adf.fileDescriptor['dfName'])
+ # remove PEs of each NAA instance
+ if naa.name in self.pes_by_naa:
+ for inst in self.pes_by_naa[naa.name]:
+ # delete all the PEs of the NAA
+ self.pe_list = [pe for pe in self.pe_list if pe not in inst]
+ self._process_pelist()
+ # remove any RFM PEs for the just-removed ADFs
+ if 'rfm' in self.pe_by_type:
+ to_delete_pes = []
+ for rfm_pe in self.pe_by_type['rfm']:
+ if 'adfRFMAccess' in rfm_pe.decoded:
+ if rfm_pe.decoded['adfRFMAccess']['adfAID'] in naa_adf_names:
+ to_delete_pes.append(rfm_pe)
+ self.pe_list = [pe for pe in self.pe_list if pe not in to_delete_pes]
+ self._process_pelist()
+ # TODO: remove any records related to the ADFs from EF.DIR
+
def __repr__(self) -> str:
return "PESequence(%s)" % ', '.join([str(x) for x in self.pe_list])
diff --git a/pySim/esim/saip/oid.py b/pySim/esim/saip/oid.py
index 238e49f..d33b786 100644
--- a/pySim/esim/saip/oid.py
+++ b/pySim/esim/saip/oid.py
@@ -38,6 +38,10 @@
def __repr__(self) -> str:
return 'OID(%s)' % (str(self))
+ def prefix_match(self, oid_str):
+ """determine if oid_str is equal or below our OID."""
+ return oid_str.startswith(str(self))
+
class eOID(OID):
"""OID helper for TCA eUICC prefix"""
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37010?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I64438bf0be58bad7a561c3744b7e9b1338a7857c
Gerrit-Change-Number: 37010
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: newchange
laforge has uploaded this change for review. ( https://gerrit.osmocom.org/c/pysim/+/37011?usp=email )
Change subject: add contrib/saip-tool.py
......................................................................
add contrib/saip-tool.py
This is a tool to work with eSIM profiles in SAIP format. It allows
to dump the contents, run constraint checkers as well as splitting
of the PE-Sequence into the individual PEs.
Change-Id: I396bcd594e0628dfc26bd90233317a77e2f91b20
---
A contrib/saip-tool.py
1 file changed, 176 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/11/37011/1
diff --git a/contrib/saip-tool.py b/contrib/saip-tool.py
new file mode 100755
index 0000000..eae906c
--- /dev/null
+++ b/contrib/saip-tool.py
@@ -0,0 +1,163 @@
+#!/usr/bin/env python3
+
+# (C) 2024 by Harald Welte <laforge(a)osmocom.org>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+import os
+import sys
+import argparse
+import logging
+from pathlib import Path
+from typing import List
+
+from pySim.esim.saip import *
+from pySim.esim.saip.validation import CheckBasicStructure
+from pySim.utils import h2b, b2h, swap_nibbles
+from pySim.pprint import HexBytesPrettyPrinter
+
+pp = HexBytesPrettyPrinter(indent=4,width=500)
+
+logging.basicConfig(level=logging.DEBUG)
+
+parser = argparse.ArgumentParser(description="""
+Utility program to work with eSIM SAIP (SimAlliance Interoperable Profile) files.""")
+parser.add_argument('INPUT_UPP', help='Unprotected Profile Package Input file')
+subparsers = parser.add_subparsers(dest='command', help="The command to perform", required=True)
+
+parser_split = subparsers.add_parser('split', help='Split PE-Sequence into individual PEs')
+parser_split.add_argument('--output-prefix', default='.', help='Prefix path/filename for output files')
+
+parser_dump = subparsers.add_parser('dump', help='Dump information on PE-Sequence')
+parser_dump.add_argument('mode', choices=['all_pe', 'all_pe_by_type', 'all_pe_by_naa'])
+parser_dump.add_argument('--dump-decoded', action='store_true', help='Dump decoded PEs')
+
+parser_check = subparsers.add_parser('check', help='Run constraint checkers on PE-Sequence')
+
+parser_rpe = subparsers.add_parser('remove-pe', help='Remove specified PEs from PE-Sequence')
+parser_rpe.add_argument('--output-file', required=True, help='Output file name')
+parser_rpe.add_argument('--identification', type=int, action='append', help='Remove PEs matching specified identification')
+
+parser_rn = subparsers.add_parser('remove-naa', help='Remove speciifed NAAs from PE-Sequence')
+parser_rn.add_argument('--output-file', required=True, help='Output file name')
+parser_rn.add_argument('--naa-type', required=True, choices=NAAs.keys(), help='Network Access Application type to remove')
+# TODO: add an --naa-index or the like, so only one given instance can be removed
+
+
+def do_split(pes: ProfileElementSequence, opts):
+ i = 0
+ for pe in pes.pe_list:
+ basename = Path(opts.INPUT_UPP).stem
+ if not pe.identification:
+ fname = '%s-%02u-%s.der' % (basename, i, pe.type)
+ else:
+ fname = '%s-%02u-%05u-%s.der' % (basename, i, pe.identification, pe.type)
+ print("writing single PE to file '%s'" % fname)
+ with open(os.path.join(opts.output_prefix, fname), 'wb') as outf:
+ outf.write(pe.to_der())
+ i += 1
+
+def do_dump(pes: ProfileElementSequence, opts):
+ def print_all_pe(pes: ProfileElementSequence, dump_decoded:bool = False):
+ # iterate over each pe in the pes (using its __iter__ method)
+ for pe in pes:
+ print("="*70 + " " + pe.type)
+ if dump_decoded:
+ pp.pprint(pe.decoded)
+
+ def print_all_pe_by_type(pes: ProfileElementSequence, dump_decoded:bool = False):
+ # sort by PE type and show all PE within that type
+ for pe_type in pes.pe_by_type.keys():
+ print("="*70 + " " + pe_type)
+ for pe in pes.pe_by_type[pe_type]:
+ pp.pprint(pe)
+ if dump_decoded:
+ pp.pprint(pe.decoded)
+
+ def print_all_pe_by_naa(pes: ProfileElementSequence, dump_decoded:bool = False):
+ for naa in pes.pes_by_naa:
+ i = 0
+ for naa_instance in pes.pes_by_naa[naa]:
+ print("="*70 + " " + naa + str(i))
+ i += 1
+ for pe in naa_instance:
+ pp.pprint(pe.type)
+ if dump_decoded:
+ for d in pe.decoded:
+ print(" %s" % d)
+ #pp.pprint(pe.decoded[d])
+ #if pe.type in ['akaParameter', 'pinCodes', 'pukCodes']:
+ # pp.pprint(pe.decoded)
+
+ if opts.mode == 'all_pe':
+ print_all_pe(pes, opts.dump_decoded)
+ elif opts.mode == 'all_pe_by_type':
+ print_all_pe_by_type(pes, opts.dump_decoded)
+ elif opts.mode == 'all_pe_by_naa':
+ print_all_pe_by_naa(pes, opts.dump_decoded)
+
+def do_check(pes: ProfileElementSequence, opts):
+ print("Checking PE-Sequence structure...")
+ checker = CheckBasicStructure()
+ checker.check(pes)
+ print("All good!")
+
+def do_remove_pe(pes: ProfileElementSequence, opts):
+ new_pe_list = []
+ for pe in pes.pe_list:
+ identification = pe.identification
+ if identification:
+ if identification in opts.identification:
+ print("Removing PE %s (id=%u) from Sequence..." % (pe, identification))
+ continue
+ new_pe_list.append(pe)
+
+ pes.pe_list = new_pe_list
+ pes._process_pelist()
+ print("Writing %u PEs to file '%s'..." % (len(pes.pe_list), opts.output_file))
+ with open(opts.output_file, 'wb') as f:
+ f.write(pes.to_der())
+
+def do_remove_naa(pes: ProfileElementSequence, opts):
+ if not opts.naa_type in NAAs:
+ raise ValueError('unsupported NAA type %s' % opts.naa_type)
+ naa = NAAs[opts.naa_type]
+ print("Removing NAAs of type '%s' from Sequence..." % opts.naa_type)
+ pes.remove_naas_of_type(naa)
+ print("Writing %u PEs to file '%s'..." % (len(pes.pe_list), opts.output_file))
+ with open(opts.output_file, 'wb') as f:
+ f.write(pes.to_der())
+
+
+if __name__ == '__main__':
+ opts = parser.parse_args()
+
+ with open(opts.INPUT_UPP, 'rb') as f:
+ pes = ProfileElementSequence.from_der(f.read())
+
+ print("Read %u PEs from file '%s'" % (len(pes.pe_list), opts.INPUT_UPP))
+
+ if opts.command == 'split':
+ do_split(pes, opts)
+ elif opts.command == 'dump':
+ do_dump(pes, opts)
+ elif opts.command == 'check':
+ do_check(pes, opts)
+ elif opts.command == 'remove-pe':
+ do_remove_pe(pes, opts)
+ elif opts.command == 'remove-naa':
+ do_remove_naa(pes, opts)
+ else:
+ parser.print_help(sys.stderr)
+ sys.exit(2)
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/37011?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I396bcd594e0628dfc26bd90233317a77e2f91b20
Gerrit-Change-Number: 37011
Gerrit-PatchSet: 1
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-MessageType: newchange
Attention is currently required from: laforge, lynxis lazus, osmith.
Hello Jenkins Builder, lynxis lazus, osmith,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/pysim/+/36960?usp=email
to look at the new patch set (#4).
The following approvals got outdated and were removed:
Code-Review+1 by lynxis lazus, Code-Review+1 by osmith, Verified+1 by Jenkins Builder
Change subject: esim.saip: Implement ProfileElement.header_name for more PE types
......................................................................
esim.saip: Implement ProfileElement.header_name for more PE types
We now cover all PE types as of PE_Definitions-3.3.1.asn
Change-Id: I37951a0441fe53fce7a329066aebd973389cb743
---
M pySim/esim/saip/__init__.py
1 file changed, 27 insertions(+), 0 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/60/36960/4
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36960?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I37951a0441fe53fce7a329066aebd973389cb743
Gerrit-Change-Number: 36960
Gerrit-PatchSet: 4
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: laforge <laforge(a)osmocom.org>
Gerrit-Attention: lynxis lazus <lynxis(a)fe80.eu>
Gerrit-MessageType: newpatchset
Attention is currently required from: dexter.
Hello Jenkins Builder, dexter,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/pysim/+/36974?usp=email
to look at the new patch set (#2).
The following approvals got outdated and were removed:
Verified-1 by Jenkins Builder
Change subject: add contrib/es9p_client: Perform ES9+ client functions like LPA+eUICC
......................................................................
add contrib/es9p_client: Perform ES9+ client functions like LPA+eUICC
This tool can be used to test the SM-DP+. It implements the full dance
of all HTTPs API operations to get to the downloadProfile, and will
decrypt the BPP to the UPP, which is then subsequently stored as file on
disk.
Needless to say, this will only work if you have an eUICC certificate +
private key that is compatible with the CI of your SM-DP+.
Change-Id: Idf8881e82f9835f5221c58b78ced9937cf5fb520
---
A contrib/es9p_client.py
M pySim/esim/es8p.py
2 files changed, 339 insertions(+), 1 deletion(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/74/36974/2
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36974?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: Idf8881e82f9835f5221c58b78ced9937cf5fb520
Gerrit-Change-Number: 36974
Gerrit-PatchSet: 2
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newpatchset
Attention is currently required from: dexter.
Hello Jenkins Builder, dexter, fixeria, osmith,
I'd like you to reexamine a change. Please visit
https://gerrit.osmocom.org/c/pysim/+/36931?usp=email
to look at the new patch set (#6).
The following approvals got outdated and were removed:
Verified+1 by Jenkins Builder
The change is no longer submittable: Verified is unsatisfied now.
Change subject: global_platform/euicc: Implement obtaining SCP keys from CardKeyProvider
......................................................................
global_platform/euicc: Implement obtaining SCP keys from CardKeyProvider
Now that CardKeyProvider is capable of storing key materials
transport-key-encrypted, we can use this functionality to look up the
SCP02 / SCP03 key material for a given security domain.
This patch implements this for the ISD-R and ECASD using a look-up by
EID inside the CSV.
Change-Id: I2a21f031ab8af88019af1b8390612678b9b35880
---
M pySim/euicc.py
M pySim/global_platform/__init__.py
2 files changed, 53 insertions(+), 8 deletions(-)
git pull ssh://gerrit.osmocom.org:29418/pysim refs/changes/31/36931/6
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36931?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I2a21f031ab8af88019af1b8390612678b9b35880
Gerrit-Change-Number: 36931
Gerrit-PatchSet: 6
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: dexter <pmaier(a)sysmocom.de>
Gerrit-Reviewer: fixeria <vyanitskiy(a)sysmocom.de>
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-Attention: dexter <pmaier(a)sysmocom.de>
Gerrit-MessageType: newpatchset
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36959?usp=email )
Change subject: pySim.esim.saip.validation: Ensure unique PE identification value
......................................................................
pySim.esim.saip.validation: Ensure unique PE identification value
Change-Id: I37b9eb4cfb74de79b0493986d976c8a5f8ccd8ea
---
M pySim/esim/saip/validation.py
1 file changed, 15 insertions(+), 0 deletions(-)
Approvals:
osmith: Looks good to me, but someone else must approve
Jenkins Builder: Verified
laforge: Looks good to me, approved
diff --git a/pySim/esim/saip/validation.py b/pySim/esim/saip/validation.py
index f9f5773..c253b7a 100644
--- a/pySim/esim/saip/validation.py
+++ b/pySim/esim/saip/validation.py
@@ -95,6 +95,12 @@
if 'profile-a-p256' in m_svcs and not ('usim' in m_svcs or 'isim' in m_svcs):
raise ProfileError('profile-a-p256 mandatory, but no usim or isim')
+ def check_identification_unique(self, pes: ProfileElementSequence):
+ """Ensure that each PE has a unique identification value."""
+ id_list = [pe.header['identification'] for pe in pes.pe_list if pe.header]
+ if len(id_list) != len(set(id_list)):
+ raise ProfileError('PE identification values are not unique')
+
FileChoiceList = List[Tuple]
class FileError(ProfileError):
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36959?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I37b9eb4cfb74de79b0493986d976c8a5f8ccd8ea
Gerrit-Change-Number: 36959
Gerrit-PatchSet: 4
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-MessageType: merged
laforge has submitted this change. ( https://gerrit.osmocom.org/c/pysim/+/36957?usp=email )
Change subject: esim.saip: Introduce ProfileElement derived classes
......................................................................
esim.saip: Introduce ProfileElement derived classes
It's rather useful to have derived classes implementing specific
functions related to that SAIP profile type. Let's introruce that
concept and a first example for securityDomain, where methods allow
checking/adding/removing support for SCPs.
Change-Id: I0929cc704b2aabddbc2ddee79ab8b674b1ed4691
---
M pySim/esim/saip/__init__.py
1 file changed, 62 insertions(+), 8 deletions(-)
Approvals:
osmith: Looks good to me, but someone else must approve
laforge: Looks good to me, approved
Jenkins Builder: Verified
diff --git a/pySim/esim/saip/__init__.py b/pySim/esim/saip/__init__.py
index b8e41ce..fc86b63 100644
--- a/pySim/esim/saip/__init__.py
+++ b/pySim/esim/saip/__init__.py
@@ -26,6 +26,8 @@
from pySim.construct import build_construct
from pySim.esim import compile_asn1_subdir
from pySim.esim.saip import templates
+from pySim.tlv import BER_TLV_IE
+from pySim.global_platform.uicc import UiccSdInstallParams
asn1 = compile_asn1_subdir('saip')
@@ -134,6 +136,9 @@
"""Class representing a Profile Element (PE) within a SAIP Profile."""
FILE_BEARING = ['mf', 'cd', 'telecom', 'usim', 'opt-usim', 'isim', 'opt-isim', 'phonebook', 'gsm-access',
'csim', 'opt-csim', 'eap', 'df-5gs', 'df-saip', 'df-snpn', 'df-5gprose', 'iot', 'opt-iot']
+ def __init__(self, decoded = None):
+ self.decoded = decoded
+
def _fixup_sqnInit_dec(self) -> None:
"""asn1tools has a bug when working with SEQUENCE OF that have DEFAULT values. Let's work around
this."""
@@ -161,12 +166,6 @@
# none of the fields were initialized with a non-default (non-zero) value, so we can skip it
del self.decoded['sqnInit']
- def parse_der(self, der: bytes) -> None:
- """Parse a sequence of PE and store the result in instance attributes."""
- self.type, self.decoded = asn1.decode('ProfileElement', der)
- # work around asn1tools bug regarding DEFAULT for a SEQUENCE OF
- self._fixup_sqnInit_dec()
-
@property
def header_name(self) -> str:
"""Return the name of the header field within the profile element."""
@@ -195,12 +194,24 @@
@classmethod
def from_der(cls, der: bytes) -> 'ProfileElement':
"""Construct an instance from given raw, DER encoded bytes."""
- inst = cls()
- inst.parse_der(der)
+ pe_type, decoded = asn1.decode('ProfileElement', der)
+ if pe_type == 'securityDomain':
+ inst = ProfileElementSD(decoded)
+ else:
+ inst = ProfileElement(decoded)
+ inst.type = pe_type
+ # work around asn1tools bug regarding DEFAULT for a SEQUENCE OF
+ inst._fixup_sqnInit_dec()
+ # run any post-decoder a derived class may have
+ if hasattr(inst, '_post_decode'):
+ inst._post_decode()
return inst
def to_der(self) -> bytes:
"""Build an encoded DER representation of the instance."""
+ # run any pre-encoder a derived class may have
+ if hasattr(self, '_pre_encode'):
+ self._pre_encode()
# work around asn1tools bug regarding DEFAULT for a SEQUENCE OF
self._fixup_sqnInit_enc()
return asn1.encode('ProfileElement', (self.type, self.decoded))
@@ -208,6 +219,35 @@
def __str__(self) -> str:
return self.type
+class ProfileElementSD(ProfileElement):
+ """Class representing a securityDomain ProfileElement."""
+ type = 'securityDomain'
+
+ class C9(BER_TLV_IE, tag=0xC9, nested=UiccSdInstallParams):
+ pass
+
+ def _post_decode(self):
+ self.usip = self.C9()
+ self.usip.from_bytes(self.decoded['instance']['applicationSpecificParametersC9'])
+
+ def _pre_encode(self):
+ self.decoded['instance']['applicationSpecificParametersC9'] = self.usip.to_bytes()
+
+ def has_scp(self, scp: int) -> bool:
+ """Determine if SD Installation parameters already specify given SCP."""
+ return self.usip.nested_collection.has_scp(scp)
+
+ def add_scp(self, scp: int, i: int):
+ """Add given SCP (and i parameter) to list of SCP of the Security Domain Install Params.
+ Example: add_scp(0x03, 0x70) for SCP03, or add_scp(0x02, 0x55) for SCP02."""
+ self.usip.nested_collection.add_scp(scp, i)
+ self._pre_encode()
+
+ def remove_scp(self, scp: int):
+ """Remove given SCP from list of SCP of the Security Domain Install Params."""
+ self.usip.nested_collection.remove_scp(scp)
+ self._pre_encode()
+
def bertlv_first_segment(binary: bytes) -> Tuple[bytes, bytes]:
"""obtain the first segment of a binary concatenation of BER-TLV objects.
--
To view, visit https://gerrit.osmocom.org/c/pysim/+/36957?usp=email
To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings
Gerrit-Project: pysim
Gerrit-Branch: master
Gerrit-Change-Id: I0929cc704b2aabddbc2ddee79ab8b674b1ed4691
Gerrit-Change-Number: 36957
Gerrit-PatchSet: 3
Gerrit-Owner: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: laforge <laforge(a)osmocom.org>
Gerrit-Reviewer: osmith <osmith(a)sysmocom.de>
Gerrit-MessageType: merged