v3.26.0: per-TAR default keysets (the preset/SCP80/RAM rework)
Every preset TAR entry carries `keyset` (int 1-15) - the keyset every
operation addressed to that TAR uses: mandatory for any non-zero MSL
(the counters are keyset-linked), optional for MSL 00 (allowed: some
cards reject the no-security 00/00 KIc/KID form). The store fills it
automatically when the preset has a single keyset, the validation
refuses an entry naming an undefined keyset, and the schema is 6 (a v5
file loads leniently; editing it forces the fix).
The keyset selectors are gone: the SCP80 TAR field became a select of
the preset's entries (applying the TAR's keyset to the form and seeding
the SPI1 from its MSL); the RAM operations use the preset's ISD role
entry (the PWA sends only the preset id, the ISD TAR, SPI and the
counter override - the server resolves the keyset and the keys:
presets.tar_keyset, _preset_tar_keyset, _resolve_operation_keyset,
_op_keyset, used by send-ota's APDU path, ram-install, ram-install-app
and cap-compat); the counter probe and the test runner's scp80 steps
default to their TAR's keyset (an explicit kvn stays an override). A
security TAR without a keyset refuses the operation ("set it in the
Cards tab") - never a silent keyless send - and the start buttons wait
for a usable operation-TAR keyset.
The TAR probe checks the preset's TAR list only (the standard
TAR_PROBE_TARS list and the custom-TAR localStorage are gone; a `tars`
list selects a subset, a TAR outside the preset is refused), each row
using its own MSL and default keyset. The Cards editor's TAR table
gained a Keyset column (the only keyset preselected, an amber marker
when a security MSL lacks one).
Docs: help EN/RU, api.md's tar-probe contract, both AGENTS. Tests: the
store (the field, the auto-fill, the schema, the string forms), the
server resolution (send-ota + the refusal, the probe's per-row keysets
and refusals), the PWA (the TAR select, the RAM ISD resolution, the
keyset-free requests) - several fixtures updated for the new schema.
891 frontend + 885 Python; sw cache simple-v434.
This commit is contained in:
+17
-15
@@ -341,28 +341,30 @@ first attempt instead of hammering the card.
|
||||
### `POST /api/tar-probe`
|
||||
|
||||
Probe which OTA applications the card has registered: one **secured packet per
|
||||
TAR** (the standard allocations of TS 101 220 V18.3.0 Annex D, Table D.1 unless
|
||||
a `tars` list is given), each carrying a harmless C-APDU (`SELECT MF` by
|
||||
default), with the preset's keyset. Each checked TAR uses **its own MSL** when
|
||||
the preset carries the entry, otherwise the request's `spi1`; a TAR that
|
||||
resolves to neither is refused with a hint **before any packet is sent**. The
|
||||
resolved SPI1 must carry a counter check (b5b4 ≠ 00) and ask for a PoR.
|
||||
Every accepted packet consumes a counter, which is persisted into the keyset
|
||||
like any other operation, so the probe is refused when the SPI1 has no counter
|
||||
check or the named preset does not define the keyset number. A missing
|
||||
`cntr` is seeded from that keyset (v3.20.0; an explicit value wins but never
|
||||
lowers the stored counter). The delivered SMS carries the OTA CPI IE by
|
||||
TAR of the named preset** (v3.26.0 — the probe checks the preset's TAR list
|
||||
only; a `tars` list may select a subset, and a TAR outside the preset is
|
||||
refused with `400`), each carrying a harmless C-APDU (`SELECT MF` by default).
|
||||
Each row uses **its own MSL** (the request's `spi1` is only a fallback for a
|
||||
TAR the preset does not carry) and **its own default keyset** — the keyset
|
||||
resolved from that TAR's entry, so the request does not carry KIc/KID/keys and
|
||||
the probe's keyset selector is gone. A TAR whose MSL requires security
|
||||
(non-zero) without a default keyset, or one naming an undefined keyset, is
|
||||
refused with a hint **before any packet is sent**. The resolved SPI1 must
|
||||
carry a counter check (b5b4 ≠ 00) and ask for a PoR. Every accepted packet
|
||||
consumes a counter, which is persisted into that row's keyset like any other
|
||||
operation (each keyset has its own counter, TS 102 225 A.1); an explicit
|
||||
`cntr` seeds the first row only. The delivered SMS carries the OTA CPI IE by
|
||||
default (`includeCpi`, as in `/api/send-ota`).
|
||||
|
||||
```json
|
||||
{"preset_id": "…", "kic": "25", "kid": "25", "kicKey": "…", "kidKey": "…",
|
||||
"cntr": "0000000187", "apdu": "00A40000023F00", "tars": ["000000", "B00000"]}
|
||||
{"preset_id": "…", "spi1": "16", "apdu": "00A40000023F00",
|
||||
"tars": ["000000", "B00000"]}
|
||||
```
|
||||
|
||||
**Response:** `{"success": true, "registered": N, "total": M,
|
||||
"final_cntr": "…", "kvn": 2, "spi1": "16", "spi2": "01",
|
||||
"results": [{"tar": "000000", "label": "Issuer Security Domain (compact)",
|
||||
"spi1": "16", "verdict": "registered", "sw": "9000",
|
||||
"results": [{"tar": "000000", "label": "ISD", "spi1": "16", "kvn": 2,
|
||||
"verdict": "registered", "sw": "9000",
|
||||
"por_status": "por_ok",
|
||||
"por_sw": "6D00", "por_data": ""}], "steps": [...]}`
|
||||
|
||||
|
||||
Reference in New Issue
Block a user