fix: restore MF after fast-init probing so eUICC cards init cleanly (v2.8.1)

With an eUICC in the reader the fast init raised SwMatchError twice and
fell back to the stock pysim init: pick_profile_no_reset() disables the
physical resets that CardProfile.match_with_card() normally performs, so
the successful SGP.22 probe leaves the ISD-R ADF selected.  RuntimeState
then selects MF by FID (00 A4 00 04 02 3F00) from within the ADF, which
this card answers with 6A82.

- _restore_mf_after_probe() re-selects MF after the profile pick: the
  cheap select keeps the reset-free path for normal cards, a physical
  reset covers cards that refuse the MF select from an ADF.
- The EID read restores with rs.reset() (soft reset, escalating to a
  physical reset) instead of rs.soft_reset(), which had the same trap.
- tests: FakeScc mf_select_error mode + two _restore_mf_after_probe
  cases (no reset / exactly one physical reset).
This commit is contained in:
2026-09-21 23:20:50 +03:00
parent a4d5415034
commit 69b4caf5d8
6 changed files with 42 additions and 6 deletions
+18 -1
View File
@@ -24,17 +24,21 @@ from pysim_simple_server.fastinit import (
class FakeScc:
def __init__(self):
def __init__(self, mf_select_error=False):
self.sel_ctrl = '0004'
self.cla_byte = '00'
self.resets = 0
self.selected = []
self.mf_select_error = mf_select_error
def reset_card(self):
self.resets += 1
def select_file(self, fid):
self.selected.append(fid)
if fid == '3f00' and self.mf_select_error:
# eUICC with the ISD-R ADF selected: MF is not selectable by FID
raise SwMatchError('6a82', '9000')
return ('', '9000')
def select_adf(self, aid):
@@ -56,6 +60,19 @@ class TestPickProfileNoReset(unittest.TestCase):
self.assertEqual(scc.resets, 1)
class TestRestoreMfAfterProbe(unittest.TestCase):
def test_normal_card_keeps_the_reset_free_path(self):
scc = FakeScc()
fastinit._restore_mf_after_probe(scc)
self.assertEqual(scc.resets, 0)
self.assertEqual(scc.selected[-1], '3f00')
def test_adf_selected_card_falls_back_to_a_physical_reset(self):
scc = FakeScc(mf_select_error=True)
fastinit._restore_mf_after_probe(scc)
self.assertEqual(scc.resets, 1)
class FakeLchan:
def __init__(self):
self.scc = types.SimpleNamespace(scp=object())