fix: always emit the mandatory C9 in the install parameters (v3.6.20)

The v3.6.17 prefix built `C9` only when its field was filled, so filling the
C7/C8 quotas with an empty C9 produced `EF…`-only Install Parameters - and
GP Table 11-49 makes C9 mandatory, so the card rejected the data field with
6A80 (decrypted live packet: params started `EF08C7020000C8020000EA25…`).

- `ramParamsPrefix` always emits the C9 TLV (empty -> `C900`, like the
  reference tools); the vendor form becomes `C900 EF08 C7020000 C8020000
  EA…`.
- the raw "Install parameters (hex)" field is relabelled "Extra install
  parameters (hex)" - it appends extra TLVs after the generated prefix.
- tests updated (empty prefix -> `C900`, quotas-only ->
  `C900EF08C7020000C8020000`).

650 frontend / 499 Python green; version 3.6.20; sw simple-v293.
This commit is contained in:
2026-09-28 08:29:29 +03:00
parent 31162efc8c
commit 2d268f024b
5 changed files with 18 additions and 13 deletions
+10 -7
View File
@@ -857,8 +857,8 @@
</div>
</div>
</div>
<label class="block mb-1 mt-2 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Install parameters (hex, optional)">Install parameters (hex, optional)</label>
<input id="ram-install-params-hex" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800" placeholder="C9 TLV">
<label class="block mb-1 mt-2 text-xs font-medium text-gray-500 dark:text-slate-400" data-l10n="Extra install parameters (hex, optional)">Extra install parameters (hex, optional)</label>
<input id="ram-install-params-hex" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800" placeholder="extra TLVs (optional)">
<label class="block mb-1 text-xs font-medium text-gray-500 dark:text-slate-400 mt-2" data-l10n="STK parameters (hex, optional)">STK parameters (hex, optional)</label>
<input id="ram-stk-params" oninput="this.dataset.manual='1'" class="w-full font-mono border border-gray-300 dark:border-slate-600 text-sm rounded px-3 py-1.5 dark:bg-slate-800" placeholder="EA / CA TLV">
<div id="ram-stk-hint" class="hidden text-xs text-red-600 dark:text-red-400 mt-1"></div>
@@ -1711,7 +1711,7 @@
// ===== Version =====
// Single source of truth for the PWA version: shown in the header and used
// by the server version check in pysimConnect().
const SIMPLE_VERSION = '3.6.19';
const SIMPLE_VERSION = '3.6.20';
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
// ===== Tab switching =====
@@ -2748,11 +2748,13 @@ function ramQuotaValue(n) {
// The applet-specific prefix of the install parameters, in the vendor's
// order: `C9 <applet-specific parameters>` + `EF <C7/C8 memory quotas>`.
// The server appends the STK (`EA`/`EF+CA`) part after it.
// The server appends the STK (`EA`/`EF+CA`) part after it. C9 is mandatory
// in the Install Parameters (GP Table 11-49), so an empty field is sent as
// `C9 00` - like the reference tools; a prefix without C9 makes the card
// reject the data field with 6A80 (live 2026-09-28).
function ramParamsPrefix(c9Hex, c7, c8) {
const c9 = (c9Hex || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase();
let out = '';
if (c9) out += 'C9' + berLenStr(c9.length / 2) + c9;
let out = 'C9' + berLenStr(c9.length / 2) + c9;
let ef = '';
if (String(c7 ?? '') !== '' && !isNaN(parseInt(c7, 10))) ef += 'C7' + ramQuotaValue(c7);
if (String(c8 ?? '') !== '' && !isNaN(parseInt(c8, 10))) ef += 'C8' + ramQuotaValue(c8);
@@ -2772,7 +2774,7 @@ function updateInstallParamsHex() {
const el = document.getElementById('ram-install-params-hex');
// The field carries extra raw TLVs; the generated prefix is shown in the
// placeholder so the composed parameters stay visible.
el.placeholder = prefix ? prefix + ' …' : 'C9 TLV';
el.placeholder = prefix ? prefix + ' …' : 'extra TLVs (optional)';
}
// ===== GSM 7-bit alphabet =====
@@ -16813,6 +16815,7 @@ const LANG_RU = {
'Select a card preset with keys first (RAM subtab → Card preset)': 'Сначала выберите пресет карты с ключами (RAM → Пресет карты)',
'Select a .cap file': 'Выберите файл .cap',
'RAM install (CAP file)': 'RAM-установка (файл CAP)',
'Extra install parameters (hex, optional)': 'Дополнительные параметры установки (hex, опционально)',
'Install parameters (hex, optional)': 'Параметры установки (hex, опционально)',
'STK parameters (hex, optional)': 'STK-параметры (hex, опционально)',
'Make selectable': 'Сделать выбираемым',
+1 -1
View File
@@ -1,4 +1,4 @@
const CACHE = 'simple-v292';
const CACHE = 'simple-v293';
const URLS = [
'index.html',
'help.html',
+5 -3
View File
@@ -131,11 +131,13 @@ test('adfAidFromFci extracts the DF name (tag 84) from an FCI', () => {
test('ramParamsPrefix composes C9 + EF (C7/C8) like the vendor scripts', () => {
// The vendor's working install (samples/uicc/applets/STK3):
// C9 22 <config> EF 08 C7 02 0000 C8 02 0000 EA ...
assert.strictEqual(ramParamsPrefix('', '', ''), '');
// C9 is mandatory (GP Table 11-49): an empty field is sent as C9 00 -
// without it the card rejects the data field with 6A80 (live 2026-09-28).
assert.strictEqual(ramParamsPrefix('', '', ''), 'C900');
assert.strictEqual(ramParamsPrefix('082905112000012066', '', ''),
'C909082905112000012066');
assert.strictEqual(ramParamsPrefix('', '0', '0'), 'EF08C7020000C8020000');
assert.strictEqual(ramParamsPrefix('', '32768', ''), 'EF06C70400008000');
assert.strictEqual(ramParamsPrefix('', '0', '0'), 'C900EF08C7020000C8020000');
assert.strictEqual(ramParamsPrefix('', '32768', ''), 'C900EF06C70400008000');
assert.strictEqual(ramParamsPrefix('AA', '', '1234'), 'C901AAEF04C80204D2');
});
+1 -1
View File
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
[project]
name = "pysim-simple-server"
version = "3.6.19"
version = "3.6.20"
description = "HTTP REST server wrapping pysim for the SIMple PWA"
requires-python = ">=3.8"
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
+1 -1
View File
@@ -31,7 +31,7 @@ from osmocom.tlv import BER_TLV_IE
from osmocom.utils import rpad
VERSION = '3.6.19'
VERSION = '3.6.20'
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE