v3.23.2: the start-reset ordering fix (review follow-up)

A suite with start_reset and an incomplete SCP80 preset reset the card and
only then refused the start: the reset block ran before _test_preset_error.
The reset now runs after the preset checks - a run that cannot start must
not touch the card - and stays before the ADM gate, which must see the
post-reset card session (the reset bumps card_session, invalidating the ADM
latch).  The ICCID re-match stays with the reset block.

Test: an incomplete preset refuses with 400 and _card_reset_reinit is not
called.  846 frontend + 830 Python; sw cache simple-v415.
This commit is contained in:
2026-10-07 10:09:14 +03:00
parent 9ef1a59f2c
commit 9ad22f2e26
5 changed files with 30 additions and 14 deletions
+12 -11
View File
@@ -36,7 +36,7 @@ from osmocom.tlv import BER_TLV_IE
from osmocom.utils import rpad
VERSION = '3.23.1'
VERSION = '3.23.2'
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
@@ -7738,12 +7738,21 @@ class PysimHandler(BaseHTTPRequestHandler):
self._send_json(resp, 400)
self._log_resp(resp)
return
steps = [step for _entry, script in members for step in script['steps']]
if any(s['type'] == 'action' and s['kind'] == 'scp80' for s in steps):
err = _test_preset_error({'steps': steps}, preset)
if err:
resp = {'error': err}
self._send_json(resp, 400)
self._log_resp(resp)
return
reset_info = None
if suite.get('start_reset'):
# A suite may start with a card reset: the physical reset + the
# full equip re-initialization, so its scripts run against a
# freshly initialized card. This runs before the scp80 checks and
# the ADM gate: the card session changes, so the ADM latch is
# freshly initialized card. This runs after the preset checks - a
# run that cannot start must not reset the card - and before the
# ADM gate: the card session changes, so the ADM latch is
# re-verified against the post-reset card, and the ICCID must
# still match the run's preset (a reset can switch the active
# profile on an eUICC).
@@ -7777,14 +7786,6 @@ class PysimHandler(BaseHTTPRequestHandler):
self._send_json(resp, 400)
self._log_resp(resp)
return
steps = [step for _entry, script in members for step in script['steps']]
if any(s['type'] == 'action' and s['kind'] == 'scp80' for s in steps):
err = _test_preset_error({'steps': steps}, preset)
if err:
resp = {'error': err}
self._send_json(resp, 400)
self._log_resp(resp)
return
needed_adm = bool(suite.get('require_adm')) or any(
bool(script.get('require_adm')) for _entry, script in members)
ok, adm_info, adm_err = _ensure_adm(self.server, preset, needed_adm)