Commit Graph

63 Commits

Author SHA1 Message Date
catarrh 7ece8a531c Response parser: add TS 51.011 SIM status word families; v1.9.6
OTA inner-APDU SWs from SIM-domain applications surfaced as 'Unknown
status word' (e.g. 9404 on a failed SELECT inside an authenticated
B00000 packet). SW_MAP.generic gains the complete TS 51.011 §9.4
families, so they decode in every resp-cmd context:

- 9200/9240 memory management (retry / memory problem)
- 9400/9402/9404/9408 referencing management (no EF selected,
  out of range, file ID/pattern not found, file inconsistent)
- 9802/9804/9808/9810/9840/9850 security management (CHV/access-
  condition/invalidation contradictions and blocked states; 9850
  also added to generic alongside its gp/uicc copy)
- 9EXX/9FXX data-download error length / response length wildcards

Exact keys safely coexist with the 92XX proactive wildcard (exact
match wins). TS 102 221 sweep found no further stragglers: 63C0-C9
PIN retry counters are covered by the existing 63CX wildcard.

Secured packet page: enforce fresh packet per send
- any change to APDU/TAR/CNTR/keys/padding/SPI now clears the secured
  packet textarea via spInvalidate(), so Send cannot reuse a stale
  packet ('No secured packet to send' guards the path)
- on por_ok the CNTR field auto-increments (10-digit hex normalized,
  wraps modulo 2^40) and the textarea clears; security-error verdicts
  leave both untouched for retry after fixing the cause

SIM/USIM SELECT: P1/P2 per spec + live RFM idioms
- USIM FID selects requested no response data (P2=0C) - that coding is
  reserved for the select-MF-by-empty-data special case; ordinary FID
  selects now request the FCP template (P2=04) with Le='00' per
  TS 102 221 Table 11.2 / pySim sel_ctrl convention; preset tables
  fixed in both genSimUsim and updateP1P2Display
- path method gains base selector: from MF (P1=08) / from current DF
  (P1=09) - reproduces the dominant live RFM idiom 09/0C
- 'silent' checkbox on fid/path/chain emits P2=0C without Le for hops
  where the FCI is not needed
- chain syntax gains GET RESPONSE hops: 'C0' emits CLA C0 00 00 00 and
  'C0:NN' sets explicit Le, enabling classic SELECT -> 9FXX ->
  GET RESPONSE pairs in a single secured packet so the PoR carries the
  actual FCI/response bytes instead of a bare length SW
- SW dictionary: 9FXX reworded to point at GET RESPONSE
- placeholders show the new chain syntax
- findings & backport decisions written to ~/WSL/RFM_notes.md

response_map.test.js: +8 assertions across the new families.
sim.test.js: USIM FID expectation updated; silent/base/chain cases.
apdu_parse.test.js: live capture lines 1-3 as regression fixtures.
Version 1.9.5 -> 1.9.6 everywhere; SW cache otaman-v16 -> otaman-v17
2026-08-24 23:04:54 +03:00
catarrh 73f46e99c4 genSp: unciphered packets drop CPL prefix + prominent PoR status; v1.9.5
pySim encode_cmd transmits the 2-byte CPL only when ciphering is
applied; unciphered packets start at CHL. genSp always emitted it,
so every SPI1=0x00 packet diverged from the pySim reference at byte 0
(sp-verify MISMATCH) and carried a length octet pair real cards need
not expect.

