v3.12.0: the card preset carries the card's CAT (USAT) release
The release selector lives in the preset rather than a global chip: presets already travel with the card (ICCID auto-selection, export/import), and the operations that will consume the release are preset-aware. - presets.py: the optional `release` field (4-18; empty = unspecified) joins PRESET_FIELDS; a value outside 4-18 is refused on save/import; the store schema version is 5. - catrelease.py: DEFAULT_RELEASE = 12 and preset_release() - the effective release is the preset's own value, else Rel-12 (the safe level for cards whose release is not known; an unset release never filters anything away). The PWA mirrors both (CAT_RELEASE_DEFAULT + presetRelease()), drift-guarded. - Cards tab: the editor's header row gains a compact CAT release select (unspecified / pre-Rel-6 stored as 5 / Rel-6 ... Rel-18); the empty option names the Rel-12 default and the tooltip explains the guard; the field is collected, cleared and restored with the other form fields. - Nothing filters yet: the Simulator's event parameters (stage 3) will use the effective release. - docs/api.md + help EN/RU updated; sw cache simple-v368.
This commit is contained in:
@@ -16,7 +16,9 @@ histories do not pin down - never filter on it.
|
||||
|
||||
The PWA mirrors this table (``CAT_RELEASE`` in frontend/index.html); the drift
|
||||
guard is tests/test_catrelease.py. Releases below 6 display as "pre-Rel-6"
|
||||
(``release_label``).
|
||||
(``release_label``). ``DEFAULT_RELEASE`` (Rel-12) is the release a card
|
||||
preset's empty ``release`` resolves to (``preset_release``) - the safe level
|
||||
for cards whose release is not known.
|
||||
"""
|
||||
|
||||
# Keyed by: events - the event code (TS 102 223 8.25 / TS 31.111 7.5);
|
||||
@@ -117,3 +119,24 @@ def release_label(rel):
|
||||
def item_release(kind, key, default=None):
|
||||
"""The introduction release of an item, or `default` when unknown."""
|
||||
return CAT_RELEASE.get(kind, {}).get(key, default)
|
||||
|
||||
|
||||
# The release a preset's empty `release` resolves to: Rel-12 is the safe level
|
||||
# for cards whose release is not known (the CAT items the tool sends stay
|
||||
# within what a modern card implements). Mirrored in the PWA
|
||||
# (`CAT_RELEASE_DEFAULT`), drift-guarded by tests/test_catrelease.py.
|
||||
DEFAULT_RELEASE = 12
|
||||
|
||||
|
||||
def preset_release(preset):
|
||||
"""The effective CAT release of a card preset.
|
||||
|
||||
The preset's own `release` when it names one (4-18), else the default.
|
||||
Empty or invalid values resolve to the default - an unset release must
|
||||
never filter anything away.
|
||||
"""
|
||||
try:
|
||||
rel = int((preset or {}).get('release') or 0)
|
||||
except (TypeError, ValueError):
|
||||
rel = 0
|
||||
return rel if 4 <= rel <= 18 else DEFAULT_RELEASE
|
||||
|
||||
@@ -24,6 +24,12 @@ The optional **card codes** (`pin1`/`puk1`/`pin2`/`puk2`/`adm`) are stored for
|
||||
later use by the card operations (nothing consumes them yet); the PIN/PUK codes
|
||||
are 4-8 decimal digits, the ADM key is hex or ASCII digits.
|
||||
|
||||
The optional **CAT (USAT) release** (`release`, 4-18) names the release the
|
||||
card implements: the release guard hides CAT items introduced after it (the
|
||||
Simulator's event parameters, see `catrelease`). Empty means unspecified and
|
||||
resolves to Rel-12 (`catrelease.DEFAULT_RELEASE`) - an unset release never
|
||||
filters anything away.
|
||||
|
||||
A preset holds **several keysets**; the b8..b5 nibble of KIc/KID numbers them
|
||||
(TS 102 225 5.1.2/A.2). Each keyset has its own KIc/KID keys and its own
|
||||
counter - "a dedicated counter shall be associated to each key version"
|
||||
@@ -63,14 +69,14 @@ from pathlib import Path
|
||||
|
||||
DEFAULT_DIR = '.pysim-simple-server'
|
||||
DEFAULT_FILENAME = 'card_presets.json'
|
||||
SCHEMA_VERSION = 4
|
||||
SCHEMA_VERSION = 5
|
||||
|
||||
# The fields a preset carries: the localStorage shape plus the id. The OTA key
|
||||
# material lives in `keysets` - the b8..b5 nibble of KIc/KID numbers them,
|
||||
# each with its own counter (TS 102 225 Annex A.1: "a dedicated counter shall
|
||||
# be associated to each key version"); the TAR table lives in `tars` (see
|
||||
# TAR_ROLES). The optional card codes (PIN/PUK/ADM) are stored for later use.
|
||||
PRESET_FIELDS = ('name', 'iccid', 'pin1', 'puk1', 'pin2', 'puk2', 'adm',
|
||||
PRESET_FIELDS = ('name', 'iccid', 'release', 'pin1', 'puk1', 'pin2', 'puk2', 'adm',
|
||||
'pskIdentity', 'pskKey')
|
||||
# The v3.8.0 flat key fields: converted into a single keyset on load/import.
|
||||
LEGACY_KEY_FIELDS = ('kic', 'kid', 'kicKey', 'kidKey', 'cntr')
|
||||
@@ -371,6 +377,9 @@ class PresetStore:
|
||||
raise PresetError('PSK identity and PSK key must be set together')
|
||||
if p['pskKey'] and not re.fullmatch(r'[0-9A-F]{32}', p['pskKey']):
|
||||
raise PresetError('PSK key must be 32 hex characters')
|
||||
if p['release'] and (not re.fullmatch(r'[0-9]{1,2}', p['release'])
|
||||
or not 4 <= int(p['release']) <= 18):
|
||||
raise PresetError('release must be 4-18 (or empty for the Rel-12 default)')
|
||||
for k in DIGIT_FIELDS:
|
||||
if p[k] and not re.fullmatch(r'[0-9]{4,8}', p[k]):
|
||||
raise PresetError('%s must be 4-8 decimal digits (or empty)'
|
||||
|
||||
@@ -32,7 +32,7 @@ from osmocom.tlv import BER_TLV_IE
|
||||
from osmocom.utils import rpad
|
||||
|
||||
|
||||
VERSION = '3.11.0'
|
||||
VERSION = '3.12.0'
|
||||
|
||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user