The audit's P2 items:
- ODD_INS: add 0x73 MANAGE SECURE CHANNEL and 0x75 TRANSACT DATA
(TS 102 221 Table 10.5); the tools/vs_reader.py mirror and the pinned
test are updated.
- 9E/9F are SW1: ISO 7816-3 10.3.3 Table 11 makes every 9X value SW1.
Remove the fabricated "extended-length procedure byte" that consumed
SW2 as a length and lost the status word.
- T=1: EOF-guard every block read, bound the M-bit chain with
T1_CHAIN_MAX, and drop the caller's duplicate chain loop -- it read the
next block after every I-block (usually the peer's R-block) and merged
the following I-block's INF into the packet. R/S blocks emit nothing;
the (possibly chained) I-block INF is the APDU payload.
- Parity: a packet containing a parity-error byte is emitted with
GSMTAP_FLAG_BAD_FCS (the CHKSUM annotation was invisible downstream),
with a log note when the exchange is otherwise clean.
- EOF guards: handle_atr (TA/TB/TC/TD, historical, TCK), handle_pps
(request/response fields incl. PPS1-3) and the T=1 block parser return
cleanly on a truncated capture instead of raising on None.
- Dead code: _edge_read was initialized True and never cleared, so the
ATR-based T=0 procedure loop (58 lines) and the 1.5-ETU guard branch
were unreachable. Remove the flag, both dead paths and the branch;
dedent the live loop (behavior unchanged).
- Samplerate scaling: _samples_for_us() replaces the hard-coded 16 MHz
thresholds -- start-bit deglitch (0.125 us), min_high floor (0.25 us)
and the ETU glitch floor (0.75 us). At 16 MHz the values are
unchanged.
Validation: 130/130 unit tests (13 new: 9E/9F SW1, parity BAD_FCS,
T=1 I/R/S blocks + M chain + truncations + one-block-per-step, PPS
truncations, truncated ATR TA, samplerate/ETU-floor vectors); the
10-trace suite is unchanged from v1.9.6 (identical APDU/CHKSUM/CONCAT/
BAD_FCS counts, RESULT: OK); compare_baseline.sh reports IDENTICAL.
VERSION -> 1.9.7.