- genSp output: bytesToHex(ciphering ? packet : packet.subarray(2));
  MAC input unchanged (still covers the virtual-CPL frame, matching
  pySim's sign-then-strip convention)
- Secured packet page: PoR verdict now rendered prominently in a
  dedicated text-base semibold line ('PoR: por_ok' green / other
  statuses red) above the small detail line; hidden when no PoR was
  requested or the ENVELOPE failed
- sp.test.js: three unciphered expectations updated to CHL-first form;
  ciphered vectors untouched (byte-identical)
- version 1.9.4 -> 1.9.5 everywhere; SW cache otaman-v15 -> otaman-v16
2026-08-24 20:55:00 +03:00
catarrh e607637782 Code review fixes: CB label, trailing newlines
- PARSE_INS CB: rename 'RETRIEVE DATA (GET DATA)' -> 'RETRIEVE DATA'
  (CA = GET DATA, CB = RETRIEVE DATA are separate commands per TS 102 221)
- Add trailing newlines to sim.test.js + response_map.test.js
2026-08-23 10:07:56 +03:00
catarrh 072e8fe08b C-APDU encoder features + GET STATUS E3 coverage; v1.9.2
SIM/USIM encoder (registry §2.3):
- New PIN commands: DISABLE '26' / ENABLE '28' (single FF-padded PIN,
  Lc=08) and UNBLOCK '2C' (unblock+new, Lc=10); dynamic field labels
- ACTIVATE/DEACTIVATE FILE target selection: Current EF (case 1),
  by FID (P1=00), path from MF (P1=08), path from current DF (P1=09)
  with Lc+FID/path data form
- LANG_RU entries for new labels

Tests:
- sim.test.js: new stub-DOM genSimUsim harness; exact-hex for all PIN
  ops, ACTIVATE/DEACTIVATE forms, SELECT Le rules, RECORD P1=00 rule
- response_map.test.js: lookupSw wildcards (91XX / 63CX), LIFECYCLE_MAP
  per GPC v2.3, PRIVILEGE_NAMES vs Tables 11-7/11-8/11-9

GET STATUS E3 template decoding verified already present
(TLV_TAG_NAMES + decodeTlvValue cover 4F/9F70/C5/CF/C4/CC/CE/84).

Version 1.9.1 -> 1.9.2, SW cache otaman-v12 -> otaman-v13
2026-08-22 23:54:49 +03:00
catarrh feeefa3018 C-APDU parser + Response parser alignment with updated spec registry
PARSE_INS: +24 command labels per TS 102 221 table 10.5 / TS 102 222 /
GPC (TERMINAL PROFILE, ENVELOPE, FETCH, TERMINAL RESPONSE, SEARCH RECORD,
INCREASE, RETRIEVE DATA, PUT/SET DATA, GET CHALLENGE, AUTHENTICATE odd
INS, SUSPEND UICC, TERMINAL CAPABILITY, MANAGE SECURE CHANNEL, TRANSACT
DATA, GET IDENTITY, EXCHANGE CAPABILITIES, MANAGE LSI, CREATE FILE,
RESIZE FILE 'D4' (registry fixes 'D8' typo), INITIALIZE UPDATE, PUT KEY,
MANAGE CHANNEL; DISABLE/ENABLE/UNBLOCK PIN). INS '88' relabelled
AUTHENTICATE per TS 102 221 §11.1.16.

describeP1P2: SELECT P2 response field per ETSI b5-b3 ('001' FCP /
'011' none); READ/UPDATE BINARY offset / SFI-mode descriptors.

Response parser maps:
- LIFECYCLE_MAP: SD PERSONALIZED is '1F'; '0F' = SECURED (card);
  '01' dual-context OP_READY (card) / LOADED (ELF)
- SW_MAP.uicc: add '91XX' wildcard (proactive lengths vary)
- SW_MAP.generic: add 6A85 / 6A89 / 6A8A; 63CX notes blocked/no-counter
- SW_MAP.gp: reword stale 6310 (P2=42 option was removed as RFU)
2026-08-22 23:39:50 +03:00
catarrh 71d2e80242 C-APDU parser: P1/P2 descriptors, INSTALL LV decode, structural fixes; v1.9.1
Parser labels (§8.3, verified against GPC v2.3 / TS 102 221 PDFs):
- describeP1P2: SELECT P1/P2 (FID/DF-name/path-MF/path-DF; FCP/no-data),
  READ/UPDATE RECORD modes (next/previous/absolute + SFI, P1-ignored note),
  GET STATUS P1 (ISD/Apps/ELF/ELF+Modules) and P2 formats,
  INSTALL P1 bit-aware roles ('for install + for make selectable'),
  SET STATUS P1 (80 ISD / 40 App-or-SSD / 60 SD+associated) with
  card states vs lock/unlock P2, VERIFY/CHANGE PIN ref

Parser structure (§8.4):
- describeInstallDataLv: exact-sum LV walker for all 5 INSTALL layouts
  with privilege bit names and params tag nesting (C9, EF->CA, EA->80);
  falls back to legacy TLV view when lengths do not sum exactly
- GET DATA: case-2 (P3=Le) vs case-4 (Lc + tag list + Le)
- SET STATUS data: 'ignored for ISD' / raw AID / legacy 4F-TLV labeled
- Trailing single byte consumed as Le at end of compact chain
- ACTIVATE/DEACTIVATE: case-1 (4 bytes), legacy empty-Lc, FID/path forms
- Expanded script C-APDU rows now decode into structured APDU nodes
- Compact matcher accepts CLA 84-87 (GP secure messaging)

Version 1.9.0 -> 1.9.1, SW cache otaman-v10 -> otaman-v11
2026-08-22 08:36:20 +03:00
catarrh 7870682f3d Spec-truth pass: decodeTextData disambiguation, privilege tables per GPC v2.3
decodeTextData: legacy no-DCS UCS2 text whose first byte is 00/04 was
misrouted into DCS-aware branches (e.g. 'HI' = 00480049 decoded as GSM7
garbage). Now: dcs=08 strict (fail = '?', no reinterpretation); ambiguous
lead byte 00/04 prefers whole-buffer UCS2 when >=8 hex chars, %4==0,
printable, uniform high bytes; else DCS-aware path; legacy fallback kept.

Privileges per GPC v2.3 Tables 11-7/11-8/11-9 (verified against PDF):
- decodePrivileges rewritten table-driven; fixes wrong byte-2 mapping
  (was: Global Lock/Final Application/Receipt Generation on wrong bits)
  and byte-1 Card Terminate/Card Reset swap
- Reverted 'Token Management' rename: spec uses 'Token Verification'
  (66x vs single Table 11-8 outlier); checkbox + parser restored
- PLAY TONE qualifiers aligned to TS 102 223 §8.6 exact wording

Registry docs/uicc/UICC_SPECS.md corrected from primary sources:
- SET STATUS P1: '20' app/suppl SD -> '40' (GPC Table 11-86)
- SELECT P2 response field is b4b3 ('01' FCP / '11' none), not b3b2b1
  (TS 102 221 Table 11.2)
2026-08-22 08:14:06 +03:00
catarrh 0fd91d7771 C-APDU parser + BER fixes: DCS prefix, qualifier tables, EFRMA refs, CLA labels; v1.9.0
Parser + BER constructor (TS 102 223 / TS 102 226):
- DCS byte: genBerPcValue prepends DCS to 8D (00=GSM7, 08=UCS2, 04=unpacked)
- decodeTextData: consume DCS first, legacy no-DCS fallback kept
- BER_QUAL.display['80']: 'Clear after delay' -> 'Wait for user to clear message'
- BER_QUAL.tone: 'Monotonous/Alternating' -> 'Vibrate alert' names
- describeProactiveCommand: map type byte -> correct BER_QUAL key
  (01->refresh, 21->display, 20->tone); proper command names
- parseActionRow: values 01-7F -> 'Reference to EFRMA record'
- parseOneApdu: CLA 84-87 -> 'GlobalPlatform (secure messaging)'
- PARSE_INS: added GET RESPONSE (INS C0)

Version: 1.8.1 -> 1.9.0, SW cache otaman-v9 -> otaman-v10
2026-08-21 22:53:16 +03:00
catarrh 288c2e5954 C-APDU constructor spec fixes (TS 102 221 / GPC v2.3 / TS 102 226)
SIM/USIM tab (TS 102 221):
- Record P2 modes: 04/06/02 -> 04/02/03; P1=00 for next/previous
- SELECT Le rules: USIM FID no Le, path/dfname P2=04+Le; SIM no Le
- Path placeholder: 3F007FFF6FC5 -> 7FFF6FC5
- ACTIVATE/DEACTIVATE: 5-byte -> 4-byte case-1
- VERIFY PIN: dedicated input, Lc=08, FF-pad to 8 bytes
- CHANGE PIN: old/new inputs, Lc=10, two 8-byte fields
- ERASE BINARY removed from USIM tab

RAM tab (GPC v2.3):
- INSTALL: all 5 variants rewritten to strict LV + Le 00
- ELF/Module AID inputs for install-install
- Privileges: 1 byte if only byte-1, else 3 bytes
- InstallParams: C9 00 + toolkit TLV (mandatory)
- LOAD/DELETE/GET STATUS: append Le 00
- GET STATUS P2: drop 40/42, keep 02/03/00
- GET DATA: 2F00/5031 -> case-4 5C00 data
- SET STATUS: raw AID (no 4F), ISD card states, P1=60
- EXT AUTH: CLA 84, P1 security level, Lc=10
- INT AUTH: CLA 00

Toolkit (TS 102 226):
- MSL: 01 <msl> -> 00 (no check) or 02 01 <msl>
- SIM CA wrapped in EF: C9 00 EF <len> CA...
- TAR length %3 validation
- Menu IDs <= 7F validation

Script Chaining (TS 102 226 Table 5.9a):
- Removed Script ID + Additional Data fields
- Emit strictly 83 01 <flags>
- Deleted generateScriptIdHint

Privilege label: Token Verification -> Token Management
2026-08-21 22:37:39 +03:00
catarrh 72b0116bad C-APDU Parser: client-side hex parser for APDU/expanded script decode
New 'Parser' subtab in C-APDU section. Detects format (compact C-APDU
chain, expanded AA/AE80 script) and renders collapsible tree with decoded
parameters. Key features:
- BER-TLV parser with multi-byte tag support and CR-bit handling
- Proactive command decoder (types from BER_QUAL, devices from BER_DEVICES)
- SIM/UICC toolkit parameter decoder (CA/EA/80)
- GSM7 text decode (7-bit packed, escape sequences)
- Best-effort UCS2/GSM7 text detection
- Compact C-APDU chain with implied-CLA support (SELECT + op chaining)
- 18 test cases from exchange vectors (apdu_parse.test.js)
2026-08-20 22:11:55 +03:00
catarrh e6602c40bf RAM constructor fixes: EA/CA nesting, access domain order, menu pairs, BER lengths, services byte (TS 102 226)
- UICC Toolkit tag 80 nested inside EA (EA 12 80 10 ...)
- ram-tk-mode value ea (was 80), label 'UICC Toolkit (Tag EA)'
- SIM (CA) access domain FIRST in payload, blank = 00
- Menu entries: 2×m pairs (i=1 first, i=m last, else 0000)
- CA/EA lengths via berLenStr() (supports 81xx long form)
- UICC trailing 'Maximum number of services' byte (ram-tk-services)
- DELETE: P1=00 fixed, mode in P2 (80E4 00 <mode> ...)
- STORE DATA: ram-enc 00/40/80/C0/E0 with correct labels
- LOAD: P1 fixed to 0x80 (last block)
- USIM SELECT: selP1 0x09 -> 0x00 (select by file id)
- ram.test.js: 11 exact-hex tests from exchange vectors
- v1.8.1, SW cache otaman-v9
2026-08-20 21:23:37 +03:00
catarrh 4a6a142c3d Expanded Format spec fixes: REFRESH qualifiers, Error Action forms, Script Chaining flags, CR-bit tags (TS 102 226)
- BER_QUAL.refresh: full TS 102 223 §8.6 table (00-0A)
- Error Action rebuilt as single select: Proactive (DISPLAY/PLAY TONE only) /
  No action (82 00) / EFRMA ref (82 01 xx) / Custom hex; drop bogus
  Action Type / Trigger Conditions / Retry Count UI
- buildBerPcHtml(allowed): no Custom option; typeBytes tone 31 -> 20
- DISPLAY TEXT Duration control emitting 84 02 <unit> <interval>
- File list tag 12 -> 92 (CR bit set)
- Script Chaining flags 01/11/02/03 + keep-across-reset checkbox (RFM)
- ber.test.js: exact-hex tests for all above (exchange vectors)
2026-08-20 21:13:41 +03:00
catarrh d2c292e5b8 Merge pysim-otaman-server into otaman (monorepo, v1.7.0)
- Move PWA into frontend/; server package at pysim_otaman_server/
- Server now serves the PWA (same origin -> no CORS/PNA): static file handler
  + --web-dir flag + injects window.PYSIM_EMBEDDED marker into index.html
- Frontend defaults to relative API base when embedded (pysimBase = '')
- Version 1.7.0 aligned: server.py VERSION, pyproject.toml, PWA header
- SW cache bump otaman-v7 -> otaman-v8
- Docs: combined README + docs/api.md endpoint reference; update links
- Fix stale package.json repository URL
2026-08-14 15:48:38 +03:00