fix: decode the Response Scripting template and the compact listings (v3.6.5)
Explore still missed the F0414C46416101 package on a card whose responses wrap the R-APDU in the TS 102 226 5.2.2 Response Scripting template (`AB <len> 80 <count> 23 <len> <R-APDU>`): `_decode_por` parsed that as a compact response, so the frontend got `last_status_word` 81d0/7680 and data starting `80 01 01 23 ...` instead of the listing. - server: `_parse_response_scripting()` (AB definite / AF 80 ... 00 00 indefinite) extracts the executed-command count and the last R-APDU's SW and data; `_decode_por` exposes it as `response_type: scripting` in the same `decoded` shape as compact, so the RAM explore paging and the RAM install `por_sw` see the real 9000/6310. - frontend: the compact listing walk is deterministic on the AID length (`len AID life ver`; P1=10 adds `module_count (len module_AID)*`). `_parseRawAppEntry` no longer guesses `rawLen-1` for >8-byte AIDs (16-byte A113 applet AIDs were truncated), and `_parseRawElfEntry` no longer scans for `0x10` (a length/AID byte equal to 0x10 derailed the walk: a live page parsed to 1 entry with no F0414C46416101). - tests: exact trace fixtures - the ELF page lists F0414C46416101 (11 entries), the P1=10 page attaches its F0414C4641610101 module, the app page keeps the 16-byte A113 AIDs; Python covers the scripting template (definite/indefinite) against the live `AB 12` ISD and listing vectors. 610 frontend / 495 Python green; version 3.6.5; sw simple-v278.
This commit is contained in:
@@ -23,6 +23,7 @@ function extractFunc(src, name) {
|
||||
|
||||
// Extract chain builder functions and dependencies
|
||||
const FNS = ['berLenStr', 'buildApdu', 'escHtml', 'esc', 'chainInit', 'chainRamBuildRowHex', 'ramFmtLifecycle', 'ramFmtPrivileges', 'ramRenderExploreHtml', 'ramStepLine', 'ramGetStatusApdu',
|
||||
'_parseRawElfEntry', '_parseRawAppEntry', 'ramParseElfStatus', 'ramParseAppStatus', 'parseTLV', '_parseE3Entry',
|
||||
'ramCardIdxAfterRemove', 'ramClearResults', 'ramHideProgress', 'ramOpChanged', 'ramRender', 'ramApplyCard', 'ramExecute',
|
||||
'jcAidNorm', 'jcAidName', 'jcAidSuffix', 'jcAidHtml'];
|
||||
let code = '';
|
||||
@@ -379,3 +380,37 @@ test('ramCardIdxAfterRemove keeps the remembered index aligned', () => {
|
||||
assert.strictEqual(ramCardIdxAfterRemove(0, 2), 0);
|
||||
assert.strictEqual(ramCardIdxAfterRemove(null, 1), null);
|
||||
});
|
||||
|
||||
test('ramParseElfStatus lists the compact ELF and module listings (F0414C46416101)', () => {
|
||||
// Exact bytes from a live RAM Explore: the P1=20 ELF page and the P1=10
|
||||
// (ELF+modules) page. The old 0x10-scan walk dropped everything after the
|
||||
// first entry; the deterministic AID walk lists them all.
|
||||
const elfPage = '10A0000000090005FFFFFFFF8911000000010010A0000000871005FFFFFFFF8913100000010010A0000000871005FFFFFFFF8914100000010010A0000000090005FFFFFFFF8912000000010010A0000000871005FFFFFFFF8913200000010010A0000000090005FFFFFFFF8913000000010010A0000000090005FFFFFFFF8911010000010010D2760001180002FF49100A89AA060F00010010A1130001180001FFFFFFFF89A1003900010010A1130001180002FFF7100E8904000200010007F0414C464161010100';
|
||||
const elfs = ramParseElfStatus(elfPage);
|
||||
const f041 = elfs.find(r => r.aid === 'F0414C46416101');
|
||||
assert.ok(f041, JSON.stringify(elfs.map(r => r.aid)));
|
||||
assert.strictEqual(f041.lifecycle, '01');
|
||||
assert.ok(elfs.some(r => r.aid === 'A1130001180002FFF7100E8904000200'), 'A113 ELF missing');
|
||||
assert.ok(elfs.some(r => r.aid === 'A0000000090005FFFFFFFF8912000000'), 'uicc.toolkit ELF missing');
|
||||
|
||||
const modulesPage = '10A1130001180001FFFFFFFF89A100390001000110A1130001180001FFFFFFFF89A100390810A1130001180002FFF7100E890400020001000210A1130001180002FFF7100E890400020810A1130001180002FFF7100E89494D450807F0414C4641610101000108F0414C4641610101';
|
||||
const mods = ramParseElfStatus(modulesPage, true);
|
||||
const f041Row = mods.find(r => r.aid === 'F0414C46416101');
|
||||
assert.ok(f041Row, JSON.stringify(mods.map(r => r.aid)));
|
||||
assert.deepStrictEqual(f041Row.moduleAids, ['F0414C4641610101']);
|
||||
});
|
||||
|
||||
test('ramParseAppStatus keeps 16-byte AIDs (no rawLen-1 truncation)', () => {
|
||||
const page = '08D276000005AA3F010704'
|
||||
+ '0FD276000005AA060200000000B000000700'
|
||||
+ '0FD276000005AA060200000000B00001070010A1130001180001FFFFFFFF89A10039080700'
|
||||
+ '10A1130001180002FFF7100E8904000208070010A1130001180002FFF7100E89494D45080700';
|
||||
const apps = ramParseAppStatus(page);
|
||||
assert.deepStrictEqual(apps.map(r => r.aid), [
|
||||
'D276000005AA3F01', 'D276000005AA060200000000B00000',
|
||||
'D276000005AA060200000000B00001',
|
||||
'A1130001180001FFFFFFFF89A1003908', 'A1130001180002FFF7100E8904000208',
|
||||
'A1130001180002FFF7100E89494D4508',
|
||||
]);
|
||||
assert.strictEqual(apps[3].lifecycle, '07');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user