laforge submitted this change.
saip-tool: Add new 'info' action to print general information
It will print something like this:
SAIP Profile Version: 2.1
Profile Type: 'GSMA Generic eUICC Test Profile'
ICCID: 8949449999999990023f
Mandatory Services: usim, isim, csim, javacard, usim-test-algorithm
NAAs: mf[1], usim[1], csim[1], isim[1]
NAA mf
NAA usim (a0000000871002ff49ff0589)
IMSI: 001010123456063
NAA csim
NAA isim (a0000000871004ff49ff0589)
Number of applications: 0
Change-Id: I107d457c3313a766229b569453c18a8d69134bec
---
M contrib/saip-tool.py
M pySim/esim/saip/__init__.py
2 files changed, 91 insertions(+), 3 deletions(-)
diff --git a/contrib/saip-tool.py b/contrib/saip-tool.py
index 9bbaddf..68072fa 100755
--- a/contrib/saip-tool.py
+++ b/contrib/saip-tool.py
@@ -54,6 +54,7 @@
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
+parser_info = subparsers.add_parser('info', help='Display information about the profile')
def do_split(pes: ProfileElementSequence, opts):
i = 0
@@ -136,6 +137,45 @@
with open(opts.output_file, 'wb') as f:
f.write(pes.to_der())
+def do_info(pes: ProfileElementSequence, opts):
+ def get_naa_count(pes: ProfileElementSequence) -> dict:
+ """return a dict with naa-type (usim, isim) as key and the count of NAA instances as value."""
+ ret = {}
+ for naa_type in pes.pes_by_naa:
+ ret[naa_type] = len(pes.pes_by_naa[naa_type])
+ return ret
+
+ pe_hdr_dec = pes.pe_by_type['header'][0].decoded
+ print()
+ print("SAIP Profile Version: %u.%u" % (pe_hdr_dec['major-version'], pe_hdr_dec['minor-version']))
+ print("Profile Type: '%s'" % pe_hdr_dec['profileType'])
+ print("ICCID: %s" % b2h(pe_hdr_dec['iccid']))
+ print("Mandatory Services: %s" % ', '.join(pe_hdr_dec['eUICC-Mandatory-services'].keys()))
+ print()
+ naa_strs = ["%s[%u]" % (k, v) for k, v in get_naa_count(pes).items()]
+ print("NAAs: %s" % ', '.join(naa_strs))
+ for naa_type in pes.pes_by_naa:
+ for naa_inst in pes.pes_by_naa[naa_type]:
+ first_pe = naa_inst[0]
+ adf_name = ''
+ if hasattr(first_pe, 'adf_name'):
+ adf_name = '(' + first_pe.adf_name + ')'
+ print("NAA %s %s" % (first_pe.type, adf_name))
+ if hasattr(first_pe, 'imsi'):
+ print("\tIMSI: %s" % first_pe.imsi)
+
+ # applications
+ print()
+ apps = pes.pe_by_type.get('application', [])
+ print("Number of applications: %u" % len(apps))
+ for app_pe in apps:
+ print("App Load Package AID: %s" % b2h(app_pe.decoded['loadBlock']['loadPackageAID']))
+ print("\tMandated: %s" % ('mandated' in app_pe.decoded['app-Header']))
+ print("\tLoad Block Size: %s" % len(app_pe.decoded['loadBlock']['loadBlockObject']))
+ for inst in app_pe.decoded.get('instanceList', []):
+ print("\tInstance AID: %s" % b2h(inst['instanceAID']))
+ pass
+
if __name__ == '__main__':
opts = parser.parse_args()
@@ -155,3 +195,5 @@
do_remove_pe(pes, opts)
elif opts.command == 'remove-naa':
do_remove_naa(pes, opts)
+ elif opts.command == 'info':
+ do_info(pes, opts)
diff --git a/pySim/esim/saip/__init__.py b/pySim/esim/saip/__init__.py
index ee2538c..278b5cf 100644
--- a/pySim/esim/saip/__init__.py
+++ b/pySim/esim/saip/__init__.py
@@ -22,7 +22,7 @@
import asn1tools
-from pySim.utils import bertlv_parse_tag, bertlv_parse_len, b2h, h2b
+from pySim.utils import bertlv_parse_tag, bertlv_parse_len, b2h, h2b, dec_imsi
from pySim.ts_102_221 import FileDescriptor
from pySim.construct import build_construct
from pySim.esim import compile_asn1_subdir
@@ -263,10 +263,15 @@
@classmethod
def from_der(cls, der: bytes) -> 'ProfileElement':
+ class4petype = {
+ 'securityDomain': ProfileElementSD,
+ 'usim': ProfileElementUSIM,
+ 'isim': ProfileElementISIM,
+ }
"""Construct an instance from given raw, DER encoded bytes."""
pe_type, decoded = asn1.decode('ProfileElement', der)
- if pe_type == 'securityDomain':
- inst = ProfileElementSD(decoded)
+ if pe_type in class4petype:
+ inst = class4petype[pe_type](decoded)
else:
inst = ProfileElement(decoded)
inst.type = pe_type
@@ -437,6 +442,22 @@
'uiccToolkitApplicationSpecificParametersField': h2b('01000001000000020112036C756500'),
}
+class ProfileElementUSIM(ProfileElement):
+ type = 'usim'
+ @property
+ def adf_name(self) -> str:
+ return b2h(self.decoded['adf-usim'][0][1]['dfName'])
+ @property
+ def imsi(self) -> Optional[str]:
+ f = File('ef-imsi', self.decoded['ef-imsi'])
+ return dec_imsi(b2h(f.stream.getvalue()))
+
+class ProfileElementISIM(ProfileElement):
+ type = 'isim'
+ @property
+ def adf_name(self) -> str:
+ return b2h(self.decoded['adf-isim'][0][1]['dfName'])
+
def bertlv_first_segment(binary: bytes) -> Tuple[bytes, bytes]:
"""obtain the first segment of a binary concatenation of BER-TLV objects.
Returns: tuple of first TLV and remainder."""
To view, visit change 37168. To unsubscribe, or for help writing mail filters, visit settings.