release: v3.9.1 - the counter probe sends a fixed read-only APDU
- The probe no longer takes a caller-supplied `apdu`: it always sends the read-only SELECT MF (the counter advances on the packet's security acceptance whatever the applet answers - 6A86/6D00 are normal there), so no caller can turn the sync probe into a write. - Version 3.9.1: server VERSION, pyproject.toml and the PWA header; sw cache simple-v357; docs/api.md and the repo AGENTS.md updated, and the workspace AGENTS.md gains the v3.9.1 history entry (its "Currently" line was stale at v3.7.1).
This commit is contained in:
+6
-6
@@ -252,7 +252,7 @@ import also accepts presets exported by the older localStorage-based builds.
|
||||
Sync a preset's SCP80 counter with the card. The card accepts only a counter
|
||||
*above* its own (TS 102 225 §5.1.1, SPI1 b5b4 = `10`) and updates it only when
|
||||
the packet is accepted, so rejected attempts change nothing; the probe walks a
|
||||
doubling ladder (`start+1`, `+2`, `+4`, …) with a read-only command until one
|
||||
doubling ladder (`start+1`, `+2`, `+4`, …) with a fixed read-only command until one
|
||||
is accepted, then persists `accepted+1` (monotonic) into the keyset. The
|
||||
search stops at a ceiling and after a bounded number of packets, so it can
|
||||
never run towards the 40-bit maximum, where the card blocks the counter. The
|
||||
@@ -261,15 +261,15 @@ the packet's, TS 102 225 §5.2 Table 3), which is why this probe exists.
|
||||
|
||||
```json
|
||||
{"preset_id": "…", "kvn": 2, "tar": "000000", "spi1": "16", "spi2": "21",
|
||||
"cntr": "0001000000", "ceiling": "FFFFFFFF", "max_attempts": 40,
|
||||
"apdu": "00A40000023F00"}
|
||||
"cntr": "0001000000", "ceiling": "FFFFFFFF", "max_attempts": 40}
|
||||
```
|
||||
|
||||
All fields except `preset_id` are optional: `kvn` picks a keyset (the first
|
||||
otherwise), `tar`/`spi1`/`spi2` default to the preset's values, `cntr` to the
|
||||
keyset's counter, `ceiling` to `FFFFFFFF` (must stay below `FFFFFFFFFF`),
|
||||
`max_attempts` to 40 (clamped to 1–64), and `apdu` to a read-only `SELECT MF`
|
||||
(the probe command should never modify anything). A SPI1 without a counter
|
||||
keyset's counter, `ceiling` to `FFFFFFFF` (must stay below `FFFFFFFFFF`) and
|
||||
`max_attempts` to 40 (clamped to 1–64). The probe always sends the read-only
|
||||
`SELECT MF` - the counter advances on the packet's security acceptance whatever
|
||||
the applet answers (`6A86`/`6D00` are normal there). A SPI1 without a counter
|
||||
check is refused (400).
|
||||
|
||||
**Response:** `{"success": true, "accepted_cntr": "0001000000",
|
||||
|
||||
+1
-1
@@ -1801,7 +1801,7 @@
|
||||
// ===== Version =====
|
||||
// Single source of truth for the PWA version: shown in the header and used
|
||||
// by the server version check in pysimConnect().
|
||||
const SIMPLE_VERSION = '3.9.0';
|
||||
const SIMPLE_VERSION = '3.9.1';
|
||||
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||
|
||||
// ===== Tab switching =====
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simple-v356';
|
||||
const CACHE = 'simple-v357';
|
||||
const URLS = [
|
||||
'index.html',
|
||||
'help.html',
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "pysim-simple-server"
|
||||
version = "3.9.0"
|
||||
version = "3.9.1"
|
||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||
requires-python = ">=3.8"
|
||||
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
||||
|
||||
@@ -32,7 +32,7 @@ from osmocom.tlv import BER_TLV_IE
|
||||
from osmocom.utils import rpad
|
||||
|
||||
|
||||
VERSION = '3.9.0'
|
||||
VERSION = '3.9.1'
|
||||
|
||||
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||
|
||||
@@ -1668,7 +1668,10 @@ def _counter_probe_params(preset, body):
|
||||
'spi1': spi1,
|
||||
'spi2': str(body.get('spi2') or preset.get('spi2') or '21').strip().upper(),
|
||||
'tar': str(body.get('tar') or preset.get('tar') or '000000').strip().upper(),
|
||||
'apdu': str(body.get('apdu') or COUNTER_PROBE_DEFAULT_APDU).replace(' ', '').upper(),
|
||||
# the probe command is fixed: read-only SELECT MF, which every applet
|
||||
# answers (an error SW is fine - the counter advances on the packet's
|
||||
# security acceptance, not on the command's own result)
|
||||
'apdu': COUNTER_PROBE_DEFAULT_APDU,
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user