From b02f28f6ce68a054683dd943f79e6474c4ef443d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Thu, 17 Sep 2026 00:33:39 +0300 Subject: [PATCH] docs: help restored to the UI (Cards/SCP81 sections), READMEs updated The help pages had no SCP81 section and documented Cards as a 3.2 subsection of the SCP80 tab. They now mirror the UI: 3 SCP80 (3.1 Secured Packet, 3.2 RAM), 4 Cards tab, 5 SCP81 tab (5.1 Listener, 5.2 Scripts), with the following sections renumbered (6 Card reader, 7 Profiler, 8 Phone simulator, 9 Server, 10 Compatibility) and the TERMINAL PROFILE range corrected to bytes 1-39 (TS 102 223 5.2 + TS 31.111 5.2). The SCP81 tab and its sub-pills set their own help anchors; a new test asserts every help anchor used by the UI exists in help.html. READMEs: seven top-level tabs, SCP80 two pills, Cards fields/buttons/SCP81 column, SCP81 modes (PSK TLS / pass-through / capture), PSK pairs from presets, Scripts page and resume semantics. SW cache otaman-v178. --- README.md | 47 ++++++++++----- README_RUS.md | 53 +++++++++++------ frontend/help-ru.html | 109 +++++++++++++++++++++-------------- frontend/help.html | 111 ++++++++++++++++++++++-------------- frontend/index.html | 3 + frontend/sw.js | 2 +- frontend/tests/html.test.js | 22 +++++++ 7 files changed, 230 insertions(+), 117 deletions(-) diff --git a/README.md b/README.md index 3472219..f8c634a 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ npm run build ## Interface -Six top-level tabs: **Remote APDU**, **SCP80**, **SCP81**, **Profiler**, **Card reader**, and **Phone simulator**. **Remote APDU** and **SCP80** use pill sub-tabs; the Card reader tab has three sub-tabs: **File manager**, **pySim command line**, and **Raw APDU**; the Profiler tab lists **Profiles**, **Card snapshots**, and **Custom files**. +Seven top-level tabs: **Remote APDU**, **SCP80**, **SCP81**, **Cards**, **Profiler**, **Card reader**, and **Phone simulator**. **Remote APDU** and **SCP80** use pill sub-tabs; the **SCP81** tab has **Listener** and **Scripts** pills; the Card reader tab has three sub-tabs: **File manager**, **pySim command line**, and **Raw APDU**; the Profiler tab lists **Profiles**, **Card snapshots**, and **Custom files**. --- @@ -349,7 +349,7 @@ Decodes a raw command response: pick the command that was sent, enter the SW (e. ## SCP80 tab -The **SCP80** top-level tab groups SCP80-related views, switched by three pills: **Secured Packet**, **Cards**, and **RAM**. Assembles secured packets per ETSI TS 102 225. +The **SCP80** top-level tab groups SCP80-related views, switched by two pills: **Secured Packet** and **RAM**. Assembles secured packets per ETSI TS 102 225. ### Secured Packet @@ -433,23 +433,25 @@ Delivery PoR (SPI2 `01`) is simpler — the card returns the PoR directly in the ### Cards -Stores saved card configurations (presets). Each preset stores the cryptographic keys, SPI settings, TAR, and replay counter needed for SCP80 operations. +Stores saved card configurations (presets) in `localStorage`. A preset holds the cryptographic keys, SPI settings, TAR and replay counter for SCP80 operations, plus the **PSK identity / PSK key** pair used by the SCP81 HTTP OTA listener. Cards is a **top-level tab**. | Field | Description | |---|---| +| Name | Human-readable label (required) | +| ICCID | Optional card identifier | | SPI1 / SPI2 | Security level and PoR settings | +| KIc / KID index | Key version number (required together with the keys) | | KIc / KID key | Encryption and MAC key hex | -| KIc / KID index | Key version number | | TAR | Toolkit Application Reference (3 bytes) | | Counter (CNTR) | 10-digit hex replay counter, auto-incremented after each successful SCP80 send | +| PSK identity | SCP81 HTTP OTA: the identity the card sends in the TLS handshake | +| PSK key | SCP81 HTTP OTA: 32 hex chars (16 bytes); the listener picks it by the identity the card presents | -**Add a card:** fill in the name, SPI1/SPI2, KIc/KID keys and indices, TAR, and click **Add**. The card appears in the list and becomes available in the RAM tab's **Card preset** dropdown. +The **SCP81** column shows whether the preset supplies a usable PSK pair: **✓** (identity and key), **⚠** (only one of the two — the listener ignores such a preset), **—** (no PSK). Identity and key must be set together. -**Edit a card:** click a card in the list, modify fields, click **Save**. +**Add a card:** fill in the name, ICCID (optional), SPI1/SPI2, KIc/KID keys and indices, TAR, the SCP81 PSK pair (optional) and click **Add**. The card appears in the list and becomes available in the RAM tab's **Card preset** dropdown. -**Delete a card:** select a card, click **Delete**. Removes the preset from `localStorage`. - -**Counter:** the 10-digit hex counter (CNTR) is auto-incremented after each successful SCP80 send (both manual Secured Packet sends and RAM operations). The updated counter is saved back to the preset automatically. +**Edit / remove:** **Edit** loads a preset into the form (the Add button becomes **Save**; **Cancel** clears the form); **Remove** deletes the row from `localStorage`. A successful SCP80 send advances and stores the replay counter, and edits are pushed into a running SCP81 listener automatically. ### RAM @@ -586,13 +588,30 @@ Values persist on the server until restart. Apply → hex updates; Save → POST ## SCP81 -The **SCP81** tab drives HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B). The card's BIP channel is always redirected to a local listener on the server: +The **SCP81** tab drives HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B) and has two pills: **Listener** and **Scripts**. -- **Capture (dump)** — accepts the card's TCP channel and logs whatever it sends (e.g. the TLS ClientHello) without answering. Use it to inspect what the card asks for. -- **PSK TLS server** — answers the handshake with the TLS 1.2 PSK cipher suites of the spec and speaks the GP HTTP administration dialog (`X-Admin-*` headers, `200` with a command string or `204 No Content`). Enter the **PSK Identity** the card uses and the **PSK key (hex)**; the key is only sent to the local server, never stored or logged. -- **Script** — the command script served over the session: **Memory + ELF info** (default) sends `GET DATA FF21` (available non-volatile/volatile memory, applet count) and `GET STATUS P1=20/10` (Executable Load Files and modules registry) as RAM/GP commands in TS 102 226 Command Scripting templates, one C-APDU per request; **None** closes every session with `204`. Custom APDU lists are accepted by the API. +The **Listener** starts/stops the target the card's BIP channel is redirected to, in one of three modes: -The state line shows the listener, the negotiated identity and live channels (bytes in/out); the log records OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA and every TLS/HTTP/script step, including each R-APDU (`script-rapdu`, `script-memory`). The same controls are available through `POST /api/scp81/bip` and `GET /api/scp81/script` (see `docs/api.md`). +- **PSK TLS server** (default) — a PSK TLS listener on **Host:Port** that answers with the TLS 1.2 PSK cipher suites of the spec and speaks the GP HTTP administration dialog (`X-Admin-*` headers, `200` with a command string or `204 No Content`). PSK keys come from the card presets (**Cards** tab): the key is picked by the identity the card sends in the handshake, and Start is refused when no preset has both parts. Keys are never stored or logged; an unrecognised identity is logged as `tls-psk-unknown`. +- **Pass-through (external server)** — no local listener: every BIP channel is connected to the configured external platform (Host and Port required), which terminates TLS and runs the administration dialog; the address the card requests is only logged. +- **Capture (dump)** — accepts the card's TCP channel and logs whatever it sends (e.g. the TLS ClientHello) without answering. + +**Script** selects the command list served over the session: **None** (leave the server's configured script) or one of the scripts created in the **Scripts** pill; **Restart script** re-queues the selected script with `force`, starting over from the first APDU. + +The state line shows the listener, the negotiated identity and live channels (bytes in/out); **Script results (R-APDUs)** lists each served C-APDU with its R-APDU and SW (`done/total` progress); the **HTTP OTA log** records OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA and every TLS/HTTP/script step (`tls-handshake`, `tls-request`, `script-send`, `script-rapdu`, `script-page`, `script-done`, `data-available`, `peer-close`). The same controls are available through `POST /api/scp81/bip` and `GET /api/scp81/script` (see `docs/api.md`). + +### Scripts + +The **Scripts** pill manages named APDU lists stored in `localStorage` (`otaman_scripts`) and sent to the server when a listener starts. Each list is a sequence of hex C-APDUs, one per line (`#`/`;` comments allowed). **New** creates one from a template: + +| Template | What it builds | +|---|---| +| **Empty** | an empty list | +| **Explore** | the reference administration sequence (`GET DATA FF21`, GET STATUS ISD/ELF/application listings, `GET DATA 0085`); long listings auto-continue through `SW 6310/CAFE` pages | +| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] from a `.cap` (optional SD AID, install/STK parameters, make selectable) via `POST /api/scp81/gen-install`; the file is only used to generate the APDUs — it is not stored, not even its name | +| **Delete** | DELETE APDUs from an AID list (one per line) with P2 = object only / object and related objects | + +The table lists each script with kind, APDU count and creation time; **Edit** opens the name + APDU editor and **Delete** removes it. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (`X-Admin-Script-Status`), a session that dies resends only the unexecuted APDUs (`X-Admin-Resume` continues, a fresh dialog restarts), and a completed script is closed with `204 No Content`. The Remote APDU → **RAM/GP** builder can feed a command chain straight into the run with **Queue in SCP81**. ## PWA diff --git a/README_RUS.md b/README_RUS.md index 635609a..152a5e9 100644 --- a/README_RUS.md +++ b/README_RUS.md @@ -31,7 +31,7 @@ npm run build ## Интерфейс -Шесть вкладок: **Remote APDU**, **SCP80**, **SCP81**, **Profiler**, **Card reader** и **Phone simulator**. Вкладки Remote APDU и SCP80 используют пиллы-подвкладки; во вкладке Card reader три подвкладки: **File manager**, **pySim command line** и **Raw APDU**; во вкладке Profiler — **Profiles**, **Card snapshots** и **Custom files**. +Семь вкладок верхнего уровня: **Remote APDU**, **SCP80**, **SCP81**, **Cards («Карты»)**, **Profiler**, **Card reader** и **Phone simulator**. Вкладки Remote APDU и SCP80 используют пиллы-подвкладки; вкладка **SCP81** — пиллы **Listener** и **Scripts**; во вкладке Card reader три подвкладки: **File manager**, **pySim command line** и **Raw APDU**; во вкладке Profiler — **Profiles**, **Card snapshots** и **Custom files**. --- @@ -323,7 +323,7 @@ CLA = `80` (GlobalPlatform v2.3.1). Удалённое управление со ## Вкладка SCP80 -Вкладка **SCP80** группирует SCP80-виды, переключаемые тремя пиллами: **Secured Packet**, **Cards** и **RAM**. Сборка защищённых пакетов по ETSI TS 102 225. +Вкладка **SCP80** группирует SCP80-виды, переключаемые двумя пиллами: **Secured Packet** и **RAM**. Сборка защищённых пакетов по ETSI TS 102 225. ### Secured Packet @@ -405,25 +405,27 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на - ISO 9797-1 - NIST SP 800-38B (CMAC) -### Cards +### Карты -Пилл **Cards** управляет сохранёнными конфигурациями карт (пресеты). Каждый пресет хранит криптографические ключи, настройки TAR и счётчик повторов для SCP80-операций. +Хранит сохранённые конфигурации карт (пресеты) в `localStorage`. Пресет содержит криптографические ключи, настройки SPI, TAR и счётчик повторов для SCP80-операций, а также пару **PSK identity / PSK key** для слушателя SCP81 HTTP OTA. «Карты» — **верхнеуровневая вкладка**. | Поле | Описание | |---|---| +| Name | Понятная метка (обязательна) | +| ICCID | Опциональный идентификатор карты | | SPI1 / SPI2 | Уровень безопасности и настройки PoR | -| Ключ KIc / KID | Hex ключи шифрования и MAC | -| Индекс KIc / KID | Номер версии ключа | +| Индекс KIc / KID | Номер версии ключа (задаётся вместе с ключами) | +| Ключ KIc / KID | Hex-ключи шифрования и MAC | | TAR | Toolkit Application Reference (3 байта) | -| Счётчик (CNTR) | 10-значный hex счётчик повторов, автоматически увеличивается после каждой успешной отправки SCP80 | +| Счётчик (CNTR) | 10-значный hex-счётчик повторов, автоматически увеличивается после каждой успешной отправки SCP80 | +| PSK identity | SCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии | +| PSK key | SCP81 HTTP OTA: 32 hex-символа (16 байт); ключ выбирается по идентификатору, который предъявляет карта | -**Добавить карту:** заполните имя, SPI1/SPI2, ключи KIc/KID и их индексы, TAR, нажмите **Add**. Карта появится в списке и станет доступна в выпаданом списке **Card preset** на RAM-вкладке. +Столбец **SCP81** показывает, задана ли в пресете рабочая пара PSK: **✓** (идентификатор и ключ), **⚠** (только одно из двух — слушатель такой пресет игнорирует), **—** (PSK нет). Идентификатор и ключ задаются вместе. -**Редактировать карту:** выберите карту в списке, измените поля, нажмите **Save**. +**Добавить карту:** заполните имя, ICCID (опционально), SPI1/SPI2, ключи и индексы KIc/KID, TAR, при необходимости пару PSK и нажмите **Add**. Карта появится в списке и станет доступна в выпадающем списке **Card preset** на вкладке RAM. -**Удалить карту:** выберите карту, нажмите **Delete**. Удаляет пресет из `localStorage`. - -**Счётчик:** 10-значный hex-счётчик (CNTR) автоматически увеличивается после каждой успешной отправки SCP80 (ручные отправки Secured Packet и RAM-операции). Обновлённый счётчик автоматически сохраняется обратно в пресет. +**Изменить/удалить:** **Edit** загружает пресет в форму (кнопка Add становится **Save**; **Cancel** очищает форму); **Remove** удаляет строку из `localStorage`. Успешная отправка SCP80 увеличивает и сохраняет счётчик повторов, а изменения сразу передаются работающему слушателю SCP81. ### RAM @@ -556,13 +558,30 @@ Delivery PoR (SPI2 `01`) проще — карта возвращает PoR на ## SCP81 -Вкладка **SCP81** управляет HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B). BIP-канал карты всегда перенаправляется на локальный слушатель сервера: +Вкладка **SCP81** управляет HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B) и содержит две подвкладки: **Listener** и **Scripts**. -- **Capture (dump)** — принимает TCP-канал карты и записывает всё, что она отправляет (например, TLS ClientHello), не отвечая. Удобно для изучения запросов карты. -- **PSK TLS server** — отвечает на рукопожатие PSK-наборами TLS 1.2 из спецификации и ведёт HTTP-диалог административной сессии GP (заголовки `X-Admin-*`, `200` со строкой команд или `204 No Content`). Укажите **PSK Identity**, которую использует карта, и **PSK ключ (hex)**; ключ передаётся только локальному серверу, не сохраняется и не записывается в журнал. -- **Script** — сценарий команд, отдаваемых в сессии: **Память + ELF** (по умолчанию) отправляет `GET DATA FF21` (доступная энергонезависимая/энергозависимая память, число апплетов) и `GET STATUS P1=20/10` (реестр Executable Load File и модулей) как RAM/GP-команды в Command Scripting template по TS 102 226, по одной C-APDU на запрос; **None** закрывает каждую сессию ответом `204`. Свой список APDU можно задать через API. +**Listener** запускает и останавливает цель, на которую перенаправляется BIP-канал карты, в одном из трёх режимов: -Строка состояния показывает слушатель, согласованную identity и активные каналы (байты in/out); журнал фиксирует OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA и каждый шаг TLS/HTTP. Те же функции доступны через `POST /api/scp81/bip` (см. `docs/api.md`). +- **PSK TLS server** (по умолчанию) — PSK TLS-слушатель на **Host:Port**, отвечающий PSK-наборами TLS 1.2 из спецификации и ведущий HTTP-диалог административной сессии GP (заголовки `X-Admin-*`, `200` со строкой команд или `204 No Content`). PSK-ключи берутся из пресетов карт (вкладка **Cards**): ключ выбирается по идентификатору, который карта присылает в рукопожатии; если ни у одного пресета нет пары, Start не запускается. Ключи не сохраняются и не записываются в журнал; незнакомый идентификатор помечается записью `tls-psk-unknown`. +- **Pass-through (external server)** — без локального слушателя: каждый BIP-канал подключается к указанной внешней платформе (нужны Host и Port), которая завершает TLS и ведёт административный диалог; запрошенный картой адрес только журналируется. +- **Capture (dump)** — принимает TCP-канал карты и записывает всё, что она отправляет (например, TLS ClientHello), не отвечая. + +**Script** выбирает список команд, отдаваемый в сессии: **None** (оставить настроенный на сервере скрипт) или один из скриптов, созданных на подвкладке **Scripts**; **Restart script** заново ставит выбранный скрипт в очередь с `force`, начиная с первого APDU. + +Строка состояния показывает слушатель, согласованный идентификатор и активные каналы (байты in/out); панель **Script results (R-APDUs)** перечисляет каждый отданный C-APDU с его R-APDU и SW (прогресс `done/total`); журнал **HTTP OTA log** фиксирует OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA и каждый шаг TLS/HTTP/скрипта (`tls-handshake`, `tls-request`, `script-send`, `script-rapdu`, `script-page`, `script-done`, `data-available`, `peer-close`). Те же функции доступны через `POST /api/scp81/bip` и `GET /api/scp81/script` (см. `docs/api.md`). + +### Скрипты + +Подвкладка **Scripts** управляет именованными списками APDU, которые хранятся в `localStorage` (`otaman_scripts`) и передаются серверу при старте слушателя. Каждый список — последовательность hex C-APDU, по одной в строке (допускаются комментарии `#`/`;`). Кнопка **New** создаёт список из шаблона: + +| Шаблон | Что строит | +|---|---| +| **Empty** | пустой список | +| **Explore** | эталонная административная последовательность (`GET DATA FF21`, листинги GET STATUS ISD/ELF/приложений, `GET DATA 0085`); длинные листинги автоматически продолжаются страницами `SW 6310/CAFE` | +| **Install from .cap** | INSTALL [for load] → LOAD ×N → INSTALL [for install] из `.cap` (опционально SD AID, параметры install/STK, make selectable) через `POST /api/scp81/gen-install`; файл используется только для генерации APDU — он не сохраняется, как и его имя | +| **Delete** | APDU DELETE из списка AID (по одному в строке) с P2 = object only / object and related objects | + +Таблица показывает имя, тип, число APDU и время создания каждого скрипта; **Edit** открывает редактор имени и списка APDU, **Delete** удаляет скрипт. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (`X-Admin-Script-Status`), оборвавшаяся сессия досылает только невыполненные APDU (`X-Admin-Resume` продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом `204 No Content`. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой **«В очередь SCP81»**. ## PWA diff --git a/frontend/help-ru.html b/frontend/help-ru.html index 5f7817b..cc60650 100644 --- a/frontend/help-ru.html +++ b/frontend/help-ru.html @@ -45,7 +45,7 @@
  • Шапка — версия приложения, кнопка INSTALL PWA (появляется, когда браузер предлагает установку, для офлайн-работы), ссылки на проект на GitHub и на эту справку, переключатель языка EN/RU и переключатель тёмной/светлой темы. Рядом с заголовком небольшой индикатор показывает состояние сервера/карты (серая точка = подключение, красная = нет сервера, значки карты = нет карты / инициализация / карта готова) и компактный значок ADM ✓ (зелёный, администраторский PIN подтверждён) или ADM ✗ (красный, не подтверждён) для текущей сессии карты.
  • Выбор языка и темы хранится в localStorage и сохраняется между перезагрузками.
  • Вкладки верхнего уровня: Remote APDU (SIM RFM, USIM RFM, Expanded Script, RAM/GP, HTTP OTA, Разбор C-APDU, «Парсер ответов»), SCP80 (Secured Packet, RAM), SCP81 («Слушатель», «Скрипты»), «Карты», «Профайлер» (вкладки «Профили», «Снимки карт», «Пользовательские файлы»), «Картридер» (Файловый менеджер, Командная строка pySim, Отправка APDU) и «Симулятор телефона».
  • -
  • Ссылка справка открывает эту документацию на разделе, соответствующем текущему представлению (например, вкладка «Профайлер» открывает §5).
  • +
  • Ссылка справка открывает эту документацию на разделе, соответствующем текущему представлению (например, вкладка «Профайлер» открывает §7).
  • @@ -274,25 +274,7 @@

    Кнопка Проверить в pySim сверяет собранный пакет с эталонной реализацией OtaDialectSms.encode_cmd. Кнопка Отправить на карту доставляет пакет через ENVELOPE SMS-PP-DOWNLOAD (при подключении к серверу). Полученный Proof of Receipt декодируется и показывается строкой статуса PoR (статус, TAR, счётчик, сырой PoR); статусное слово и данные ответа последней команды подставляются в подвкладку «Парсер ответов» (Remote APDU), а успешный PoR увеличивает счётчик повторов и очищает пакет.

    -

    3.2 Карты

    -

    Хранит предустановки карт локально в браузере (localStorage), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, а слушатель SCP81 HTTP OTA — находить PSK-ключи. Вкладка «Карты» — верхнеуровневая.

    - - - - - - - - - - - - - -
    ПолеОписание
    NameПонятная метка
    ICCIDОпциональный идентификатор карты
    KIc / KIDИндикаторы ключа и алгоритма (например, 15 = индекс 1, 3DES-CBC2; x2 = AES)
    SPI1 / SPI2Security Parameter Indicators
    TARToolkit Application Reference
    CounterСчётчик повторов (5 байт)
    KIc key / KID key16/24/32 hex-символа (ключи 8/16/24 байта 3DES) или 32/48/64 hex-символа (ключи 16/24/32 байта AES)
    PSK identitySCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии (например, 89390100000129506903)
    PSK keySCP81 HTTP OTA: 32 hex-символа (16 байт). Слушатель выбирает этот ключ, когда карта предъявляет совпадающий идентификатор; предустановка с ключом без идентификатора игнорируется (и помечается в таблице)
    -

    Столбец SCP81 показывает, задана ли в предустановке рабочая пара PSK. Кнопка Изменить загружает предустановку в форму (кнопка становится Сохранить; Отмена очищает форму), поэтому поля можно менять без повторного ввода карты. Обмен предустановками: Экспорт в JSON и Экспорт в файл для выгрузки, Импорт из файла, Вставить и импортировать или Импорт JSON из буфера для загрузки. Выбранная предустановка автоматически заполняет форму Secured Packet; изменения сразу передаются работающему слушателю SCP81.

    - -

    3.3 RAM

    +

    3.2 RAM

    Выполняет операции удалённого управления приложениями (Remote Application Management) как защищённые пакеты SCP80 через SMS-PP-DOWNLOAD ENVELOPE. Карта должна поддерживать SCP03 (AES или 3DES). Предустановка карты со вкладки Карты обеспечивает SPI, ключи, TAR и счётчик.

    Операции

    @@ -315,10 +297,53 @@
    -

    4. Вкладка «Картридер» (pySim)

    +

    4. Вкладка «Карты»

    +

    Хранит предустановки карт локально в браузере (localStorage), чтобы представление Secured Packet могло автоматически подставлять ключи и параметры, а слушатель SCP81 HTTP OTA — находить PSK-ключи. «Карты» — верхнеуровневая вкладка.

    + + + + + + + + + + + + + +
    ПолеОписание
    NameПонятная метка (обязательна)
    ICCIDОпциональный идентификатор карты
    KIc / KIDИндикаторы ключа и алгоритма (например, 15 = индекс 1, 3DES-CBC2; x2 = AES); задаются вместе с ключами
    SPI1 / SPI2Security Parameter Indicators
    TARToolkit Application Reference
    CounterСчётчик повторов (5 байт); увеличивается и сохраняется после каждой успешной отправки SCP80
    KIc key / KID key16/24/32 hex-символа (ключи 8/16/24 байта 3DES) или 32/48/64 hex-символа (ключи 16/24/32 байта AES)
    PSK identitySCP81 HTTP OTA: идентификатор, который карта присылает в TLS-рукопожатии (например, 89390100000129506903)
    PSK keySCP81 HTTP OTA: 32 hex-символа (16 байт) для PSK TLS-слушателя; ключ выбирается по идентификатору, который предъявляет карта
    +

    Столбец SCP81 показывает, задана ли в предустановке рабочая пара PSK: (зелёный) — идентификатор и ключ заданы; (жёлтый) — задано только одно из двух, и слушатель такую предустановку игнорирует; — PSK нет. Идентификатор и ключ PSK задаются вместе. Кнопка Редактировать загружает предустановку в форму (кнопка Add становится Сохранить; Отмена очищает форму), поэтому поля можно менять без повторного ввода карты; Удалить удаляет строку. Обмен предустановками: Экспорт в JSON и Экспорт в файл для выгрузки, Импорт из файла, Вставить и импортировать или Импорт JSON из буфера для загрузки. Выбранная предустановка автоматически заполняет форму Secured Packet; изменения сразу передаются работающему слушателю SCP81.

    +
    + +
    +

    5. Вкладка SCP81

    +

    Управляет HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B): BIP-канал карты перенаправляется на цель, которую слушает сервер (или на внешнюю платформу), а терминальная сторона административной сессии эмулируется. Две подвкладки: «Слушатель» и «Скрипты».

    +

    5.1 Слушатель

    +

    Кнопки Start / Остановить управляют целью; Перезапустить скрипт ставит выбранный скрипт в очередь заново с force, начиная прогон с первого APDU. Режимы:

    + +

    Сценарий выбирает список команд, отдаваемый в сессии — Нет (оставить настроенный на сервере скрипт) или один из скриптов подвкладки «Скрипты»; выбранный список передаётся серверу при старте слушателя.

    +

    Строка состояния показывает слушатель, согласованный идентификатор и активные каналы (байты in/out). Панель Script results (R-APDUs) перечисляет каждый отданный C-APDU с его R-APDU/SW и прогрессом done/total; журнал HTTP OTA log фиксирует OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA и каждый шаг TLS/HTTP/скрипта (tls-handshake, tls-request, script-send, script-rapdu, script-page, script-done, data-available, peer-close), кнопка Clear очищает его.

    +

    5.2 Скрипты

    +

    Именованные списки APDU хранятся локально (otaman_scripts) и передаются серверу при старте слушателя. Каждый список — последовательность hex C-APDU (по одной в строке; допускаются комментарии #/;). Кнопка Новый создаёт список из шаблона:

    + +

    Таблица показывает имя, тип, число APDU и время создания каждого скрипта, а также кнопки Редактировать и Удалить; в редакторе есть поле имени и текстовая область APDU. В ходе сессии сервер отдаёт по одному C-APDU на каждый POST карты и отслеживает выполнение: карта сообщает статус в следующем POST (X-Admin-Script-Status), оборвавшаяся сессия досылает только невыполненные APDU (X-Admin-Resume продолжает, новый диалог начинает заново), а завершённый скрипт закрывается ответом 204 No Content. Конструктор RAM/GP вкладки Remote APDU может отправить цепочку команд прямо в прогон кнопкой «В очередь SCP81».

    +
    + +
    +

    6. Вкладка «Картридер» (pySim)

    Подключение к локальному pysim-otaman-server для работы с картой: введите URL сервера (по умолчанию http://127.0.0.1:8080) и нажмите Подключиться. Область статуса показывает состояние ридера/карты, а Подключить карту (пере)инициализирует карту после вставки. Подвкладки: Файловый менеджер, Командная строка pySim и Отправка APDU. «Профайлер» и «Симулятор телефона» — отдельные вкладки верхнего уровня.

    -

    4.1 Файловый менеджер

    +

    6.1 Файловый менеджер

    Дерево файловой системы отображается слева; выбор файла открывает панель деталей справа. Элементы сгруппированы: DF выше EF, сортировка по FID или символьному имени (пиллы и кнопка «Проверить все файлы» закреплены над прокручиваемым деревом; выбор сохраняется в localStorage). При выборе файла над содержимым также показываются FID, тип файла, размер / структура записей и декодированный FCI.

    -

    4.2 Командная строка pySim

    +

    6.2 Командная строка pySim

    Выполнение любых команд pySim-shell с подсказками (300 мс) и автодополнением.

    -

    4.3 Отправка APDU

    +

    6.3 Отправка APDU

    Отправка произвольного APDU и просмотр ответа.

    -

    4.4 Сценарии использования

    +

    6.4 Сценарии использования

    Сценарий A — Работа с файлами, не входящими в модель pySim («Пользовательские файлы»)

      @@ -372,7 +397,7 @@
      -

      5. Профайлер

      +

      7. Профайлер

      Проверяет соответствие карты именованному профилю — упорядоченному набору правил, описывающих ожидаемую файловую систему и (опционально) содержимое файлов. Профили хранятся в localStorage.

      Список профилей

        @@ -412,13 +437,13 @@

        Добавление файлов, не покрытых моделью pySim. Пользовательский файл всегда имеет полный путь от MF или ADF (ADF.USIM, ADF.ISIM): выберите корень, введите путь родительского DF (сам корень, стандартный DF из дерева файлового менеджера или пользовательский DF — любой вложенности, с подсказками при вводе; родитель, ещё не встречавшийся в дереве, остаётся допустимым и помечается ), 4-hex FID и псевдоним (EF.…/DF.…; префикс определяет, EF это или DF). Канонический путь убирает прежнюю неоднозначность, когда один и тот же файл можно было описать и относительно, и абсолютно. Добавленные файлы появляются в дереве «Файловый менеджер»; в каждой строке есть «Редактировать» (путь + псевдоним; изменение пути DF перепривязывает дочерние записи — кнопка становится «Сохранить», «Отмена» отменяет) и «Удалить» (удаление DF удаляет и его дочерние записи после подтверждения). Список сохраняется в localStorage; обмен — Экспорт в JSON / Экспорт в файл / Импорт; старые относительные пути (например, a153/4954) разрешаются при загрузке, неразрешимые отбрасываются и отмечаются в списке.

        -

        6. Симулятор телефона

        +

        8. Симулятор телефона

        Работа с сессией Card Application Toolkit. Две подвкладки: «Телефон» (меню STK, STATUS и опрос, подписанные события, журнал проактивных команд) и «Конфигурация TR» (данные ответов, подставляемые в TERMINAL RESPONSE для проактивных команд).

        -

        6.1 Меню STK

        +

        8.1 Меню STK

        Если карта выдала команду SET UP MENU, вверху этого представления появляется блок «Меню STK» с изумрудной кнопкой STK: <название>, открывающей оверлей меню (браузер STK-меню карты). Если карта не задала меню, вместо кнопки показывается «Меню не задано картой». Состояние меню обновляется при каждом открытии представления. Интерактивные проактивные команды всегда получают TERMINAL RESPONSE: оверлей ждёт вашего выбора, и если вы не ответили и не нажали Timeout, сервер сам отвечает результатом timeout через --menu-timeout секунд (по умолчанию 60, 0 отключает). Назад и Timeout продолжают диалог с картой: если карта в ответ выдаёт следующую проактивную команду (SELECT ITEM или DISPLAY TEXT), панель показывает её; кэшированное верхнее меню появляется только когда карте больше нечего выполнять.

        -

        6.2 Подписанные события (SET UP EVENT LIST)

        +

        8.2 Подписанные события (SET UP EVENT LIST)

        События, которые отслеживает карта. У каждого события есть кнопка Отправить, открывающая форму, специфичную для типа события:

        • События без данных (User Activity, Idle Screen, Data Available, …) — уведомление в один клик
        • @@ -428,16 +453,16 @@

        Отправка события использует ENVELOPE(Event Download) по TS 102 223 / TS 131 111.

        -

        6.3 Журнал проактивных команд

        +

        8.3 Журнал проактивных команд

        Хронологический список извлечённых проактивных команд. Каждая строка показывает время, код типа, имя и декодированный квалификатор (для команд, у которых он есть). Раскрытие строки показывает декодированную команду: текст и пункты DISPLAY TEXT / SELECT ITEM / SET UP MENU, параметры BIP-каналов, действия TIMER MANAGEMENT, названия квалификаторов PROVIDE LOCAL INFORMATION (все стандартные, включая ESN 07, MEID 0B и Supported RATs 1A) и SEND SHORT MESSAGE — разбирается SMS TPDU (тип, TP-MR, TP-DA, TP-PID, TP-DCS, срок действия, TP-UDL), а пользовательские данные показываются как текст для текстовых кодировок (GSM 7-бит, UCS2, 8-бит) или как secured-пакет (TS 31.115) при TP-PID = 7F (SIM data download); заголовки конкатенации UDH декодируются. Для команд с данными ответа показывается строка Ответ: с байтами TERMINAL RESPONSE (без служебных TLV); ответы PROVIDE LOCAL INFORMATION декодируются через словарь данных PLI.

        -

        6.4 TERMINAL PROFILE

        -

        Блок TERMINAL PROFILE (рядом с «STATUS и опрос») содержит кнопки «Отправить» (повторная отправка, как «Спасение») и «Настроить». В диалоге настройки: селектор пресетов (модели устройств, например профиль BIP-совместимого аппарата из этого проекта), поле hex и форма с флажком на каждый бит профиля по TS 102 223 §5.2 (байты 1–33; далее — обобщённые подписи); каждый байт — вертикальный список битов; блоки размещены фиксированными группами (байты 1–12 в 2 колонки, 13–16 в 4, 17–18 в 2, 19–21 в 3, 22–25 в 2, 26–28 в 3, 29–30 в 2, далее по одному в строке); переключение бита обновляет hex, а правка hex перерисовывает форму — поле hex основное, неизвестные байты и биты сохраняются. Кнопка «Применить» отправляет новое значение на сервер (и далее на карту), сбрасывая STK-сессию как «Спасение»; изменение хранится только в памяти (значение --terminal-profile — стартовое по умолчанию).

        +

        8.4 TERMINAL PROFILE

        +

        Блок TERMINAL PROFILE (рядом с «STATUS и опрос») содержит кнопки «Отправить» (повторная отправка, как «Спасение») и «Настроить». В диалоге настройки: селектор пресетов (модели устройств, например профиль BIP-совместимого аппарата из этого проекта), поле hex и форма с флажком на каждый бит профиля по TS 102 223 §5.2 / TS 31.111 §5.2 (байты 1–39; для битов 3GPP используются имена из TS 31.111); каждый байт — вертикальный список битов; блоки размещены фиксированными группами (байты 1–12 в 2 колонки, 13–16 в 4, 17–18 в 2, 19–21 в 3, 22–25 в 2, 26–28 в 3, 29–30 в 2, далее по одному в строке); переключение бита обновляет hex, а правка hex перерисовывает форму — поле hex основное, неизвестные байты и биты сохраняются. Кнопка «Применить» отправляет новое значение на сервер (и далее на карту), сбрасывая STK-сессию как «Спасение»; изменение хранится только в памяти (значение --terminal-profile — стартовое по умолчанию).

        -

        6.5 Опрос STATUS

        +

        8.5 Опрос STATUS

        Кнопка Отправить STATUS отправляет STATUS (F2) вручную. Переключатель Опрос включает фоновый опрос: после настраиваемого интервала бездействия (аргумент сервера --poll-interval, 1–255 с, по умолчанию 30 с, 0 отключает опрос) сервер отправляет STATUS и обрабатывает любую ожидающую проактивную команду. При извлечении карты опрос останавливается, а состояние карты сбрасывается.

        -

        6.6 «Конфигурация TR» — данные ответа PROVIDE LOCAL INFORMATION

        +

        8.6 «Конфигурация TR» — данные ответа PROVIDE LOCAL INFORMATION

        Редактируемые hex-значения для всех 22 квалификаторов PLI (TS 102 223 §8.6 + TS 131 111). У десяти квалификаторов есть встроенные формы декодирования/кодирования:

        • 00 Location Info (MCC, MNC, LAC/TAC, Cell ID)
        • @@ -450,10 +475,10 @@
        -

        7. Установка сервера

        +

        9. Установка сервера

        Для работы с картой (вкладка «Картридер», «Симулятор телефона», доставка OTA) нужен локальный pysim-otaman-server — встроенный в OTAMan HTTP-сервер, оборачивающий pySim, работающий с ридером через PC/SC или serial и раздающий сам PWA (откройте http://127.0.0.1:8080).

        -

        7.1 Требования

        +

        9.1 Требования

        • Python 3.8+ с pip
        • Git
        • @@ -461,20 +486,20 @@
        • Только Windows — используйте Python 3.10–3.13 (рекомендуется 3.13): pyscard (обёртка драйвера PC/SC) поставляет готовые wheels для этих версий. На Python 3.9 / 3.14 pip собирает pyscard из исходников, для чего требуются Microsoft C++ Build Tools («Desktop development with C++»). Мост SMPP (smpp.twisted3) на Windows намеренно не устанавливается, поэтому для Python 3.10–3.13 C++ Build Tools не нужны.
        -

        7.2 Быстрый старт — Linux / macOS

        +

        9.2 Быстрый старт — Linux / macOS

        git clone https://github.com/anttro/otaman.git
         cd otaman
         chmod +x setup.sh start.sh
         ./setup.sh          # создаёт .venv, устанавливает pysim + сервер (однократно)
         ./start.sh          # запускает сервер (PWA + API, автоопределение ридера)
        -

        7.3 Быстрый старт — Windows

        +

        9.3 Быстрый старт — Windows

        git clone https://github.com/anttro/otaman.git
         cd otaman
         setup.bat           # создаёт .venv, устанавливает pysim + сервер (однократно)
         start.bat           # запускает сервер (PWA + API)
        -

        7.4 Вспомогательные скрипты

        +

        9.4 Вспомогательные скрипты

        @@ -483,7 +508,7 @@ start.bat # запускает сервер (PWA + API)
        СкриптНазначение
        -

        7.5 Автоопределение ридера

        +

        9.5 Автоопределение ридера

        • PC/SC (Linux)start.sh передаёт -p 0, если запущен демон pcscd
        • PC/SC (Windows)start.bat всегда использует -p 0 (PC/SC встроен в Windows)
        • @@ -492,7 +517,7 @@ start.bat # запускает сервер (PWA + API)

        Если карта отсутствует, вкладка «Картридер» показывает «Карта не обнаружена. Вставьте карту и нажмите Подключить карту».

        -

        7.6 Ручная установка

        +

        9.6 Ручная установка

        # Создать и активировать venv
         python3 -m venv .venv
         source .venv/bin/activate   # Linux/macOS
        @@ -511,7 +536,7 @@ pysim-otaman-server --http-port 8080
        -

        8. Совместимость версий

        +

        10. Совместимость версий

        diff --git a/frontend/help.html b/frontend/help.html index 03696e6..73f8a96 100644 --- a/frontend/help.html +++ b/frontend/help.html @@ -45,7 +45,7 @@
      • 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) and a compact ADM ✓ (green, administrator PIN verified) or ADM ✗ (red, not verified) badge for the current card session.
      • Language and theme choices are stored in localStorage and persist across reloads.
      • Top-level tabs: Remote APDU (SIM RFM, USIM RFM, Expanded Script, RAM/GP, HTTP OTA, C-APDU Parser, Response parser), SCP80 (Secured Packet, RAM), SCP81 (Listener, Scripts), Cards, Profiler (list tabs Profiles, Card snapshots, Custom files), Card reader (File manager, pySim command line, Raw APDU), and Phone simulator.
      • -
      • The help link opens this documentation at the section matching the current view (e.g. the Profiler tab opens §5).
      • +
      • The help link opens this documentation at the section matching the current view (e.g. the Profiler tab opens §7).
      • @@ -241,7 +241,7 @@

        3. SCP80 tab

        -

        The SCP80 top-level tab groups the SCP80-related views. It is switched by three pills: Secured Packet, Cards, and RAM. Assembles SCP80 secured packets per ETSI TS 102 225.

        +

        The SCP80 top-level tab groups the SCP80-related views. It is switched by two pills: Secured Packet and RAM. Assembles SCP80 secured packets per ETSI TS 102 225.

        3.1 Secured Packet

        Builds SCP80 secured packets per ETSI TS 102 225.

        @@ -274,25 +274,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 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 Response parser tab, and a successful PoR advances the replay counter and clears the packet.

        -

        3.2 Cards

        -

        Stores card presets locally in the browser (localStorage) so the Secured Packet view can auto-fill keys and parameters, and so the SCP81 HTTP OTA listener can look up PSK keys. The Cards tab is a top-level tab.

        -
        PWA (OTAMan)СерверСтатус
        - - - - - - - - - - - - -
        FieldDescription
        NameHuman-readable label
        ICCIDOptional card identifier
        KIc / KIDKey and algorithm indicators (e.g. 15 = index 1, 3DES-CBC2; x2 = AES)
        SPI1 / SPI2Security Parameter Indicators
        TARToolkit Application Reference
        CounterReplay counter (5 bytes)
        KIc key / KID key16/24/32 hex chars (8/16/24-byte 3DES) or 32/48/64 hex chars (16/24/32-byte AES) keys
        PSK identitySCP81 HTTP OTA: the identity the card sends in the TLS handshake (e.g. 89390100000129506903)
        PSK keySCP81 HTTP OTA: 32 hex chars (16 bytes). The listener selects this key when the card presents the matching identity; a preset with a key but no identity is ignored (and flagged in the table)
        -

        The SCP81 column shows whether the preset supplies a usable PSK pair. Edit loads a preset into the form (the button becomes Save; Cancel clears it) so fields can be changed without re-entering the card. Presets can be shared with Export as JSON and Export to file, and restored with Import from file, Paste & import, or Import JSON from clipboard. The selected card preset auto-fills the Secured Packet form; edits are pushed into a running SCP81 listener automatically.

        - -

        3.3 RAM

        +

        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.

        Operations

        @@ -315,10 +297,53 @@
        -

        4. Card reader (pySim) tab

        +

        4. Cards tab

        +

        Stores card presets locally in the browser (localStorage) so the Secured Packet view can auto-fill keys and parameters, and so the SCP81 HTTP OTA listener can look up PSK keys. Cards is a top-level tab.

        + + + + + + + + + + + + + +
        FieldDescription
        NameHuman-readable label (required)
        ICCIDOptional card identifier
        KIc / KIDKey and algorithm indicators (e.g. 15 = index 1, 3DES-CBC2; x2 = AES), required together with the keys
        SPI1 / SPI2Security Parameter Indicators
        TARToolkit Application Reference
        CounterReplay counter (5 bytes); advanced and saved after each successful SCP80 send
        KIc key / KID key16/24/32 hex chars (8/16/24-byte 3DES) or 32/48/64 hex chars (16/24/32-byte AES) keys
        PSK identitySCP81 HTTP OTA: the identity the card sends in the TLS handshake (e.g. 89390100000129506903)
        PSK keySCP81 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 as JSON / Export to file and restored with Import from file, Paste & import, or Import JSON from clipboard. The selected card preset auto-fills the Secured Packet form; edits are pushed into a running SCP81 listener automatically.

        +
        + +
        +

        5. SCP81 tab

        +

        Drives HTTP OTA (GP RAM over HTTP, GPC v2.2 Amendment B): the card's BIP channel is redirected to a target the server listens on (or to an external platform), and the terminal side of the administration session is emulated. Two pills: Listener and Scripts.

        +

        5.1 Listener

        +

        Start / Stop control the target; Restart script queues the selected script again with force, restarting its run from the first APDU. Modes:

        +
          +
        • PSK TLS server (default) — a PSK TLS listener on Host:Port that answers with the TLS 1.2 PSK cipher suites of the spec and speaks the GP HTTP administration dialog (X-Admin-* headers, 200 with a command string or 204 No Content). PSK keys come from the card presets (Cards tab): the listener picks the key by the identity the card sends in the handshake, and Start is refused when no preset has both parts. The key is never stored or logged; tls-psk-unknown marks an unrecognised identity.
        • +
        • Pass-through (external server) — no local listener: every BIP channel is connected to the configured external platform (Host and Port required), which terminates TLS and runs the administration dialog; the address the card requests is only logged.
        • +
        • Capture (dump) — accepts the card's TCP channel and logs whatever it sends (e.g. the TLS ClientHello) without answering.
        • +
        +

        Script selects the command list served over the session — None (leave the server's configured script) or one of the scripts from the Scripts pill; the chosen list is sent to the server when the listener starts.

        +

        The state line shows the listener, the negotiated identity and live channels (bytes in/out). Script results (R-APDUs) lists each served C-APDU with its R-APDU/SW and a done/total progress; the HTTP OTA log records OPEN/CLOSE CHANNEL, SEND/RECEIVE DATA and every TLS/HTTP/script step (tls-handshake, tls-request, script-send, script-rapdu, script-page, script-done, data-available, peer-close), with Clear.

        +

        5.2 Scripts

        +

        Named APDU lists stored locally (otaman_scripts) and sent to the server when a listener starts. Each list is a sequence of hex C-APDUs (one per line; #/; comments allowed). New creates one from a template:

        +
          +
        • Empty — start from scratch.
        • +
        • Explore — the reference administration sequence (GET DATA FF21, GET STATUS ISD/ELF/application listings, GET DATA 0085); long listings auto-continue through the SW 6310/CAFE pages.
        • +
        • Install from .cap — pick a .cap plus optional SD AID, install/STK parameters and make selectable; Generate builds INSTALL [for load] → LOAD ×N → INSTALL [for install]. The file is only used to generate the APDUs — it is not stored, not even its name.
        • +
        • Delete — AID list (one per line) and P2 (object only / object and related objects) → DELETE APDUs.
        • +
        +

        The table lists each script with its kind, APDU count and creation time, plus Edit and Delete; the editor has a name field and the APDU textarea. Over a session the server serves one C-APDU per card POST and tracks execution: the card reports status in its next POST (X-Admin-Script-Status), a session that dies resends only the unexecuted APDUs (X-Admin-Resume continues, a fresh dialog restarts), and a completed script is closed with 204 No Content. The Remote APDU tab's RAM/GP builder can feed a command chain straight into the run with Queue in SCP81.

        +
        + +
        +

        6. Card reader (pySim) tab

        Connects to a local pysim-otaman-server for live card operations: enter the server URL (default http://127.0.0.1:8080) and press Connect. The status area shows the reader/card state, and Equip card (re)initializes the card after insertion. Sub-tabs: File manager, pySim command line, and Raw APDU. The Profiler and Phone simulator are separate top-level tabs.

        -

        4.1 File manager

        +

        6.1 File manager

        The file system tree is displayed on the left; selecting a file opens its detail pane on the right. Entries are grouped with DFs above EFs and sorted by FID or symbolic Name (pills pinned above the scrolling tree together with Probe all files; the choice is remembered in localStorage). Selecting a file also shows its FID, file type, size / record layout and the decoded FCI above the content pane.

        • Read — reads the selected file (auto-detects transparent vs record files)
        • @@ -327,13 +352,13 @@
        • Probe all files — walks the whole tree (including custom files) and marks every entry present (normal) or absent (red ✗, no expand arrow); empty-but-present DFs show (empty). Shows progress N / total, can be stopped, and finishes with a present/absent summary. Files are only verified when expanded or probed — browsing stays lazy.
        -

        4.2 pySim command line

        +

        6.2 pySim command line

        Execute any pySim-shell command with usage hints (300 ms) and autocomplete.

        -

        4.3 Raw APDU

        +

        6.3 Raw APDU

        Send an arbitrary APDU and view the raw response.

        -

        4.4 Usage scenarios

        +

        6.4 Usage scenarios

        Scenario A — Working with files not in pySim’s model (Custom files)

          @@ -372,7 +397,7 @@
          -

          5. Profiler

          +

          7. Profiler

          Verifies that a card matches a named profile — an ordered set of rules describing the expected file system and (optionally) file contents. Profiles are stored in localStorage.

          Profile list

            @@ -412,13 +437,13 @@

            Add files that pySim’s model does not cover. A custom file always has a full path rooted at MF or an ADF (ADF.USIM, ADF.ISIM): pick the root, type the parent DF path (the root itself, a standard DF known from the file-manager tree, or a custom DF — any depth, with suggestions while you type; a parent that has not been seen in the tree yet stays valid and is marked ), the 4-hex FID and an alias (EF.…/DF.…; the prefix decides whether the entry is an EF or a DF). The canonical path removes the old ambiguity where the same file could be described both relatively and absolutely. Added files appear in the File manager tree; each row has Edit (path + alias; changing a DF’s path re-points its child entries — the button becomes Save, Cancel aborts) and Delete (deleting a DF also deletes its child entries after a confirmation). The list persists in localStorage and can be shared with Export as JSON / Export to file / Import; legacy relative paths (e.g. a153/4954) are resolved on load, unresolvable ones are dropped and reported in the list.

            -

            6. Phone simulator

            +

            8. Phone simulator

            Interacts with the Card Application Toolkit session. The view has two pills: Phone (STK menu, STATUS and polling, subscribed events, proactive command log) and TR Config (response data injected into TERMINAL RESPONSEs for proactive commands).

            -

            6.1 STK menu

            +

            8.1 STK menu

            When the card has issued a SET UP MENU command, a “STK menu” block appears at the top of this view with an emerald STK: <title> button that opens the menu overlay (same as the card’s STK menu browser). If the card has not set up a menu, the block shows “No menu set by the card” instead. The menu state is refreshed each time the view is opened. User-interactive proactive commands always get a TERMINAL RESPONSE: the overlay pauses for your choice, and if you neither answer nor press Timeout, the server answers with a timeout result after the --menu-timeout seconds (default 60, 0 disables). Back and Timeout keep the dialogue with the card going: when the card replies with a further proactive command (SELECT ITEM or DISPLAY TEXT) the panel shows it; the cached top menu appears only when the card has nothing more to execute.

            -

            6.2 Subscribed events (SET UP EVENT LIST)

            +

            8.2 Subscribed events (SET UP EVENT LIST)

            The events the card monitors. Each event has a Send button that opens a form specific to the event type:

            • No-data events (User Activity, Idle Screen, Data Available, …) — one-click notification
            • @@ -428,16 +453,16 @@

            Sending an event uses ENVELOPE(Event Download) per TS 102 223 / TS 131 111.

            -

            6.3 Proactive command log

            +

            8.3 Proactive command log

            Chronological list of fetched proactive commands. Each row shows the elapsed time, type code, name, and a decoded qualifier (for commands that have one). Expanding a row shows the decoded command: DISPLAY TEXT / SELECT ITEM / SET UP MENU text and items, BIP channel parameters, TIMER MANAGEMENT actions, PROVIDE LOCAL INFORMATION qualifier names (all standard qualifiers, including ESN 07, MEID 0B and Supported RATs 1A), and SEND SHORT MESSAGE — the SMS TPDU is parsed (type, TP-MR, TP-DA, TP-PID, TP-DCS, validity period, TP-UDL) with the user data shown as text for text codings (GSM 7-bit, UCS2, 8-bit) or as a secured packet (TS 31.115) when TP-PID = 7F (SIM data download); UDH concatenation headers are decoded. Commands with response data show a Response: line with the TERMINAL RESPONSE bytes (boilerplate TLVs stripped); PROVIDE LOCAL INFORMATION responses are decoded using the PLI data dictionary decoders.

            -

            6.4 TERMINAL PROFILE

            -

            The TERMINAL PROFILE block (next to STATUS and Polling) offers Send (re-sends it, like Rescue) and Configure. The Configure dialog has a preset selector (device models, e.g. this project's BIP-capable handset profile), a hex field and a form with one checkbox per profile bit decoded per TS 102 223 §5.2 (bytes 1–33; later bytes get generic labels), each byte is a vertical list of its bits, placed in fixed column groups (bytes 1-12 in 2 columns, 13-16 in 4, 17-18 in 2, 19-21 in 3, 22-25 in 2, 26-28 in 3, 29-30 in 2, later bytes one per row); toggling a bit updates the hex and editing the hex re-renders the form — the hex field is authoritative and unknown bytes/bits are preserved. Apply sends the new value to the server (and on to the card), resetting the STK session like Rescue; the change is in-memory only (the --terminal-profile CLI value is the startup default).

            +

            8.4 TERMINAL PROFILE

            +

            The TERMINAL PROFILE block (next to STATUS and Polling) offers Send (re-sends it, like Rescue) and Configure. The Configure dialog has a preset selector (device models, e.g. this project's BIP-capable handset profile), a hex field and a form with one checkbox per profile bit decoded per TS 102 223 §5.2 / TS 31.111 §5.2 (bytes 1–39, 3GPP-defined bits use the TS 31.111 names), each byte is a vertical list of its bits, placed in fixed column groups (bytes 1-12 in 2 columns, 13-16 in 4, 17-18 in 2, 19-21 in 3, 22-25 in 2, 26-28 in 3, 29-30 in 2, later bytes one per row); toggling a bit updates the hex and editing the hex re-renders the form — the hex field is authoritative and unknown bytes/bits are preserved. Apply sends the new value to the server (and on to the card), resetting the STK session like Rescue; the change is in-memory only (the --terminal-profile CLI value is the startup default).

            -

            6.5 STATUS polling

            +

            8.5 STATUS polling

            A Send STATUS button issues a manual STATUS (F2). A Polling toggle enables background polling: after a configurable idle interval (server CLI --poll-interval, 1–255 s, default 30 s, 0 disables polling) the server sends STATUS and handles any pending proactive command. Polling stops and card state resets if the card is removed.

            -

            6.6 TR Config — PROVIDE LOCAL INFORMATION response data

            +

            8.6 TR Config — PROVIDE LOCAL INFORMATION response data

            Editable hex values for all 22 PLI qualifiers (TS 102 223 §8.6 + TS 131 111). Ten qualifiers have inline decode/encode forms:

            • 00 Location Info (MCC, MNC, LAC/TAC, Cell ID)
            • @@ -450,10 +475,10 @@
            -

            7. Server installation

            +

            9. Server installation

            Live card operations (Card reader tab, Phone simulator, OTA delivery) require the local pysim-otaman-server — a small HTTP server bundled with OTAMan that wraps pySim, talks to the reader over PC/SC or serial, and also serves the PWA itself (open http://127.0.0.1:8080).

            -

            7.1 Prerequisites

            +

            9.1 Prerequisites

            • Python 3.8+ with pip
            • Git
            • @@ -461,20 +486,20 @@
            • Windows only — use Python 3.10–3.13 (3.13 recommended): pyscard (the PC/SC driver wrapper) ships precompiled wheels for these versions. On Python 3.9 / 3.14 pip builds pyscard from source, which requires Microsoft C++ Build Tools (“Desktop development with C++”). The SMPP bridge (smpp.twisted3) is intentionally not installed on Windows, so no C++ Build Tools are needed for Python 3.10–3.13.
            -

            7.2 Quick start — Linux / macOS

            +

            9.2 Quick start — Linux / macOS

            git clone https://github.com/anttro/otaman.git
             cd otaman
             chmod +x setup.sh start.sh
             ./setup.sh          # creates .venv, installs pysim + server (run once)
             ./start.sh          # starts the server (serves PWA + API, auto-detects reader)
            -

            7.3 Quick start — Windows

            +

            9.3 Quick start — Windows

            git clone https://github.com/anttro/otaman.git
             cd otaman
             setup.bat           # creates .venv, installs pysim + server (run once)
             start.bat           # starts the server (serves PWA + API)
            -

            7.4 Helper scripts

            +

            9.4 Helper scripts

            @@ -483,7 +508,7 @@ start.bat # starts the server (serves PWA + API)
            ScriptPurpose
            -

            7.5 Reader auto-detection

            +

            9.5 Reader auto-detection

            • PC/SC (Linux)start.sh passes -p 0 when the pcscd daemon is running
            • PC/SC (Windows)start.bat always uses -p 0 (PC/SC is built into Windows)
            • @@ -492,7 +517,7 @@ start.bat # starts the server (serves PWA + API)

            If no card is present, the Card reader tab shows “No card detected”. Insert the card and click Equip card to initialize it.

            -

            7.6 Manual installation

            +

            9.6 Manual installation

            # Create and activate a venv
             python3 -m venv .venv
             source .venv/bin/activate   # Linux/macOS
            @@ -511,7 +536,7 @@ pysim-otaman-server --http-port 8080
            -

            8. Version compatibility

            +

            10. Version compatibility

            diff --git a/frontend/index.html b/frontend/index.html index 205af79..abece5e 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -7792,6 +7792,7 @@ function scp81SwitchSubtab(name) { document.getElementById('scp81-sub-scripts').classList.toggle('hidden', name !== 'scripts'); if (name === 'scripts') { scriptsRender(); scriptsRebuildSelect(); } else { scp81ModeChanged(); scp81StatusRefresh(); } + setHelpAnchor(name === 'scripts' ? 'scp81-scripts' : 'scp81-listener'); } function scp81Msg(text, cls) { @@ -8449,6 +8450,8 @@ function scp81Enter() { scriptsRender(); scp81StatusRefresh(); scp81LogRefresh(); + setHelpAnchor(document.getElementById('scp81-sub-scripts').classList.contains('hidden') + ? 'scp81-listener' : 'scp81-scripts'); if (_scp81Timer) clearInterval(_scp81Timer); _scp81Timer = setInterval(() => { if (document.getElementById('tab-scp81').classList.contains('hidden')) return; diff --git a/frontend/sw.js b/frontend/sw.js index 7eea6ba..9256061 100644 --- a/frontend/sw.js +++ b/frontend/sw.js @@ -1,4 +1,4 @@ -const CACHE = 'otaman-v177'; +const CACHE = 'otaman-v178'; const URLS = [ 'index.html', 'help.html', diff --git a/frontend/tests/html.test.js b/frontend/tests/html.test.js index 0d145f8..80fe4c1 100644 --- a/frontend/tests/html.test.js +++ b/frontend/tests/html.test.js @@ -146,3 +146,25 @@ test('profile list has a Profile from snapshot button', () => { assert.ok(html.includes('function profilerScanFromSnapshot(si)')); assert.ok(html.includes('function profilerBuildFileRuleFromSnapshot(')); }); + +test('every help anchor used by the UI exists in help.html', () => { + const help = fs.readFileSync(path.join(__dirname, '..', 'help.html'), 'utf8'); + const ids = new Set([...help.matchAll(/id="([^"]+)"/g)].map(m => m[1])); + const anchors = new Set(); + // static maps in `xHelpAnchor = {...}` and inline `setHelpAnchor({...})` + for (const re of [/HelpAnchor\s*=\s*\{([^}]*)\}/g, /setHelpAnchor\s*\(\s*\{([^}]*)\}/g]) { + for (const m of html.matchAll(re)) { + for (const v of m[1].matchAll(/'([a-z0-9-]+)'/g)) anchors.add(v[1]); + } + } + for (const m of html.matchAll(/setHelpAnchor\('([^']+)'\)/g)) anchors.add(m[1]); + for (const m of html.matchAll(/HelpAnchor\s*=[^;]*\|\|\s*'([a-z0-9-]+)'/g)) anchors.add(m[1]); + for (const m of html.matchAll(/setHelpAnchor\s*\([^()]*\|\|\s*'([a-z0-9-]+)'/g)) anchors.add(m[1]); + assert.ok(anchors.size >= 15, 'expected at least 15 help anchors, got ' + anchors.size); + const missing = [...anchors].filter(a => !ids.has(a)); + assert.deepStrictEqual(missing, [], 'help.html lacks sections for: ' + missing.join(', ')); + // the SCP81 tab wires its own anchors and the targets exist + assert.ok(ids.has('scp81') && ids.has('scp81-listener') && ids.has('scp81-scripts')); + assert.ok(html.includes("'scp81-listener' : 'scp81-scripts'")); + assert.ok(html.includes("? 'scp81-scripts' : 'scp81-listener'")); +});
            PWA (OTAMan)ServerStatus