1 Commits

Author SHA1 Message Date
Philipp Maier
7d5df4329f pySim-shell_test/euicc: ensure test-profile is enabled
When testing commands like get_profile_info, enable_profile,
disable_profile or the commands to manage notifications, we
should ensure that the correct profile is enabled before
executing the actual testcase.

Change-Id: Ie57b0305876bc5001ab3a9c3a3b5711408161b74
2026-02-10 11:34:31 +01:00
9 changed files with 22 additions and 27 deletions

2
.gitignore vendored
View File

@@ -1,5 +1,5 @@
*.pyc
.*.sw?
.*.swp
/docs/_*
/docs/generated

View File

@@ -141,7 +141,7 @@ class SmppHandler:
tuple containing the last response data and the last status word as byte strings
"""
logger.info("C-APDU sending: %s...", b2h(apdu))
logger.info("C-APDU sending: %s..." % b2h(apdu))
# translate to Secured OTA RFM
secured = self.ota_dialect.encode_cmd(self.ota_keyset, self.tar, self.spi, apdu=apdu)
@@ -194,19 +194,19 @@ if __name__ == '__main__':
option_parser.add_argument('--tar', required=True, type=is_hexstr, help='Toolkit Application Reference')
option_parser.add_argument("--cntr_req", choices=CNTR_REQ.decmapping.values(), default='no_counter',
help="Counter requirement")
option_parser.add_argument('--no-ciphering', action='store_true', default=False, help='Disable ciphering')
option_parser.add_argument('--ciphering', default=True, type=bool, help='Enable ciphering')
option_parser.add_argument("--rc-cc-ds", choices=RC_CC_DS.decmapping.values(), default='cc',
help="message check (rc=redundency check, cc=crypt. checksum, ds=digital signature)")
option_parser.add_argument('--por-in-submit', action='store_true', default=False,
option_parser.add_argument('--por-in-submit', default=False, type=bool,
help='require PoR to be sent via SMS-SUBMIT')
option_parser.add_argument('--por-no-ciphering', action='store_true', default=False, help='Disable ciphering (PoR)')
option_parser.add_argument('--por-shall-be-ciphered', default=True, type=bool, help='require encrypted PoR')
option_parser.add_argument("--por-rc-cc-ds", choices=RC_CC_DS.decmapping.values(), default='cc',
help="PoR check (rc=redundency check, cc=crypt. checksum, ds=digital signature)")
option_parser.add_argument("--por_req", choices=POR_REQ.decmapping.values(), default='por_required',
help="Proof of Receipt requirements")
option_parser.add_argument('--src-addr', default='12', type=str, help='SMS source address (MSISDN)')
option_parser.add_argument('--dest-addr', default='23', type=str, help='SMS destination address (MSISDN)')
option_parser.add_argument('--timeout', default=10, type=int, help='Maximum response waiting time')
option_parser.add_argument('--src-addr', default='12', type=str, help='TODO')
option_parser.add_argument('--dest-addr', default='23', type=str, help='TODO')
option_parser.add_argument('--timeout', default=10, type=int, help='TODO')
option_parser.add_argument('-a', '--apdu', action='append', required=True, type=is_hexstr, help='C-APDU to send')
opts = option_parser.parse_args()
@@ -214,22 +214,18 @@ if __name__ == '__main__':
format='%(asctime)s %(levelname)s %(message)s',
datefmt='%Y-%m-%d %H:%M:%S')
if opts.kic_idx != opts.kid_idx:
logger.warning("KIC index (%s) and KID index (%s) are different (security violation, card should reject message)",
opts.kic_idx, opts.kid_idx)
ota_keyset = OtaKeyset(algo_crypt=opts.algo_crypt,
kic_idx=opts.kic_idx,
kic=h2b(opts.kic),
algo_auth=opts.algo_auth,
kid_idx=opts.kid_idx,
kid_idx=opts.kic_idx,
kid=h2b(opts.kid),
cntr=opts.cntr)
spi = {'counter' : opts.cntr_req,
'ciphering' : not opts.no_ciphering,
'ciphering' : opts.ciphering,
'rc_cc_ds': opts.rc_cc_ds,
'por_in_submit': opts.por_in_submit,
'por_shall_be_ciphered': not opts.por_no_ciphering,
'por_in_submit':opts.por_in_submit,
'por_shall_be_ciphered':opts.por_shall_be_ciphered,
'por_rc_cc_ds': opts.por_rc_cc_ds,
'por': opts.por_req}
apdu = h2b("".join(opts.apdu))

View File

@@ -54,8 +54,6 @@ def compile_asn1_subdir(subdir_name:str, codec='der'):
__ver = sys.version_info
if (__ver.major, __ver.minor) >= (3, 9):
for i in resources.files('pySim.esim').joinpath('asn1').joinpath(subdir_name).iterdir():
if not i.name.endswith('.asn'):
continue
asn_txt += i.read_text()
asn_txt += "\n"
#else:

View File

@@ -19,6 +19,7 @@ import abc
import requests
import logging
import json
from re import match
from typing import Optional
import base64
from twisted.web.server import Request
@@ -210,7 +211,7 @@ class JsonHttpApiFunction(abc.ABC):
# additional custom HTTP headers (server responses)
extra_http_res_headers = {}
def __new__(cls, *args, role = 'legacy_client', **kwargs):
def __new__(cls, *args, role = None, **kwargs):
"""
Args:
args: (see JsonHttpApiClient and JsonHttpApiServer)
@@ -220,13 +221,14 @@ class JsonHttpApiFunction(abc.ABC):
# Create a dictionary with the class attributes of this class (the properties listed above and the encode_
# decode_ methods below). The dictionary will not include any dunder/magic methods
cls_attr = {attr_name: getattr(cls, attr_name) for attr_name in dir(cls) if not attr_name.startswith('__')}
cls_attr = { attr_name: getattr(cls, attr_name) for attr_name in dir(cls) if not match("__.*__", attr_name) }
# Normal instantiation as JsonHttpApiFunction:
if len(args) == 0 and len(kwargs) == 0:
if len(args) == 0:
return type(cls.__name__, (abc.ABC,), cls_attr)()
# Instantiation as as JsonHttpApiFunction with a JsonHttpApiClient or JsonHttpApiServer base
role = kwargs.get('role', 'legacy_client')
if role == 'legacy_client':
# Deprecated: With the advent of the server role (JsonHttpApiServer) the API had to be changed. To maintain
# compatibility with existing code (out-of-tree) the original behaviour and API interface and behaviour had

