forked from public/pysim
Compare commits
6 Commits
neels/saip3
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 25e43e1540 | |||
| 6e10da4c55 | |||
| 973d6eb2cc | |||
| 597f1e0398 | |||
| 45d37ed959 | |||
| 757c7d048e |
+30
-48
@@ -24,21 +24,21 @@ import traceback
|
|||||||
import re
|
import re
|
||||||
import cmd2
|
import cmd2
|
||||||
from packaging import version
|
from packaging import version
|
||||||
from cmd2 import style
|
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from pySim.log import PySimLogger
|
from pySim.log import PySimLogger
|
||||||
from osmocom.utils import auto_uint8
|
from osmocom.utils import auto_uint8
|
||||||
|
|
||||||
# cmd2 >= 2.3.0 has deprecated the bg/fg in favor of Bg/Fg :(
|
# cmd2 >= 3.0 replaced Fg + style() with Color + stylize()
|
||||||
if version.parse(cmd2.__version__) < version.parse("2.3.0"):
|
if version.parse(cmd2.__version__) >= version.parse("3.0.0"):
|
||||||
from cmd2 import fg, bg # pylint: disable=no-name-in-module
|
from cmd2 import Color, stylize # pylint: disable=no-name-in-module
|
||||||
RED = fg.red
|
RED = Color.RED
|
||||||
YELLOW = fg.yellow
|
YELLOW = Color.YELLOW
|
||||||
LIGHT_RED = fg.bright_red
|
LIGHT_RED = Color.BRIGHT_RED
|
||||||
LIGHT_GREEN = fg.bright_green
|
LIGHT_GREEN = Color.BRIGHT_GREEN
|
||||||
|
def style(text, fg=None, bg=None, bold=False): # pylint: disable=function-redefined
|
||||||
|
return stylize(text, fg) if fg else text
|
||||||
else:
|
else:
|
||||||
from cmd2 import Fg, Bg # pylint: disable=no-name-in-module
|
from cmd2 import style, Fg # pylint: disable=no-name-in-module
|
||||||
RED = Fg.RED
|
RED = Fg.RED
|
||||||
YELLOW = Fg.YELLOW
|
YELLOW = Fg.YELLOW
|
||||||
LIGHT_RED = Fg.LIGHT_RED
|
LIGHT_RED = Fg.LIGHT_RED
|
||||||
@@ -76,43 +76,19 @@ from pySim.app import init_card
|
|||||||
|
|
||||||
log = PySimLogger.get(Path(__file__).stem)
|
log = PySimLogger.get(Path(__file__).stem)
|
||||||
|
|
||||||
class Cmd2Compat(cmd2.Cmd):
|
class PysimApp(cmd2.Cmd):
|
||||||
"""Backwards-compatibility wrapper around cmd2.Cmd to support older and newer
|
|
||||||
releases. See https://github.com/python-cmd2/cmd2/blob/master/CHANGELOG.md"""
|
|
||||||
def run_editor(self, file_path: Optional[str] = None) -> None:
|
|
||||||
if version.parse(cmd2.__version__) < version.parse("2.0.0"):
|
|
||||||
return self._run_editor(file_path) # pylint: disable=no-member
|
|
||||||
else:
|
|
||||||
return super().run_editor(file_path) # pylint: disable=no-member
|
|
||||||
|
|
||||||
class Settable2Compat(cmd2.Settable):
|
|
||||||
"""Backwards-compatibility wrapper around cmd2.Settable to support older and newer
|
|
||||||
releases. See https://github.com/python-cmd2/cmd2/blob/master/CHANGELOG.md"""
|
|
||||||
def __init__(self, name, val_type, description, settable_object, **kwargs):
|
|
||||||
if version.parse(cmd2.__version__) < version.parse("2.0.0"):
|
|
||||||
super().__init__(name, val_type, description, **kwargs) # pylint: disable=no-value-for-parameter
|
|
||||||
else:
|
|
||||||
super().__init__(name, val_type, description, settable_object, **kwargs) # pylint: disable=too-many-function-args
|
|
||||||
|
|
||||||
class PysimApp(Cmd2Compat):
|
|
||||||
CUSTOM_CATEGORY = 'pySim Commands'
|
CUSTOM_CATEGORY = 'pySim Commands'
|
||||||
BANNER = """Welcome to pySim-shell!
|
BANNER = """Welcome to pySim-shell!
|
||||||
(C) 2021-2023 by Harald Welte, sysmocom - s.f.m.c. GmbH and contributors
|
(C) 2021-2023 by Harald Welte, sysmocom - s.f.m.c. GmbH and contributors
|
||||||
Online manual available at https://downloads.osmocom.org/docs/pysim/master/html/shell.html """
|
Online manual available at https://downloads.osmocom.org/docs/pysim/master/html/shell.html """
|
||||||
|
|
||||||
def __init__(self, verbose, card, rs, sl, ch, script=None):
|
def __init__(self, verbose, card, rs, sl, ch, script=None):
|
||||||
if version.parse(cmd2.__version__) < version.parse("2.0.0"):
|
|
||||||
kwargs = {'use_ipython': True}
|
|
||||||
else:
|
|
||||||
kwargs = {'include_ipy': True}
|
|
||||||
|
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
PySimLogger.setup(self.poutput, {logging.WARN: YELLOW})
|
PySimLogger.setup(self.poutput, {logging.WARN: YELLOW})
|
||||||
self._onchange_verbose('verbose', False, self.verbose)
|
self._onchange_verbose('verbose', False, self.verbose)
|
||||||
|
|
||||||
# pylint: disable=unexpected-keyword-arg
|
|
||||||
super().__init__(persistent_history_file='~/.pysim_shell_history', allow_cli_args=False,
|
super().__init__(persistent_history_file='~/.pysim_shell_history', allow_cli_args=False,
|
||||||
auto_load_commands=False, startup_script=script, **kwargs)
|
auto_load_commands=False, startup_script=script, include_ipy=True)
|
||||||
self.intro = style(self.BANNER, fg=RED)
|
self.intro = style(self.BANNER, fg=RED)
|
||||||
self.default_category = 'pySim-shell built-in commands'
|
self.default_category = 'pySim-shell built-in commands'
|
||||||
self.card = None
|
self.card = None
|
||||||
@@ -128,18 +104,24 @@ Online manual available at https://downloads.osmocom.org/docs/pysim/master/html/
|
|||||||
self.apdu_trace = False
|
self.apdu_trace = False
|
||||||
self.apdu_strict = False
|
self.apdu_strict = False
|
||||||
|
|
||||||
self.add_settable(Settable2Compat('numeric_path', bool, 'Print File IDs instead of names', self,
|
self.add_settable(cmd2.Settable('numeric_path', bool,
|
||||||
onchange_cb=self._onchange_numeric_path))
|
'Print File IDs instead of names',
|
||||||
self.add_settable(Settable2Compat('conserve_write', bool, 'Read and compare before write', self,
|
self, onchange_cb=self._onchange_numeric_path))
|
||||||
onchange_cb=self._onchange_conserve_write))
|
self.add_settable(cmd2.Settable('conserve_write', bool,
|
||||||
self.add_settable(Settable2Compat('json_pretty_print', bool, 'Pretty-Print JSON output', self))
|
'Read and compare before write',
|
||||||
self.add_settable(Settable2Compat('apdu_trace', bool, 'Trace and display APDUs exchanged with card', self,
|
self, onchange_cb=self._onchange_conserve_write))
|
||||||
onchange_cb=self._onchange_apdu_trace))
|
self.add_settable(cmd2.Settable('json_pretty_print', bool,
|
||||||
self.add_settable(Settable2Compat('apdu_strict', bool,
|
'Pretty-Print JSON output',
|
||||||
'Strictly apply APDU format according to ISO/IEC 7816-3, table 12', self))
|
self))
|
||||||
self.add_settable(Settable2Compat('verbose', bool,
|
self.add_settable(cmd2.Settable('apdu_trace', bool,
|
||||||
'Enable/disable verbose logging', self,
|
'Trace and display APDUs exchanged with card',
|
||||||
onchange_cb=self._onchange_verbose))
|
self, onchange_cb=self._onchange_apdu_trace))
|
||||||
|
self.add_settable(cmd2.Settable('apdu_strict', bool,
|
||||||
|
'Strictly apply APDU format according to ISO/IEC 7816-3, table 12',
|
||||||
|
self))
|
||||||
|
self.add_settable(cmd2.Settable('verbose', bool,
|
||||||
|
'Enable/disable verbose logging',
|
||||||
|
self, onchange_cb=self._onchange_verbose))
|
||||||
self.equip(card, rs)
|
self.equip(card, rs)
|
||||||
|
|
||||||
def equip(self, card, rs):
|
def equip(self, card, rs):
|
||||||
|
|||||||
+49
-38
@@ -300,6 +300,51 @@ class ADF_ARAM(CardADF):
|
|||||||
'major': v_major, 'minor': v_minor, 'patch': v_patch}}])
|
'major': v_major, 'minor': v_minor, 'patch': v_patch}}])
|
||||||
return ADF_ARAM.xceive_apdu_tlv(scc, '80cadf21', cmd_do, ResponseAramConfigDO)
|
return ADF_ARAM.xceive_apdu_tlv(scc, '80cadf21', cmd_do, ResponseAramConfigDO)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def store_ref_ar_do(scc, aid:Hexstr, aid_empty:bool, device_app_id:Hexstr, pkg_ref:str,
|
||||||
|
apdu_filter:Hexstr, apdu_never:bool, apdu_always:bool,
|
||||||
|
nfc_always:bool, nfc_never:bool, android_permissions:Hexstr):
|
||||||
|
# REF
|
||||||
|
ref_do_content = []
|
||||||
|
if aid is not None:
|
||||||
|
ref_do_content += [{'aid_ref_do': aid}]
|
||||||
|
elif aid_empty:
|
||||||
|
ref_do_content += [{'aid_ref_empty_do': None}]
|
||||||
|
ref_do_content += [{'dev_app_id_ref_do': device_app_id}]
|
||||||
|
if pkg_ref:
|
||||||
|
ref_do_content += [{'pkg_ref_do': {'package_name_string': pkg_ref}}]
|
||||||
|
# AR
|
||||||
|
ar_do_content = []
|
||||||
|
if apdu_never:
|
||||||
|
ar_do_content += [{'apdu_ar_do': {'generic_access_rule': 'never'}}]
|
||||||
|
elif apdu_always:
|
||||||
|
ar_do_content += [{'apdu_ar_do': {'generic_access_rule': 'always'}}]
|
||||||
|
elif apdu_filter:
|
||||||
|
if len(apdu_filter) % 16:
|
||||||
|
raise ValueError(f'Invalid non-modulo-16 length of APDU filter: {len(apdu_filter)}')
|
||||||
|
offset = 0
|
||||||
|
apdu_filter_list = []
|
||||||
|
while offset < len(apdu_filter):
|
||||||
|
apdu_filter_list += [{'header': apdu_filter[offset:offset+8],
|
||||||
|
'mask': apdu_filter[offset+8:offset+16]}]
|
||||||
|
offset += 16 # Move offset to the beginning of the next apdu_filter object
|
||||||
|
ar_do_content += [{'apdu_ar_do': {'apdu_filter': apdu_filter_list}}]
|
||||||
|
if nfc_never:
|
||||||
|
ar_do_content += [{'nfc_ar_do': {'nfc_event_access_rule': 'never'}}]
|
||||||
|
elif nfc_always:
|
||||||
|
ar_do_content += [{'nfc_ar_do': {'nfc_event_access_rule': 'always'}}]
|
||||||
|
if android_permissions:
|
||||||
|
ar_do_content += [{'perm_ar_do': {'permissions': android_permissions}}]
|
||||||
|
d = [{'ref_ar_do': [{'ref_do': ref_do_content}, {'ar_do': ar_do_content}]}]
|
||||||
|
csrado = CommandStoreRefArDO()
|
||||||
|
csrado.from_val_dict(d)
|
||||||
|
return ADF_ARAM.store_data(scc, csrado)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def aram_delete_all(scc):
|
||||||
|
deldo = CommandDelete()
|
||||||
|
return ADF_ARAM.store_data(scc, deldo)
|
||||||
|
|
||||||
@with_default_category('Application-Specific Commands')
|
@with_default_category('Application-Specific Commands')
|
||||||
class AddlShellCommands(CommandSet):
|
class AddlShellCommands(CommandSet):
|
||||||
def do_aram_get_all(self, _opts):
|
def do_aram_get_all(self, _opts):
|
||||||
@@ -344,48 +389,15 @@ class ADF_ARAM(CardADF):
|
|||||||
@cmd2.with_argparser(store_ref_ar_do_parse)
|
@cmd2.with_argparser(store_ref_ar_do_parse)
|
||||||
def do_aram_store_ref_ar_do(self, opts):
|
def do_aram_store_ref_ar_do(self, opts):
|
||||||
"""Perform STORE DATA [Command-Store-REF-AR-DO] to store a (new) access rule."""
|
"""Perform STORE DATA [Command-Store-REF-AR-DO] to store a (new) access rule."""
|
||||||
# REF
|
res_do = ADF_ARAM.store_ref_ar_do(self._cmd.lchan.scc, opts.aid, opts.aid_empty, opts.device_app_id,
|
||||||
ref_do_content = []
|
opts.pkg_ref, opts.apdu_filter, opts.apdu_never, opts.apdu_always,
|
||||||
if opts.aid is not None:
|
opts.nfc_always, opts.nfc_never, opts.android_permissions)
|
||||||
ref_do_content += [{'aid_ref_do': opts.aid}]
|
|
||||||
elif opts.aid_empty:
|
|
||||||
ref_do_content += [{'aid_ref_empty_do': None}]
|
|
||||||
ref_do_content += [{'dev_app_id_ref_do': opts.device_app_id}]
|
|
||||||
if opts.pkg_ref:
|
|
||||||
ref_do_content += [{'pkg_ref_do': {'package_name_string': opts.pkg_ref}}]
|
|
||||||
# AR
|
|
||||||
ar_do_content = []
|
|
||||||
if opts.apdu_never:
|
|
||||||
ar_do_content += [{'apdu_ar_do': {'generic_access_rule': 'never'}}]
|
|
||||||
elif opts.apdu_always:
|
|
||||||
ar_do_content += [{'apdu_ar_do': {'generic_access_rule': 'always'}}]
|
|
||||||
elif opts.apdu_filter:
|
|
||||||
if len(opts.apdu_filter) % 16:
|
|
||||||
raise ValueError(f'Invalid non-modulo-16 length of APDU filter: {len(opts.apdu_filter)}')
|
|
||||||
offset = 0
|
|
||||||
apdu_filter = []
|
|
||||||
while offset < len(opts.apdu_filter):
|
|
||||||
apdu_filter += [{'header': opts.apdu_filter[offset:offset+8],
|
|
||||||
'mask': opts.apdu_filter[offset+8:offset+16]}]
|
|
||||||
offset += 16 # Move offset to the beginning of the next apdu_filter object
|
|
||||||
ar_do_content += [{'apdu_ar_do': {'apdu_filter': apdu_filter}}]
|
|
||||||
if opts.nfc_always:
|
|
||||||
ar_do_content += [{'nfc_ar_do': {'nfc_event_access_rule': 'always'}}]
|
|
||||||
elif opts.nfc_never:
|
|
||||||
ar_do_content += [{'nfc_ar_do': {'nfc_event_access_rule': 'never'}}]
|
|
||||||
if opts.android_permissions:
|
|
||||||
ar_do_content += [{'perm_ar_do': {'permissions': opts.android_permissions}}]
|
|
||||||
d = [{'ref_ar_do': [{'ref_do': ref_do_content}, {'ar_do': ar_do_content}]}]
|
|
||||||
csrado = CommandStoreRefArDO()
|
|
||||||
csrado.from_val_dict(d)
|
|
||||||
res_do = ADF_ARAM.store_data(self._cmd.lchan.scc, csrado)
|
|
||||||
if res_do:
|
if res_do:
|
||||||
self._cmd.poutput_json(res_do.to_dict())
|
self._cmd.poutput_json(res_do.to_dict())
|
||||||
|
|
||||||
def do_aram_delete_all(self, _opts):
|
def do_aram_delete_all(self, _opts):
|
||||||
"""Perform STORE DATA [Command-Delete[all]] to delete all access rules."""
|
"""Perform STORE DATA [Command-Delete[all]] to delete all access rules."""
|
||||||
deldo = CommandDelete()
|
res_do = ADF_ARAM.aram_delete_all(self._cmd.lchan.scc)
|
||||||
res_do = ADF_ARAM.store_data(self._cmd.lchan.scc, deldo)
|
|
||||||
if res_do:
|
if res_do:
|
||||||
self._cmd.poutput_json(res_do.to_dict())
|
self._cmd.poutput_json(res_do.to_dict())
|
||||||
|
|
||||||
@@ -394,7 +406,6 @@ class ADF_ARAM(CardADF):
|
|||||||
(Proprietary feature that is specific to sysmocom's fork of Bertrand Martel’s ARA-M implementation.)"""
|
(Proprietary feature that is specific to sysmocom's fork of Bertrand Martel’s ARA-M implementation.)"""
|
||||||
self._cmd.lchan.scc.send_apdu_checksw('80e2900001A1', '9000')
|
self._cmd.lchan.scc.send_apdu_checksw('80e2900001A1', '9000')
|
||||||
|
|
||||||
|
|
||||||
# SEAC v1.1 Section 4.1.2.2 + 5.1.2.2
|
# SEAC v1.1 Section 4.1.2.2 + 5.1.2.2
|
||||||
sw_aram = {
|
sw_aram = {
|
||||||
'ARA-M': {
|
'ARA-M': {
|
||||||
|
|||||||
@@ -21,9 +21,11 @@ import io
|
|||||||
import re
|
import re
|
||||||
from typing import List, Tuple, Generator, Optional
|
from typing import List, Tuple, Generator, Optional
|
||||||
|
|
||||||
|
from construct.core import StreamError
|
||||||
from osmocom.tlv import camel_to_snake
|
from osmocom.tlv import camel_to_snake
|
||||||
from osmocom.utils import hexstr
|
from osmocom.utils import hexstr
|
||||||
from pySim.utils import enc_iccid, dec_iccid, enc_imsi, dec_imsi, h2b, b2h, rpad, sanitize_iccid
|
from pySim.utils import enc_iccid, dec_iccid, enc_imsi, dec_imsi, h2b, b2h, rpad, sanitize_iccid
|
||||||
|
from pySim.ts_31_102 import EF_AD
|
||||||
from pySim.ts_51_011 import EF_SMSP
|
from pySim.ts_51_011 import EF_SMSP
|
||||||
from pySim.esim.saip import param_source
|
from pySim.esim.saip import param_source
|
||||||
from pySim.esim.saip import ProfileElement, ProfileElementSD, ProfileElementSequence
|
from pySim.esim.saip import ProfileElement, ProfileElementSD, ProfileElementSequence
|
||||||
@@ -660,6 +662,72 @@ class SmspTpScAddr(ConfigurableParameter):
|
|||||||
yield { cls.name: cls.tuple_to_str((international, digits)) }
|
yield { cls.name: cls.tuple_to_str((international, digits)) }
|
||||||
|
|
||||||
|
|
||||||
|
class MncLen(EnumParam):
|
||||||
|
"""MNC length. Sets only the MNC length field in EF.AD (Administrative Data).
|
||||||
|
Accepted values: integer 2 or 3, digit strings '2' or '3', or enum names 'MNC2'/'MNC3'.
|
||||||
|
"""
|
||||||
|
name = 'MNC-LEN'
|
||||||
|
example_input = '2'
|
||||||
|
default_source = param_source.ConstantSource
|
||||||
|
|
||||||
|
class Values(enum.IntEnum):
|
||||||
|
MNC2 = 2
|
||||||
|
MNC3 = 3
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def validate_val(cls, val):
|
||||||
|
if isinstance(val, str) and val.isdigit():
|
||||||
|
val = int(val)
|
||||||
|
return super().validate_val(val)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_f_ad(cls, pe: ProfileElement):
|
||||||
|
if not hasattr(pe, 'files'):
|
||||||
|
return None
|
||||||
|
f_ad = pe.files.get('ef-ad', None)
|
||||||
|
if f_ad and f_ad.body:
|
||||||
|
return f_ad
|
||||||
|
return None
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _decode_f_ad(cls, f_ad):
|
||||||
|
try:
|
||||||
|
ef_ad_dec = EF_AD().decode_bin(f_ad.body)
|
||||||
|
except StreamError:
|
||||||
|
return None
|
||||||
|
if 'mnc_len' not in ef_ad_dec:
|
||||||
|
return None
|
||||||
|
return ef_ad_dec
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def apply_val(cls, pes: ProfileElementSequence, val: int):
|
||||||
|
for pe in pes.get_pes_for_type('usim'):
|
||||||
|
f_ad = cls._get_f_ad(pe)
|
||||||
|
if f_ad is None:
|
||||||
|
continue
|
||||||
|
# decode existing values
|
||||||
|
ef_ad_dec = cls._decode_f_ad(f_ad)
|
||||||
|
if ef_ad_dec is None:
|
||||||
|
continue
|
||||||
|
# change mnc_len
|
||||||
|
ef_ad_dec['mnc_len'] = val
|
||||||
|
# re-encode into the File body
|
||||||
|
f_ad.body = EF_AD().encode_bin(ef_ad_dec)
|
||||||
|
pe.file2pe(f_ad)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def get_values_from_pes(cls, pes: ProfileElementSequence):
|
||||||
|
for pe in pes.get_pes_for_type('usim'):
|
||||||
|
f_ad = cls._get_f_ad(pe)
|
||||||
|
if f_ad is None:
|
||||||
|
continue
|
||||||
|
ef_ad_dec = cls._decode_f_ad(f_ad)
|
||||||
|
if ef_ad_dec is None:
|
||||||
|
continue
|
||||||
|
mnc_len = ef_ad_dec.get('mnc_len')
|
||||||
|
yield { cls.name: str(mnc_len) }
|
||||||
|
|
||||||
|
|
||||||
class SdKey(BinaryParam):
|
class SdKey(BinaryParam):
|
||||||
"""Configurable Security Domain (SD) Key. Value is presented as bytes.
|
"""Configurable Security Domain (SD) Key. Value is presented as bytes.
|
||||||
Non-abstract implementations are generated in SdKey.generate_sd_key_classes"""
|
Non-abstract implementations are generated in SdKey.generate_sd_key_classes"""
|
||||||
|
|||||||
+10
-2
@@ -24,7 +24,15 @@
|
|||||||
#
|
#
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
from cmd2 import style
|
import cmd2
|
||||||
|
from packaging import version
|
||||||
|
|
||||||
|
if version.parse(cmd2.__version__) >= version.parse("3.0.0"):
|
||||||
|
from cmd2 import stylize as _stylize # pylint: disable=no-name-in-module
|
||||||
|
def _style(text, fg=None): # pylint: disable=function-redefined
|
||||||
|
return _stylize(text, fg) if fg else text
|
||||||
|
else: # cmd2>=2.6.2
|
||||||
|
from cmd2 import style as _style # pylint: disable=no-name-in-module
|
||||||
|
|
||||||
class _PySimLogHandler(logging.Handler):
|
class _PySimLogHandler(logging.Handler):
|
||||||
def __init__(self, log_callback):
|
def __init__(self, log_callback):
|
||||||
@@ -121,7 +129,7 @@ class PySimLogger:
|
|||||||
if isinstance(color, str):
|
if isinstance(color, str):
|
||||||
PySimLogger.print_callback(color + formatted_message + "\033[0m")
|
PySimLogger.print_callback(color + formatted_message + "\033[0m")
|
||||||
else:
|
else:
|
||||||
PySimLogger.print_callback(style(formatted_message, fg = color))
|
PySimLogger.print_callback(_style(formatted_message, fg = color))
|
||||||
else:
|
else:
|
||||||
PySimLogger.print_callback(formatted_message)
|
PySimLogger.print_callback(formatted_message)
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,7 +1,7 @@
|
|||||||
pyscard
|
pyscard
|
||||||
pyserial
|
pyserial
|
||||||
pytlv
|
pytlv
|
||||||
cmd2>=2.6.2,<3.0
|
cmd2>=2.6.2,<4.0
|
||||||
jsonpath-ng
|
jsonpath-ng
|
||||||
construct>=2.10.70
|
construct>=2.10.70
|
||||||
bidict
|
bidict
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ setup(
|
|||||||
"pyscard",
|
"pyscard",
|
||||||
"pyserial",
|
"pyserial",
|
||||||
"pytlv",
|
"pytlv",
|
||||||
"cmd2 >= 1.5.0, < 3.0",
|
"cmd2 >= 2.6.2, < 4.0",
|
||||||
"jsonpath-ng",
|
"jsonpath-ng",
|
||||||
"construct >= 2.10.70",
|
"construct >= 2.10.70",
|
||||||
"bidict",
|
"bidict",
|
||||||
|
|||||||
@@ -267,6 +267,15 @@ class ConfigurableParameterTest(unittest.TestCase):
|
|||||||
'11111111111111111111111111111111'
|
'11111111111111111111111111111111'
|
||||||
'22222222222222222222222222222222'),
|
'22222222222222222222222222222222'),
|
||||||
|
|
||||||
|
Paramtest(param_cls=p13n.MncLen,
|
||||||
|
val='2',
|
||||||
|
expect_clean_val=2,
|
||||||
|
expect_val='2'),
|
||||||
|
Paramtest(param_cls=p13n.MncLen,
|
||||||
|
val=3,
|
||||||
|
expect_clean_val=3,
|
||||||
|
expect_val='3'),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
for sdkey_cls in (
|
for sdkey_cls in (
|
||||||
|
|||||||
@@ -163,6 +163,14 @@ ok: TS48v5_SAIP2.1A_NoBERTLV.der MilenageXoringConstants(val= b'\xaa\xaa\xaa\xaa
|
|||||||
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
||||||
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.1A_NoBERTLV.der MncLen(val= '2':str)
|
||||||
|
clean_val= 2:int
|
||||||
|
read_back_val= {'MNC-LEN': '2'}:{str}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.1A_NoBERTLV.der MncLen(val= 3:int)
|
||||||
|
clean_val= 3:int
|
||||||
|
read_back_val= {'MNC-LEN': '3'}:{str}
|
||||||
|
|
||||||
ok: TS48v5_SAIP2.1A_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
ok: TS48v5_SAIP2.1A_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
||||||
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
||||||
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
||||||
@@ -855,6 +863,14 @@ ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MilenageXoringConstants(val= b'\xaa\xaa\xaa\x
|
|||||||
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
||||||
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MncLen(val= '2':str)
|
||||||
|
clean_val= 2:int
|
||||||
|
read_back_val= {'MNC-LEN': '2'}:{str}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.3_BERTLV_SUCI.der MncLen(val= 3:int)
|
||||||
|
clean_val= 3:int
|
||||||
|
read_back_val= {'MNC-LEN': '3'}:{str}
|
||||||
|
|
||||||
ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
ok: TS48v5_SAIP2.3_BERTLV_SUCI.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
||||||
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
||||||
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
||||||
@@ -1547,6 +1563,14 @@ ok: TS48v5_SAIP2.1B_NoBERTLV.der MilenageXoringConstants(val= b'\xaa\xaa\xaa\xaa
|
|||||||
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
||||||
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.1B_NoBERTLV.der MncLen(val= '2':str)
|
||||||
|
clean_val= 2:int
|
||||||
|
read_back_val= {'MNC-LEN': '2'}:{str}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.1B_NoBERTLV.der MncLen(val= 3:int)
|
||||||
|
clean_val= 3:int
|
||||||
|
read_back_val= {'MNC-LEN': '3'}:{str}
|
||||||
|
|
||||||
ok: TS48v5_SAIP2.1B_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
ok: TS48v5_SAIP2.1B_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
||||||
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
||||||
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
||||||
@@ -2239,6 +2263,14 @@ ok: TS48v5_SAIP2.3_NoBERTLV.der MilenageXoringConstants(val= b'\xaa\xaa\xaa\xaa\
|
|||||||
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
clean_val= b'\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xbb\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\xcc\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11""""""""""""""""':bytes
|
||||||
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
read_back_val= {'MilenageXOR': 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccc1111111111111111111111111111111122222222222222222222222222222222'}:{hexstr}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.3_NoBERTLV.der MncLen(val= '2':str)
|
||||||
|
clean_val= 2:int
|
||||||
|
read_back_val= {'MNC-LEN': '2'}:{str}
|
||||||
|
|
||||||
|
ok: TS48v5_SAIP2.3_NoBERTLV.der MncLen(val= 3:int)
|
||||||
|
clean_val= 3:int
|
||||||
|
read_back_val= {'MNC-LEN': '3'}:{str}
|
||||||
|
|
||||||
ok: TS48v5_SAIP2.3_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
ok: TS48v5_SAIP2.3_NoBERTLV.der SdKeyScp02Kvn20AesDek(val= '01020304050607080910111213141516':str)
|
||||||
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
clean_val= b'\x01\x02\x03\x04\x05\x06\x07\x08\t\x10\x11\x12\x13\x14\x15\x16':bytes
|
||||||
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
read_back_val= {'SCP02-KVN20-AES-DEK': '01020304050607080910111213141516'}:{hexstr}
|
||||||
|
|||||||
Reference in New Issue
Block a user