diff --git a/docs/api.md b/docs/api.md
index 528a6a0..8821b28 100644
--- a/docs/api.md
+++ b/docs/api.md
@@ -192,7 +192,7 @@ A blocked ADM (`6983`/`9804`) reports `{"ok": false, "sw": "9804",
### Card presets (server-side store)
-Card presets (keysets, SPI, per-target TARs, PSK pair, ADM) live on the server
+Card presets (keysets, a TAR table with per-TAR MSLs, PSK pair, ADM) live on the server
in `~/.pysim-simple-server/card_presets.json` (`--card-presets PATH` overrides
it; `Path.home()` resolves the same way on Linux, macOS and Windows). The file
is written atomically and every counter change is appended to
@@ -203,9 +203,14 @@ is written atomically and every counter change is appended to
the bytes, there is no separate field:
```json
-{"id": "…", "name": "Card A", "iccid": "…", "spi1": "16", "spi2": "01",
- "tar": "000000", "uiccTar": "B00000", "usimTar": "B00001",
+{"id": "…", "name": "Card A", "iccid": "…",
"pskIdentity": "", "pskKey": "", "adm": "",
+ "tars": [
+ {"role": "isd", "tar": "000000", "msl": "16", "desc": ""},
+ {"role": "uiccRfm", "tar": "B00000", "msl": "16", "desc": ""},
+ {"role": "usimRfm", "tar": "B00001", "msl": "16", "desc": ""},
+ {"tar": "AF4D01", "msl": "1A", "desc": "my applet"}
+ ],
"keysets": [
{"kic": "15", "kid": "15", "kicKey": "…", "kidKey": "…", "cntr": "0000000001"},
{"kic": "29", "kid": "29", "kicKey": "…", "kidKey": "…", "cntr": "0000000005"}
@@ -221,6 +226,19 @@ fixed-width 10-hex form. A v3.8.0 flat preset (`kic`/`kid`/`kicKey`/`kidKey`/
`cntr` at the top level) converts into a single keyset on load and on import,
so old files and exports keep working.
+**TAR table.** Every Remote Management application is addressed by its TAR and
+each entry carries its own **MSL** (Minimum SPI1, TS 102 226 §8.2.1.3.2.4): the
+card checks it before the security processing and answers response status `0A`
+"Insufficient security level" when a packet's SPI1 is below it. The three role
+entries (`isd`, `uiccRfm`, `usimRfm` — GP ISD `000000`, TS 31.116 UICC RFM
+`B00000`, TS 31.115 ADF RFM `B00001`) are **mandatory** with a non-empty TAR
+and MSL; further TARs can be added with an optional `desc`. A TAR is three hex
+bytes, an MSL one, and a TAR may appear once (a duplicate is refused). A
+v3.9.1 preset's card-wide `spi1`/`tar`/`uiccTar`/`usimTar` convert into the
+three role entries, the `spi1` as their MSL. Operations **derive a packet's
+SPI1 from the MSL of its TAR**; a request naming a TAR outside the preset must
+pass `spi1` itself, otherwise it is refused with `400` and a hint.
+
**Counters.** The store is the source of truth for the SCP80 counters, one per
keyset ("a dedicated counter shall be associated to each key version",
Annex A.1 — the spec's wording). The operations below accept a `preset_id` and **persist the
@@ -232,7 +250,7 @@ is not defined in preset '…' - add it in the Cards tab"}`), and so is a
KIc/KID number mismatch. The Cards tab's export/import uses this API; the
import also accepts presets exported by the older localStorage-based builds.
-- `GET /api/presets` — `{"path": "…", "count": 2, "version": 2, "presets": [{…}]}`
+- `GET /api/presets` — `{"path": "…", "count": 2, "version": 3, "presets": [{…}]}`
(card-free: it answers while a long card operation runs).
- `POST /api/presets` — body = the preset fields (`keysets` included); returns
`{"ok": true, "preset": {…}}`. A duplicate ICCID (digits, spaced or raw EF
@@ -265,7 +283,8 @@ the packet's, TS 102 225 §5.2 Table 3), which is why this probe exists.
```
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
+otherwise), `tar` defaults to the preset's ISD entry and `spi1` to that TAR's
+MSL, `spi2` to `01`, `cntr` to the
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
@@ -286,10 +305,13 @@ first attempt instead of hammering the card.
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 and SPI `16/01` (counter check + PoR).
+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 (b5b4 = 00) or the named preset does not define the keyset number.
+check or the named preset does not define the keyset number.
```json
{"preset_id": "…", "kic": "25", "kid": "25", "kicKey": "…", "kidKey": "…",
@@ -299,7 +321,8 @@ check (b5b4 = 00) or the named preset does not define the keyset number.
**Response:** `{"success": true, "registered": N, "total": M,
"final_cntr": "…", "kvn": 2, "spi1": "16", "spi2": "01",
"results": [{"tar": "000000", "label": "Issuer Security Domain (compact)",
- "verdict": "registered", "sw": "9000", "por_status": "por_ok",
+ "spi1": "16", "verdict": "registered", "sw": "9000",
+ "por_status": "por_ok",
"por_sw": "6D00", "por_data": ""}], "steps": [...]}`
Verdicts: `registered` (ENVELOPE 9000 + a PoR carrying the application's own
@@ -423,6 +446,13 @@ segments are sent in order. A packet that would need more than 5 segments
is refused (the card's concatenation buffer is the limit). With `sp` a
pre-built packet is delivered the same way.
+**SPI1 and the TAR's MSL.** With a `preset_id` the packet's SPI1 is derived
+from the MSL of its `tar` (TS 102 226 §8.2.1.3.2.4) unless the request passes
+`spi1` — an explicit value wins (a hand send may deliberately ask for more
+security than the minimum), and a value below the TAR's MSL is reported as
+`"warning"` in the response (numeric compare). A TAR the preset does not
+carry, without an explicit `spi1`, is refused with `400` and a hint.
+
The card may answer with PoR status `actual_response_sms_submit` (`0x0B`):
the real response (a big GET STATUS listing, for example) then arrives as one
or more proactive SEND SHORT MESSAGE commands. The server captures those
@@ -590,9 +620,12 @@ suspended; only `/api/test/*`, `/api/status`, `/api/poll-status`,
"checks": [{"kind": "text", "value": "hello"}],
"respond": {"result": "ok"}}
]},
- "preset": {"name": "lab card", "kic": "15", "kid": "15", "kicKey": "...",
- "kidKey": "...", "counter": "0000000A", "tar": "B00000",
- "spi1": "16", "spi2": "01"}}
+ "preset": {"name": "lab card",
+ "keysets": [{"kic": "15", "kid": "15", "kicKey": "...", "kidKey": "...",
+ "cntr": "0000000A"}],
+ "tars": [{"role": "isd", "tar": "000000", "msl": "16"},
+ {"role": "uiccRfm", "tar": "B00000", "msl": "16"},
+ {"role": "usimRfm", "tar": "B00001", "msl": "16"}]}}
```
**Action steps** (`type: "action"`): `kind` is `envelope` (`event`, `data`),
diff --git a/frontend/help-ru.html b/frontend/help-ru.html
index 96d6f33..2dbed06 100644
--- a/frontend/help-ru.html
+++ b/frontend/help-ru.html
@@ -42,7 +42,7 @@
1.1 Интерфейс
-
Шапка — версия приложения, кнопка INSTALL PWA (появляется, когда браузер предлагает установку, для офлайн-работы), ссылки на проект на GitHub и на эту справку, переключатель языка EN/RU и переключатель тёмной/светлой темы. Рядом с заголовком небольшой индикатор показывает состояние сервера/карты (серая точка = подключение, красная = нет сервера, значки карты = нет карты / инициализация / карта готова), ICCID подключённой карты, компактный значок ADM ✓ (зелёный, администраторский PIN подтверждён) или ADM ✗ (красный, не подтверждён) для текущей сессии карты — со значком ключа в конце (ADM ✓ ⚿), если в пресете карты с этим ICCID есть ключ ADM — и серые маркеры SCP80 / SCP81, появляющиеся, когда в этом пресете заполнены все поля SCP80 (KIc/KID, SPI1/SPI2, счётчик и ключи) или SCP81 (PSK identity/ключ).
+
Шапка — версия приложения, кнопка INSTALL PWA (появляется, когда браузер предлагает установку, для офлайн-работы), ссылки на проект на GitHub и на эту справку, переключатель языка EN/RU и переключатель тёмной/светлой темы. Рядом с заголовком небольшой индикатор показывает состояние сервера/карты (серая точка = подключение, красная = нет сервера, значки карты = нет карты / инициализация / карта готова), ICCID подключённой карты, компактный значок ADM ✓ (зелёный, администраторский PIN подтверждён) или ADM ✗ (красный, не подтверждён) для текущей сессии карты — со значком ключа в конце (ADM ✓ ⚿), если в пресете карты с этим ICCID есть ключ ADM — и серые маркеры SCP80 / SCP81, появляющиеся, когда в этом пресете заполнены SCP80 (keyset и три записи TAR с их MSL) или SCP81 (PSK identity/ключ).
Выбор языка и темы хранится в localStorage и сохраняется между перезагрузками.
Ссылка справка открывает эту документацию на разделе, соответствующем текущему представлению (например, вкладка «Профайлер» открывает §7).
@@ -282,7 +282,7 @@
Верхнеуровневая вкладка SCP80 объединяет разделы, связанные с SCP80. Переключение — тремя переключателями: Secured Packet, RAM и TAR-сканер. Собирает защищённые пакеты SCP80 по ETSI TS 102 225. При подключении карты сервер читает её EF.ICCID (2FE2); если в пресете указан тот же номер (цифрами или сырым hex из EF), он автоматически выбирается во всех трёх представлениях SCP80. Вердикт низкого счётчика (cntr_low или предупреждающий ответ ENVELOPE, в котором всё ещё есть такой PoR) не исправляется повторной отправкой: любая операция SCP80/RAM немедленно останавливается. Карта не сообщает свой счётчик (поле CNTR в PoR — копия счётчика пакета), поэтому в уведомлении есть ограниченный пробник «Синхронизировать счётчик» — read-only команда с возрастающими значениями счётчика (шаг удваивается, потолок 32 бита, не более 40 пакетов), пока карта не примет одно; затем сохраняется принятое+1 — и кнопка К пресету для ручного повышения; больше ничего автоматически не записывается.
3.1 Secured Packet
-
Собирает защищённые пакеты SCP80 по ETSI TS 102 225. Селектор Keyset рядом с выбором пресета указывает, из какого keyset берутся ключи и счётчик; отправка отклоняется, если в пресете нет такого номера keyset или KIc/KID несут разные номера (TS 102 225 A.2). Селектор недоступен, пока не выбран пресет карты. Кнопка запуска недоступна, пока не выбран пресет карты и один из его keysets.
+
Собирает защищённые пакеты SCP80 по ETSI TS 102 225. Селектор Keyset рядом с выбором пресета указывает, из какого keyset берутся ключи и счётчик; отправка отклоняется, если в пресете нет такого номера keyset или KIc/KID несут разные номера (TS 102 225 A.2). Селектор недоступен, пока не выбран пресет карты. Кнопка запуска недоступна, пока не выбран пресет карты и один из его keysets. Поле TAR предлагает записи TAR пресета (с описанием и MSL); при применении пресета TAR операции подставляется, а SPI1 берётся из его MSL (минимальный SPI1, TS 102 226 §8.2.1.3.2.4 — карта проверяет его до обработки защиты и отвечает 0A, если SPI1 пакета ниже). Значение ниже MSL показывает жёлтое предупреждение под формой; введённый вручную TAR сохраняет SPI1 оператора.
Структура пакета
Поле
Размер
Описание
@@ -314,7 +314,7 @@
Кнопка Проверить в pySim сверяет собранный пакет с эталонной реализацией OtaDialectSms.encode_cmd. Кнопка Отправить на карту доставляет пакет через ENVELOPE SMS-PP-DOWNLOAD (при подключении к серверу). 2-байтовый префикс CPL передаётся, когда пакет зашифрован или несёт RC/CC/DS (входит в их входные данные), а также при конкатенации SMS; одиночное незащищённое SMS сохраняет форму pySim, начинающуюся с CHL (TS 31.115 Table 1 NOTE). Под полем пакета показывается его размер и число SMS; пакет, не помещающийся в одно SMS, отправляется конкатенированной загрузкой (TS 31.115 §4.3) — пакет делится на части SMS-пользовательских данных (первое SMS 132 октета, последующие по 134; первое дополнительно несёт информационные элементы конкатенации и CPI), и сегменты отправляются по порядку. Более 5 сегментов отклоняется: это практический предел буфера конкатенации карты. Полученный Proof of Receipt декодируется и показывается строкой статуса PoR (статус, TAR, счётчик, сырой PoR); статусное слово и данные ответа последней команды подставляются в подвкладку «Разбор R-APDU» (Remote APDU → «Разбор»), а успешный PoR увеличивает счётчик повторов (когда в SPI1 есть проверка счётчика — b5 b4 ≠ 00; без неё счётчик не увеличивается и не сохраняется) и очищает пакет.
3.2 RAM
-
Выполняет операции удалённого управления приложениями (Remote Application Management) как защищённые пакеты SCP80 через SMS-PP-DOWNLOAD ENVELOPE. Карта должна поддерживать SCP03 (AES или 3DES). Пресет карты со вкладки Карты обеспечивает SPI, ключи, TAR и счётчик (RAM использует ISD TAR пресета, по умолчанию 000000). Селектор Keyset рядом с выбором пресета указывает, из какого keyset берутся ключи и счётчик операции. Селектор недоступен, пока не выбран пресет карты. Кнопка запуска недоступна, пока не выбран пресет карты и один из его keysets. Селектор Формат фиксирует формат удалённой команды: Авто (определение) опрашивает read-only команду GET STATUS в компактном виде и в обоих expanded-кодированиях и оставляет первое, которое карта выполнила; Компактный отправляет голую C-APDU; Expanded (AA, определённая длина) / Expanded (AE 80, неопределённая длина) заворачивают её в шаблон Command Scripting из TS 102 226 §5.2.1 (на живой карте выполняются обе; шаблон, у которого заявленная длина не совпадает с телом, получает Bad format TLV — операция показывает это как ошибку шага). Запросы листингов и реестра следуют этому формату: компактные листинги несут сцепленный GET RESPONSE, а expanded-прогон отправляет те же запросы P2=00 обёрнутыми и без цепочки (форма эталонного загрузчика TCA; Le=’00’ возвращает листинг сразу), и запрос реестра, отклонённый картой в текущем формате, повторяется в остальных — отчёт называет тот, который сработал. Блок ресурсов карты также называет предполагаемый релиз ETSI карты (версия uicc.toolkit → REL-N, то же сопоставление, что и в анализе CAP; показывается, только если расширенный реестр вернул версии).
+
Выполняет операции удалённого управления приложениями (Remote Application Management) как защищённые пакеты SCP80 через SMS-PP-DOWNLOAD ENVELOPE. Карта должна поддерживать SCP03 (AES или 3DES). Пресет карты со вкладки Карты обеспечивает ключи, таблицу TAR и счётчик (RAM использует ISD TAR пресета, по умолчанию 000000; SPI1 берётся из MSL этого TAR). Селектор Keyset рядом с выбором пресета указывает, из какого keyset берутся ключи и счётчик операции. Селектор недоступен, пока не выбран пресет карты. Кнопка запуска недоступна, пока не выбран пресет карты и один из его keysets. Селектор Формат фиксирует формат удалённой команды: Авто (определение) опрашивает read-only команду GET STATUS в компактном виде и в обоих expanded-кодированиях и оставляет первое, которое карта выполнила; Компактный отправляет голую C-APDU; Expanded (AA, определённая длина) / Expanded (AE 80, неопределённая длина) заворачивают её в шаблон Command Scripting из TS 102 226 §5.2.1 (на живой карте выполняются обе; шаблон, у которого заявленная длина не совпадает с телом, получает Bad format TLV — операция показывает это как ошибку шага). Запросы листингов и реестра следуют этому формату: компактные листинги несут сцепленный GET RESPONSE, а expanded-прогон отправляет те же запросы P2=00 обёрнутыми и без цепочки (форма эталонного загрузчика TCA; Le=’00’ возвращает листинг сразу), и запрос реестра, отклонённый картой в текущем формате, повторяется в остальных — отчёт называет тот, который сработал. Блок ресурсов карты также называет предполагаемый релиз ETSI карты (версия uicc.toolkit → REL-N, то же сопоставление, что и в анализе CAP; показывается, только если расширенный реестр вернул версии).
Операции
@@ -340,13 +340,13 @@
3.3 TAR-сканер
-
Третья пилюля вкладки SCP80 показывает, какие OTA-приложения зарегистрированы на карте: отправляется по одному защищённому пакету на каждый выбранный TAR — стандартные значения из TS 101 220 V18.3.0 Annex D, Table D.1, каждая строка несёт документ-источник — с безобидной C-APDU (по умолчанию SELECT MF), пресетом и keyset этого представления, SPI 16/01 (проверка счётчика + PoR). Кнопка Execute недоступна, пока не выбран пресет карты и один из его keysets.
+
Третья пилюля вкладки SCP80 показывает, какие OTA-приложения зарегистрированы на карте: отправляется по одному защищённому пакету на каждый выбранный TAR — стандартные значения из TS 101 220 V18.3.0 Annex D, Table D.1, каждая строка несёт документ-источник — с безобидной C-APDU (по умолчанию SELECT MF), пресетом и keyset этого представления — каждый проверяемый TAR использует свой MSL, если запись есть в пресете, иначе SPI1 из общей формы; TAR, для которого нет ни того, ни другого, отклоняется до отправки. Разрешённый SPI1 должен иметь проверку счётчика (b5b4 ≠ 00) и запрашивать PoR. Кнопка Execute недоступна, пока не выбран пресет карты и один из его keysets.
Список предзаполнен стандартными TAR (все отмечены; кнопки Выбрать все / Снять все переключают быстро), свои TAR добавляются кнопкой Добавить TAR (три hex-байта и необязательное описание). Пользовательские записи хранятся в localStorage по возможности — их потеря безвредна.
Каждый TAR классифицируется по ответу карты: зарегистрировано (ENVELOPE 9000 + PoR со SW и данными приложения), принято, нет ответа (PoR без R-APDU), принято, нет PoR (пакет молча отброшен) и отклонено (ENVELOPE не 9000, обычно 6200 для TAR без зарегистрированного приложения). Таблица результата появляется в окне операции; строка под кнопкой Execute показывает зарегистрировано N / M.
-
Каждый принятый картой пакет расходует счётчик, который сохраняется в keyset пресета — проба отклоняется, если в SPI1 нет проверки счётчика или в пресете нет такого номера keyset. На живой карте: 000000, B00000 и B00001 зарегистрированы (приложения компактного формата), расширенный формат, USAT, мультиплексирование и CASD отклонены с 6200.
+
Каждый принятый картой пакет расходует счётчик, который сохраняется в keyset пресета — проба отклоняется, если в разрешённом SPI1 нет проверки счётчика или в пресете нет такого номера keyset. На живой карте: 000000, B00000 и B00001 зарегистрированы (приложения компактного формата), расширенный формат, USAT, мультиплексирование и CASD отклонены с 6200.
4. Вкладка «Карты»
-
Хранит пресеты карт на сервере (~/.pysim-simple-server/card_presets.json; переопределяется --card-presets), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, слушатель SCP81 HTTP OTA — находить PSK-ключи, а счётчики SCP80, израсходованные операцией, сохранялись самой операцией — закрытая вкладка или второе окно браузера больше не могут потерять инкремент. Пресет содержит несколько keysets — номер keyset задаётся нибблом b8..b5 его KIc/KID (TS 102 225 §5.1.2/A.2): KIc и KID одного keyset должны нести один и тот же номер (01–0F; A.2 отвергает несовпадение), и у каждого keyset на карте свой счётчик (Annex A.1), поэтому счётчики ведутся по keysets. В форме keysets редактируются строками — по одной на номер, с кнопками Добавить keyset / Удалить keyset; номер в строке вычисляется из байта KIc/KID, а 00 («без защиты») не принимается как keyset. Список загружается при подключении PWA и экспортируется/импортируется как JSON (импорт принимает и пресеты старых сборок — плоские и с keysets). «Карты» — верхнеуровневая вкладка. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается во всех трёх представлениях SCP80; если подключённая карта не совпадает ни с одним пресетом — или выбранный пресет принадлежит другой карте — все три представления SCP80 показывают жёлтое предупреждение над выбором пресета. В списке подсвечивается пресет подключённой карты. Поля формы сгруппированы в два блока с рамкой: SCP80 (GSM 03.48, ETSI TS 102 225) (KIc/KID, SPI1/SPI2, TAR-ы ISD/UICC RFM/ADF RFM, счётчик и ключи) и SCP81 (HTTP OTA) (пара PSK identity/ключ с пояснением о выборе ключа). Необязательное поле ADM находится в верхней строке и сохраняется для последующего использования файловым менеджером. В шапке отображаются серые маркеры SCP80/SCP81 и значок ключа на бейдже ADM, когда в пресете с ICCID подключённой карты эти поля заполнены.
+
Хранит пресеты карт на сервере (~/.pysim-simple-server/card_presets.json; переопределяется --card-presets), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, слушатель SCP81 HTTP OTA — находить PSK-ключи, а счётчики SCP80, израсходованные операцией, сохранялись самой операцией — закрытая вкладка или второе окно браузера больше не могут потерять инкремент. Пресет содержит несколько keysets — номер keyset задаётся нибблом b8..b5 его KIc/KID (TS 102 225 §5.1.2/A.2): KIc и KID одного keyset должны нести один и тот же номер (01–0F; A.2 отвергает несовпадение), и у каждого keyset на карте свой счётчик (Annex A.1), поэтому счётчики ведутся по keysets. В форме keysets редактируются строками — по одной на номер, с кнопками Добавить keyset / Удалить keyset; номер в строке вычисляется из байта KIc/KID, а 00 («без защиты») не принимается как keyset. Список загружается при подключении PWA и экспортируется/импортируется как JSON (импорт принимает и пресеты старых сборок — плоские и с keysets). «Карты» — верхнеуровневая вкладка. При подключении карты читается её EF.ICCID, и пресет с тем же ICCID автоматически выбирается во всех трёх представлениях SCP80; если подключённая карта не совпадает ни с одним пресетом — или выбранный пресет принадлежит другой карте — все три представления SCP80 показывают жёлтое предупреждение над выбором пресета. В списке подсвечивается пресет подключённой карты. Поля формы сгруппированы в два блока с рамкой: SCP80 (GSM 03.48, ETSI TS 102 225) (keysets, таблица TAR — три обязательные роли ISD / UICC RFM / ADF RFM, у каждой свой MSL, плюс дополнительные TAR с необязательным описанием — и счётчики) и SCP81 (HTTP OTA) (пара PSK identity/ключ с пояснением о выборе ключа). Необязательное поле ADM находится в верхней строке и сохраняется для последующего использования файловым менеджером. В шапке отображаются серые маркеры SCP80/SCP81 и значок ключа на бейдже ADM, когда в пресете с ICCID подключённой карты эти поля заполнены.
Поле
Описание
@@ -354,7 +354,7 @@
ICCID
Опциональный идентификатор карты. Кнопка С карты подставляет EF.ICCID подключённой карты (активна, только когда ICCID читается); при сохранении ICCID, уже присутствующий в списке, отклоняется (сравнение без пробелов и с учётом сырой hex-формы, конфликтующий пресет называется)
ADM
Необязательный администраторский PIN (hex или до 8 ASCII-цифр), сохраняется в пресете для последующего использования файловым менеджером; представлениями SCP80/SCP81 не используется
KIc / KID
Индикаторы ключа и алгоритма (например, 15 = индекс 1, 3DES-CBC2; x2 = AES); задаются вместе с ключами
-
SPI1 / SPI2
Security Parameter Indicators
+
TARs / MSL
Таблица TAR: три обязательные роли (ISD / UICC RFM / ADF RFM — предзаполнены) и дополнительные TAR, у каждого свой MSL (минимальный SPI1, TS 102 226 §8.2.1.3.2.4). SPI1 пакета берётся из MSL его TAR; у свободных записей есть необязательное описание
ISD TAR
TAR Issuer Security Domain (TS 101 220, приложение D); используется для операций RAM/GP (представление SCP80 RAM, цепочки RAM/GP); по умолчанию по спецификации 000000, подставляется при пустом значении
UICC RFM TAR
TAR UICC Shared File System RFM (TS 102 226 §7.2, TS 101 220 приложение D): MF выбирается неявно и доступны только файлы под MF (ADF недоступны); используется представлением SIM RFM; по умолчанию B00000
ADF RFM TAR
TAR ADF RFM (TS 102 226 §7.3, TS 101 220 приложение D): ADF выбирается неявно, TAR привязан к AID приложения — ADF.USIM в представлении USIM RFM; по умолчанию B00001
@@ -364,7 +364,7 @@
PSK key
SCP81 HTTP OTA: 32 hex-символа (16 байт) для PSK TLS-слушателя; ключ выбирается по идентификатору, который предъявляет карта
-
Столбец SCP81 показывает, задана ли в пресете рабочая пара PSK: ✓ (зелёный) — идентификатор и ключ заданы; ⚠ (жёлтый) — задано только одно из двух, и слушатель такой пресет игнорирует; — — PSK нет. Идентификатор и ключ PSK задаются вместе. Кнопка Редактировать загружает пресет в форму (кнопка Add становится Сохранить; Отмена очищает форму), поэтому поля можно менять без повторного ввода карты; Удалить удаляет строку. Обмен пресетами: Экспорт в файл для выгрузки и Импорт из файла для загрузки. Выбранный пресет автоматически заполняет форму Secured Packet и устанавливает TAR для операции (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); TAR, введённый в форму Secured Packet вручную, сохраняется при отправке - счётчик, ключи и SPI по-прежнему берутся из пресета; изменения сразу передаются работающему слушателю SCP81.
+
Столбец SCP81 показывает, задана ли в пресете рабочая пара PSK: ✓ (зелёный) — идентификатор и ключ заданы; ⚠ (жёлтый) — задано только одно из двух, и слушатель такой пресет игнорирует; — — PSK нет. Идентификатор и ключ PSK задаются вместе. Кнопка Редактировать загружает пресет в форму (кнопка Add становится Сохранить; Отмена очищает форму), поэтому поля можно менять без повторного ввода карты; Удалить удаляет строку. Обмен пресетами: Экспорт в файл для выгрузки и Импорт из файла для загрузки. Выбранный пресет автоматически заполняет форму Secured Packet и устанавливает TAR для операции (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); TAR, введённый в форму Secured Packet вручную, сохраняется при отправке - счётчик, ключи и MSL этого TAR по-прежнему берутся из пресета; SPI1 берётся из MSL, а меньшее значение даёт предупреждение (сервер тоже возвращает его как warning); изменения сразу передаются работающему слушателю SCP81.
Header — the app version, an INSTALL PWA button (shown when the browser offers installation, enabling offline use), links to the project on GitHub and to this help, an EN/RU language toggle, and a dark/light theme toggle. Next to the title a small status indicator shows the server/card state (gray dot = connecting, red dot = no server connection, card icons = no card / equipping / equipped), the equipped card's ICCID digits, a compact ADM ✓ (green, administrator PIN verified) or ADM ✗ (red, not verified) badge for the current card session — with a trailing key glyph (ADM ✓ ⚿) when the card preset matching that ICCID carries an ADM key — and gray SCP80 / SCP81 markers that appear when that preset has complete SCP80 (KIc/KID, SPI1/SPI2, counter and keys) or SCP81 (PSK identity/key) settings.
+
Header — the app version, an INSTALL PWA button (shown when the browser offers installation, enabling offline use), links to the project on GitHub and to this help, an EN/RU language toggle, and a dark/light theme toggle. Next to the title a small status indicator shows the server/card state (gray dot = connecting, red dot = no server connection, card icons = no card / equipping / equipped), the equipped card's ICCID digits, a compact ADM ✓ (green, administrator PIN verified) or ADM ✗ (red, not verified) badge for the current card session — with a trailing key glyph (ADM ✓ ⚿) when the card preset matching that ICCID carries an ADM key — and gray SCP80 / SCP81 markers that appear when that preset has complete SCP80 (a keyset plus the three TAR entries with their MSLs) or SCP81 (PSK identity/key) settings.
Language and theme choices are stored in localStorage and persist across reloads.
The help link opens this documentation at the section matching the current view (e.g. the Profiler tab opens §7).
@@ -281,7 +281,7 @@
The SCP80 top-level tab groups the SCP80-related views. It is switched by three pills: Secured Packet, RAM and TAR probe. Assembles SCP80 secured packets per ETSI TS 102 225. When a card is equipped the server reads its EF.ICCID (2FE2); if a card preset carries the same number (digits, or the raw EF hex), it is selected automatically in all three SCP80 views.
3.1 Secured Packet
-
Builds SCP80 secured packets per ETSI TS 102 225. The Keyset selector next to the card preset selector picks which keyset of the preset supplies the keys and the counter; the send is refused when the preset does not define that keyset number or when its KIc/KID carry different numbers (TS 102 225 A.2). It is disabled until a card preset is selected. The start button stays disabled until a card preset and one of its keysets are selected.
+
Builds SCP80 secured packets per ETSI TS 102 225. The Keyset selector next to the card preset selector picks which keyset of the preset supplies the keys and the counter; the send is refused when the preset does not define that keyset number or when its KIc/KID carry different numbers (TS 102 225 A.2). It is disabled until a card preset is selected. The start button stays disabled until a card preset and one of its keysets are selected. The packet's TAR field suggests the preset's TAR entries (each with its description and MSL); applying a preset sets the operation's TAR and seeds the SPI1 from that TAR's MSL (Minimum SPI1, TS 102 226 §8.2.1.3.2.4 — the card checks it before the security processing and answers 0A when the packet's SPI1 is below it). A value below the MSL shows an amber warning under the form; a hand-typed TAR keeps the operator's SPI1.
Packet structure
Field
Size
Description
@@ -313,7 +313,7 @@
A “Verify vs pySim” button cross-checks the assembled packet against pySim’s reference OtaDialectSms.encode_cmd. A “Send to Card” button delivers it via SMS-PP-DOWNLOAD ENVELOPE (when connected to the server). The 2-byte CPL prefix is transmitted whenever the packet is ciphered or carries RC/CC/DS (it is part of their input) and whenever the packet is concatenated; a single unprotected SMS keeps pySim’s CHL-first form (TS 31.115 Table 1 NOTE). Under the packet field the app reports its size and how many SMS it takes; a packet that does not fit one SMS is sent as a concatenated download (TS 31.115 §4.3) — the packet is split into SMS user-data parts (first SM 132 octets, following ones 134; the first one additionally carries the concatenation and CPI information elements) and the segments are sent in order. More than 5 segments is refused, that being the practical limit of the card’s concatenation buffer. The returned Proof of Receipt is decoded and shown as a PoR status line (status, TAR, counter, raw PoR); the last command’s status word and response data are filled into the R-APDU parser panel, and a successful PoR advances the replay counter (when SPI1 carries a counter check — b5 b4 ≠ 00; without one no counter is advanced or saved) and clears the packet. A low-counter verdict (cntr_low, or a warning ENVELOPE answer that still carries such a PoR) is not recoverable by retrying: every SCP80/RAM operation stops immediately. The card never reports its counter (the PoR’s CNTR field is a copy of the packet’s), so the notice offers a bounded Sync counter probe — a read-only command with increasing counter values (doubling steps, a 32-bit ceiling, at most 40 packets) until the card accepts one, then accepted+1 is stored — and a Go to preset button for raising the counter by hand; nothing else is written automatically.
3.2 RAM
-
Delivers Remote Application Management operations as SCP80 secured packets via SMS-PP-DOWNLOAD ENVELOPE. The card must support SCP03 (AES or 3DES). A saved card preset from the Cards tab provides the SPI, keys, TAR, and counter (RAM uses the preset's ISD TAR, 000000 by default). The Keyset selector next to the preset selector picks the keyset whose keys and counter the operation uses. It is disabled until a card preset is selected. The start button stays disabled until a card preset and one of its keysets are selected. The Format selector pins the remote command format: Auto (detect) probes the read-only GET STATUS command compact and in both expanded codings and keeps the first that the card executes, Compact sends the bare C-APDU, and Expanded (AA, definite length) / Expanded (AE 80, indefinite length) wrap it in the TS 102 226 §5.2.1 scripting template (both execute on the live ISD; a template whose declared lengths do not match its body draws a Bad format TLV, which the operation shows as the step failure). The listing and registry queries follow that format: compact listings keep the chained GET RESPONSE, while an expanded run sends the same P2=00 queries wrapped and unchained (the reference TCA loader’s form, Le=’00’ returns the listing directly), and a registry query the card refuses in the current format is retried in the other formats — the report names the one that served it. The card-resources block also names the card’s inferred ETSI release (uicc.toolkit version → REL-N, the same mapping as the CAP analysis; shown only when the expanded registry returned the versions).
+
Delivers Remote Application Management operations as SCP80 secured packets via SMS-PP-DOWNLOAD ENVELOPE. The card must support SCP03 (AES or 3DES). A saved card preset from the Cards tab provides the keys, the TAR table and the counter (RAM uses the preset's ISD TAR, 000000 by default; the SPI1 is derived from that TAR's MSL). The Keyset selector next to the preset selector picks the keyset whose keys and counter the operation uses. It is disabled until a card preset is selected. The start button stays disabled until a card preset and one of its keysets are selected. The Format selector pins the remote command format: Auto (detect) probes the read-only GET STATUS command compact and in both expanded codings and keeps the first that the card executes, Compact sends the bare C-APDU, and Expanded (AA, definite length) / Expanded (AE 80, indefinite length) wrap it in the TS 102 226 §5.2.1 scripting template (both execute on the live ISD; a template whose declared lengths do not match its body draws a Bad format TLV, which the operation shows as the step failure). The listing and registry queries follow that format: compact listings keep the chained GET RESPONSE, while an expanded run sends the same P2=00 queries wrapped and unchained (the reference TCA loader’s form, Le=’00’ returns the listing directly), and a registry query the card refuses in the current format is retried in the other formats — the report names the one that served it. The card-resources block also names the card’s inferred ETSI release (uicc.toolkit version → REL-N, the same mapping as the CAP analysis; shown only when the expanded registry returned the versions).
Operations
@@ -339,13 +339,13 @@
3.3 TAR probe
-
The third SCP80 pill probes which OTA applications the card has registered: it sends one secured packet per selected TAR — the standard allocations of TS 101 220 V18.3.0 Annex D, Table D.1, each row carrying the document it comes from — with a harmless C-APDU (default SELECT MF) using the view's preset and keyset, SPI 16/01 (counter check + PoR). The Execute button stays disabled until a card preset and one of its keysets are selected.
+
The third SCP80 pill probes which OTA applications the card has registered: it sends one secured packet per selected TAR — the standard allocations of TS 101 220 V18.3.0 Annex D, Table D.1, each row carrying the document it comes from — with a harmless C-APDU (default SELECT MF) using the view's preset and keyset — each checked TAR uses its own MSL when the preset carries the entry, otherwise the SPI1 from the shared form; a TAR resolving to neither is refused before anything is sent. The resolved SPI1 must carry a counter check (b5b4 ≠ 00) and request a PoR. The Execute button stays disabled until a card preset and one of its keysets are selected.
The list is pre-filled with the standard TARs (all checked; Select all / Select none switch them quickly) and custom TARs can be added with Add TAR (three hex bytes plus an optional description). Custom entries are kept in localStorage on a best-effort basis — losing them is harmless.
Every TAR is classified from the card's answer: registered (ENVELOPE 9000 + a PoR carrying the application's own status word and data), accepted, no answer (a PoR without an R-APDU), accepted, no PoR (the packet was silently dropped) and refused (a non-9000 ENVELOPE, typically 6200 for a TAR without a registered application). The result table appears in the operation popup; the line under Execute summarises registered N / M.
-
Each packet the card accepts consumes a counter, which is saved into the preset's keyset — the probe is refused when SPI1 has no counter check or the named preset does not define the keyset number. Observed on a live card: 000000, B00000 and B00001 registered (compact-format applications), the expanded-format TARs, USAT, multiplexing and CASD refused with 6200.
+
Each packet the card accepts consumes a counter, which is saved into the preset's keyset — the probe is refused when the resolved SPI1 has no counter check or the named preset does not define the keyset number. Observed on a live card: 000000, B00000 and B00001 registered (compact-format applications), the expanded-format TARs, USAT, multiplexing and CASD refused with 6200.
4. Cards tab
-
Stores card presets on the server (~/.pysim-simple-server/card_presets.json; --card-presets overrides it) so the Secured Packet view can auto-fill keys and parameters, the SCP81 HTTP OTA listener can look up PSK keys, and the SCP80 counters an operation consumed are persisted with the operation itself — a closed tab or a second browser window can no longer lose an increment. A preset carries several keysets — a keyset's number is the b8..b5 nibble of its KIc/KID (TS 102 225 §5.1.2/A.2): KIc and KID of a keyset must carry the same number (01–0F; A.2 rejects a mismatch), and each keyset has its own counter on the card (Annex A.1), so counters are tracked per keyset. In the form the keysets are edited as rows — one per number, with Add keyset / Remove keyset; each row shows the number derived from its KIc/KID byte, and 00 (no security) is not accepted as a keyset. The list is loaded when the PWA connects and can be exported/imported as JSON (the import also takes presets exported by older builds, flat or keyset-shaped). Cards is a top-level tab. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in all three SCP80 views; when the equipped card matches no preset — or the selected preset belongs to another card — all three SCP80 views show an amber warning above the preset selector. The list highlights the equipped card's preset. The form groups the fields into two bordered blocks: SCP80 (GSM 03.48, ETSI TS 102 225) (KIc/KID, SPI1/SPI2, the ISD/UICC RFM/ADF RFM TARs, counter and keys) and SCP81 (HTTP OTA) (the PSK identity/key pair with the key-selection note). The optional ADM field sits in the top row and is stored for later use by the file manager. The header shows gray SCP80/SCP81 markers and a key glyph on the ADM badge when the preset matching the equipped card's ICCID has those settings filled in.
+
Stores card presets on the server (~/.pysim-simple-server/card_presets.json; --card-presets overrides it) so the Secured Packet view can auto-fill keys and parameters, the SCP81 HTTP OTA listener can look up PSK keys, and the SCP80 counters an operation consumed are persisted with the operation itself — a closed tab or a second browser window can no longer lose an increment. A preset carries several keysets — a keyset's number is the b8..b5 nibble of its KIc/KID (TS 102 225 §5.1.2/A.2): KIc and KID of a keyset must carry the same number (01–0F; A.2 rejects a mismatch), and each keyset has its own counter on the card (Annex A.1), so counters are tracked per keyset. In the form the keysets are edited as rows — one per number, with Add keyset / Remove keyset; each row shows the number derived from its KIc/KID byte, and 00 (no security) is not accepted as a keyset. The list is loaded when the PWA connects and can be exported/imported as JSON (the import also takes presets exported by older builds, flat or keyset-shaped). Cards is a top-level tab. When the card is equipped its EF.ICCID is read and the preset with the same ICCID is selected automatically in all three SCP80 views; when the equipped card matches no preset — or the selected preset belongs to another card — all three SCP80 views show an amber warning above the preset selector. The list highlights the equipped card's preset. The form groups the fields into two bordered blocks: SCP80 (GSM 03.48, ETSI TS 102 225) (the keysets, the TAR table — the three mandatory role entries ISD / UICC RFM / ADF RFM, each with its MSL, plus further TARs with an optional description — and the counters) and SCP81 (HTTP OTA) (the PSK identity/key pair with the key-selection note). The optional ADM field sits in the top row and is stored for later use by the file manager. The header shows gray SCP80/SCP81 markers and a key glyph on the ADM badge when the preset matching the equipped card's ICCID has those settings filled in.
Field
Description
@@ -353,7 +353,7 @@
ICCID
Optional card identifier. From card fills it with the equipped card's EF.ICCID (enabled only while a readable ICCID is known); saving refuses an ICCID that already exists in the list (compared ignoring spaces and the raw-hex form, and the conflicting preset is named)
ADM
Optional administrator PIN (hex, or up to 8 ASCII digits), stored in the preset for later use by the file manager; not used by the SCP80/SCP81 views
KIc / KID
Key and algorithm indicators (e.g. 15 = index 1, 3DES-CBC2; x2 = AES), required together with the keys
-
SPI1 / SPI2
Security Parameter Indicators
+
TARs / MSL
The TAR table: the three role entries (ISD / UICC RFM / ADF RFM — mandatory, pre-settled) plus further TARs, each with its MSL (Minimum SPI1, TS 102 226 §8.2.1.3.2.4). A packet's SPI1 is derived from its TAR's MSL; free entries carry an optional description
ISD TAR
Issuer Security Domain TAR (TS 101 220 Annex D); used for RAM/GP operations (SCP80 RAM view, RAM/GP chains); spec default 000000, prefilled when empty
UICC RFM TAR
UICC Shared File System RFM TAR (TS 102 226 §7.2, TS 101 220 Annex D): the MF is implicitly selected and only files under the MF are accessible (no ADFs); used by the SIM RFM view; spec default B00000
ADF RFM TAR
ADF RFM TAR (TS 102 226 §7.3, TS 101 220 Annex D): the ADF is implicitly selected and the TAR is linked to the application's AID — ADF.USIM in the USIM RFM view; spec default B00001
@@ -363,7 +363,7 @@
PSK key
SCP81 HTTP OTA: 32 hex chars (16 bytes) for the PSK TLS listener, picked by the identity the card presents
-
The SCP81 column shows whether the preset supplies a usable PSK pair: ✓ (green) — identity and key set; ⚠ (amber) — only one of the two, so the listener ignores the preset; — — no PSK. PSK identity and key must be set together. Edit loads a preset into the form (the Add button becomes Save; Cancel clears it) so fields can be changed without re-entering the card; Remove deletes the row. Presets can be shared with Export to file and restored with Import from file. The selected card preset auto-fills the Secured Packet form and sets the TAR for the operation (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); a TAR typed into the Secured Packet form by hand is kept when sending - the counter, keys and SPI are still re-read from the preset; edits are pushed into a running SCP81 listener automatically.
+
The SCP81 column shows whether the preset supplies a usable PSK pair: ✓ (green) — identity and key set; ⚠ (amber) — only one of the two, so the listener ignores the preset; — — no PSK. PSK identity and key must be set together. Edit loads a preset into the form (the Add button becomes Save; Cancel clears it) so fields can be changed without re-entering the card; Remove deletes the row. Presets can be shared with Export to file and restored with Import from file. The selected card preset auto-fills the Secured Packet form and sets the TAR for the operation (RAM/GP → ISD TAR, SIM RFM → UICC RFM TAR, USIM RFM → ADF RFM TAR); a TAR typed into the Secured Packet form by hand is kept when sending - the counter, keys and the TAR's MSL are still re-read from the preset; the SPI1 is seeded from the TAR's MSL and a lower value warns (the server returns it as a warning too); edits are pushed into a running SCP81 listener automatically.
Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries several keysets, each with its own number and counter.
+
Card presets are stored on the server. JSON export/import buttons are below the card list; a preset carries several keysets, each with its own number and counter, and a TAR table — every TAR with its MSL (Minimum SPI1).