View File

@@ -352,7 +352,6 @@ class SmspTpScAddr(ConfigurableParameter):
strip_chars = ' \t\r\n'
max_len = 21 # '+' and 20 digits
min_len = 1
example_input = '+49301234567'
@classmethod
def validate_val(cls, val):
@@ -628,7 +627,7 @@ class MilenageRotationConstants(BinaryParam, AlgoConfig):
name = 'MilenageRotation'
algo_config_key = 'rotationConstants'
allow_len = 5 # length in bytes (from BinaryParam)
example_input = '40 00 20 40 60'
example_input = '0a 0b 0c 0d 0e'
@classmethod
def validate_val(cls, val):

View File

@@ -181,7 +181,7 @@ class SeqNumber(BER_TLV_IE, tag=0x80):
class NotificationAddress(BER_TLV_IE, tag=0x0c):
_construct = Utf8Adapter(GreedyBytes)
class Iccid(BER_TLV_IE, tag=0x5a):
_construct = PaddedBcdAdapter(GreedyBytes)
_construct = BcdAdapter(GreedyBytes)
class NotificationMetadata(BER_TLV_IE, tag=0xbf2f, nested=[SeqNumber, ProfileMgmtOperation,
NotificationAddress, Iccid]):
pass

View File

@@ -15,7 +15,7 @@
},
{
"profile_info": {
"iccid": "8949449999999990031",
"iccid": "8949449999999990031f",
"isdp_aid": "a0000005591010ffffffff8900001200",
"profile_state": "disabled",
"service_provider_name": "OsmocomSPN",

View File

@@ -23,7 +23,7 @@ import os
import json
from utils import *
# This testcase requires a sysmoEUICC1-C2T with the test prfile TS48V1-B-UNIQUE (ICCID 8949449999999990031)
# This testcase requires a sysmoEUICC1-C2T with the test prfile TS48V1-B-UNIQUE (ICCID 8949449999999990031f)
# installed, and in disabled state. Also the profile must be installed in such a way that notifications are
# generated when the profile is disabled or enabled (ProfileMetadata)

View File

@@ -9,5 +9,5 @@ select ADF.ISD-R
enable_profile --iccid 89000123456789012341
# Generate two (additional) notifications by quickly enabeling the test profile
enable_profile --iccid 8949449999999990031
enable_profile --iccid 8949449999999990031f
enable_profile --iccid 89000123456789012341