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:
+10
-7
@@ -857,8 +857,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</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>
|
<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="C9 TLV">
|
<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>
|
<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">
|
<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>
|
<div id="ram-stk-hint" class="hidden text-xs text-red-600 dark:text-red-400 mt-1"></div>
|
||||||
@@ -1711,7 +1711,7 @@
|
|||||||
// ===== Version =====
|
// ===== Version =====
|
||||||
// Single source of truth for the PWA version: shown in the header and used
|
// Single source of truth for the PWA version: shown in the header and used
|
||||||
// by the server version check in pysimConnect().
|
// 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;
|
document.getElementById('app-version').textContent = 'v' + SIMPLE_VERSION;
|
||||||
|
|
||||||
// ===== Tab switching =====
|
// ===== Tab switching =====
|
||||||
@@ -2748,11 +2748,13 @@ function ramQuotaValue(n) {
|
|||||||
|
|
||||||
// The applet-specific prefix of the install parameters, in the vendor's
|
// The applet-specific prefix of the install parameters, in the vendor's
|
||||||
// order: `C9 <applet-specific parameters>` + `EF <C7/C8 memory quotas>`.
|
// 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) {
|
function ramParamsPrefix(c9Hex, c7, c8) {
|
||||||
const c9 = (c9Hex || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase();
|
const c9 = (c9Hex || '').replace(/[^0-9a-fA-F]/g, '').toUpperCase();
|
||||||
let out = '';
|
let out = 'C9' + berLenStr(c9.length / 2) + c9;
|
||||||
if (c9) out += 'C9' + berLenStr(c9.length / 2) + c9;
|
|
||||||
let ef = '';
|
let ef = '';
|
||||||
if (String(c7 ?? '') !== '' && !isNaN(parseInt(c7, 10))) ef += 'C7' + ramQuotaValue(c7);
|
if (String(c7 ?? '') !== '' && !isNaN(parseInt(c7, 10))) ef += 'C7' + ramQuotaValue(c7);
|
||||||
if (String(c8 ?? '') !== '' && !isNaN(parseInt(c8, 10))) ef += 'C8' + ramQuotaValue(c8);
|
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');
|
const el = document.getElementById('ram-install-params-hex');
|
||||||
// The field carries extra raw TLVs; the generated prefix is shown in the
|
// The field carries extra raw TLVs; the generated prefix is shown in the
|
||||||
// placeholder so the composed parameters stay visible.
|
// placeholder so the composed parameters stay visible.
|
||||||
el.placeholder = prefix ? prefix + ' …' : 'C9 TLV';
|
el.placeholder = prefix ? prefix + ' …' : 'extra TLVs (optional)';
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===== GSM 7-bit alphabet =====
|
// ===== 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 card preset with keys first (RAM subtab → Card preset)': 'Сначала выберите пресет карты с ключами (RAM → Пресет карты)',
|
||||||
'Select a .cap file': 'Выберите файл .cap',
|
'Select a .cap file': 'Выберите файл .cap',
|
||||||
'RAM install (CAP file)': 'RAM-установка (файл CAP)',
|
'RAM install (CAP file)': 'RAM-установка (файл CAP)',
|
||||||
|
'Extra install parameters (hex, optional)': 'Дополнительные параметры установки (hex, опционально)',
|
||||||
'Install parameters (hex, optional)': 'Параметры установки (hex, опционально)',
|
'Install parameters (hex, optional)': 'Параметры установки (hex, опционально)',
|
||||||
'STK parameters (hex, optional)': 'STK-параметры (hex, опционально)',
|
'STK parameters (hex, optional)': 'STK-параметры (hex, опционально)',
|
||||||
'Make selectable': 'Сделать выбираемым',
|
'Make selectable': 'Сделать выбираемым',
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
const CACHE = 'simple-v292';
|
const CACHE = 'simple-v293';
|
||||||
const URLS = [
|
const URLS = [
|
||||||
'index.html',
|
'index.html',
|
||||||
'help.html',
|
'help.html',
|
||||||
|
|||||||
@@ -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', () => {
|
test('ramParamsPrefix composes C9 + EF (C7/C8) like the vendor scripts', () => {
|
||||||
// The vendor's working install (samples/uicc/applets/STK3):
|
// The vendor's working install (samples/uicc/applets/STK3):
|
||||||
// C9 22 <config> EF 08 C7 02 0000 C8 02 0000 EA ...
|
// 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', '', ''),
|
assert.strictEqual(ramParamsPrefix('082905112000012066', '', ''),
|
||||||
'C909082905112000012066');
|
'C909082905112000012066');
|
||||||
assert.strictEqual(ramParamsPrefix('', '0', '0'), 'EF08C7020000C8020000');
|
assert.strictEqual(ramParamsPrefix('', '0', '0'), 'C900EF08C7020000C8020000');
|
||||||
assert.strictEqual(ramParamsPrefix('', '32768', ''), 'EF06C70400008000');
|
assert.strictEqual(ramParamsPrefix('', '32768', ''), 'C900EF06C70400008000');
|
||||||
assert.strictEqual(ramParamsPrefix('AA', '', '1234'), 'C901AAEF04C80204D2');
|
assert.strictEqual(ramParamsPrefix('AA', '', '1234'), 'C901AAEF04C80204D2');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "pysim-simple-server"
|
name = "pysim-simple-server"
|
||||||
version = "3.6.19"
|
version = "3.6.20"
|
||||||
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
description = "HTTP REST server wrapping pysim for the SIMple PWA"
|
||||||
requires-python = ">=3.8"
|
requires-python = ">=3.8"
|
||||||
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
# pysim is a git-only dependency installed explicitly by setup.bat/setup.sh.
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ from osmocom.tlv import BER_TLV_IE
|
|||||||
from osmocom.utils import rpad
|
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
|
MAX_ENVELOPE_SEGMENTS = 5 # max SMS segments for outgoing C-APDU in ENVELOPE
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user