saip-tool: add ProfileElement class for application PE
The application profile element has no ProfileElement class yet, so let's create a ProfileElementApplication class and move the existing extract-apps code into a method of ProfileElementApplication. Change-Id: Iaa43036d388fbf1714c53cab1fc21092c4667a21
This commit is contained in:
@@ -19,14 +19,12 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import argparse
|
import argparse
|
||||||
import logging
|
import logging
|
||||||
import zipfile
|
|
||||||
from pathlib import Path as PlPath
|
from pathlib import Path as PlPath
|
||||||
from typing import List
|
from typing import List
|
||||||
from osmocom.utils import h2b, b2h, swap_nibbles
|
from osmocom.utils import h2b, b2h, swap_nibbles
|
||||||
|
|
||||||
from pySim.esim.saip import *
|
from pySim.esim.saip import *
|
||||||
from pySim.esim.saip.validation import CheckBasicStructure
|
from pySim.esim.saip.validation import CheckBasicStructure
|
||||||
from pySim import javacard
|
|
||||||
from pySim.pprint import HexBytesPrettyPrinter
|
from pySim.pprint import HexBytesPrettyPrinter
|
||||||
|
|
||||||
pp = HexBytesPrettyPrinter(indent=4,width=500)
|
pp = HexBytesPrettyPrinter(indent=4,width=500)
|
||||||
@@ -231,16 +229,9 @@ def do_extract_apps(pes:ProfileElementSequence, opts):
|
|||||||
apps = pes.pe_by_type.get('application', [])
|
apps = pes.pe_by_type.get('application', [])
|
||||||
for app_pe in apps:
|
for app_pe in apps:
|
||||||
package_aid = b2h(app_pe.decoded['loadBlock']['loadPackageAID'])
|
package_aid = b2h(app_pe.decoded['loadBlock']['loadPackageAID'])
|
||||||
|
|
||||||
fname = os.path.join(opts.output_dir, '%s-%s.%s' % (pes.iccid, package_aid, opts.format))
|
fname = os.path.join(opts.output_dir, '%s-%s.%s' % (pes.iccid, package_aid, opts.format))
|
||||||
load_block_obj = app_pe.decoded['loadBlock']['loadBlockObject']
|
|
||||||
print("Writing Load Package AID: %s to file %s" % (package_aid, fname))
|
print("Writing Load Package AID: %s to file %s" % (package_aid, fname))
|
||||||
if opts.format == 'ijc':
|
app_pe.to_file(fname)
|
||||||
with open(fname, 'wb') as f:
|
|
||||||
f.write(load_block_obj)
|
|
||||||
else:
|
|
||||||
with io.BytesIO(load_block_obj) as f, zipfile.ZipFile(fname, 'w') as z:
|
|
||||||
javacard.ijc_to_cap(f, z, package_aid)
|
|
||||||
|
|
||||||
def do_tree(pes:ProfileElementSequence, opts):
|
def do_tree(pes:ProfileElementSequence, opts):
|
||||||
pes.mf.print_tree()
|
pes.mf.print_tree()
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ import os
|
|||||||
from typing import Tuple, List, Optional, Dict, Union
|
from typing import Tuple, List, Optional, Dict, Union
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
import asn1tools
|
import asn1tools
|
||||||
|
import zipfile
|
||||||
|
from pySim import javacard
|
||||||
from osmocom.utils import b2h, h2b, Hexstr
|
from osmocom.utils import b2h, h2b, Hexstr
|
||||||
from osmocom.tlv import BER_TLV_IE, bertlv_parse_tag, bertlv_parse_len
|
from osmocom.tlv import BER_TLV_IE, bertlv_parse_tag, bertlv_parse_len
|
||||||
from osmocom.construct import build_construct, parse_construct, GreedyInteger
|
from osmocom.construct import build_construct, parse_construct, GreedyInteger
|
||||||
@@ -506,7 +508,7 @@ class ProfileElement:
|
|||||||
# TODO: cdmaParameter
|
# TODO: cdmaParameter
|
||||||
'securityDomain': ProfileElementSD,
|
'securityDomain': ProfileElementSD,
|
||||||
'rfm': ProfileElementRFM,
|
'rfm': ProfileElementRFM,
|
||||||
# TODO: application
|
'application': ProfileElementApplication,
|
||||||
# TODO: nonStandard
|
# TODO: nonStandard
|
||||||
'end': ProfileElementEnd,
|
'end': ProfileElementEnd,
|
||||||
'mf': ProfileElementMF,
|
'mf': ProfileElementMF,
|
||||||
@@ -1087,6 +1089,28 @@ class ProfileElementSSD(ProfileElementSD):
|
|||||||
'uiccToolkitApplicationSpecificParametersField': h2b('01000001000000020112036C756500'),
|
'uiccToolkitApplicationSpecificParametersField': h2b('01000001000000020112036C756500'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ProfileElementApplication(ProfileElement):
|
||||||
|
"""Class representing an application ProfileElement."""
|
||||||
|
type = 'application'
|
||||||
|
|
||||||
|
def __init__(self, decoded: Optional[dict] = None, **kwargs):
|
||||||
|
super().__init__(decoded, **kwargs)
|
||||||
|
|
||||||
|
def to_file(self, filename:str):
|
||||||
|
"""Write loadBlockObject contents of application ProfileElement to a .cap or .ijc file."""
|
||||||
|
|
||||||
|
load_package_aid = b2h(self.decoded['loadBlock']['loadPackageAID'])
|
||||||
|
load_block_object = self.decoded['loadBlock']['loadBlockObject']
|
||||||
|
|
||||||
|
if filename.lower().endswith('.cap'):
|
||||||
|
with io.BytesIO(load_block_object) as f, zipfile.ZipFile(filename, 'w') as z:
|
||||||
|
javacard.ijc_to_cap(f, z, load_package_aid)
|
||||||
|
elif filename.lower().endswith('.ijc'):
|
||||||
|
with open(filename, 'wb') as f:
|
||||||
|
f.write(load_block_object)
|
||||||
|
else:
|
||||||
|
raise ValueError('Invalid file type, file must either .cap or .ijc')
|
||||||
|
|
||||||
class ProfileElementRFM(ProfileElement):
|
class ProfileElementRFM(ProfileElement):
|
||||||
type = 'rfm'
|
type = 'rfm'
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user