fix: DELETE APDU is case 3 - no phantom command (v3.6.15)
The Explore delete showed "Failed: por_ok - remote SW 6700" while the delete executed: ramDeleteApdu appended the trailing Le, and this card's SCP80 layer counts a trailing byte as a phantom second command whose SW 6700 masked the real result (count=2, last SW 6700) - the same quirk as INSTALL [for load] before v3.6.8. - ramDeleteApdu and the chain builder's DELETE row emit the case-3 APDU (4F AID TLV, no Le); the SCP81 Delete-AID template follows (it reuses ramDeleteApdu). - tests updated (delete APDU expectations in ram/ram_counter_flow/scripts). 641 frontend / 496 Python green; version 3.6.15; sw simple-v288.
This commit is contained in:
@@ -416,16 +416,17 @@ test('ramParseAppStatus keeps 16-byte AIDs (no rawLen-1 truncation)', () => {
|
||||
assert.strictEqual(apps[3].lifecycle, '07');
|
||||
});
|
||||
|
||||
test('ramDeleteApdu builds the GP DELETE with the 4F AID TLV and Le (F0414C46416101)', () => {
|
||||
test('ramDeleteApdu builds the GP DELETE with the 4F AID TLV (F0414C46416101)', () => {
|
||||
// GP Card Spec v2.3.1 Table 11-20/23: P1=00, P2.b8 = object / object+related,
|
||||
// data = '4F' AID TLV, Le=00. The old handler called an undefined helper
|
||||
// and no APDU was ever sent.
|
||||
// data = '4F' AID TLV, case 3 (no Le - a trailing Le byte becomes a
|
||||
// phantom command on the card's SCP80 layer, live 2026-09-28). The old
|
||||
// handler called an undefined helper and no APDU was ever sent.
|
||||
assert.strictEqual(ramDeleteApdu('F0414C46416101', false),
|
||||
'80E40000094F07F0414C4641610100');
|
||||
'80E40000094F07F0414C46416101');
|
||||
assert.strictEqual(ramDeleteApdu('F0414C46416101', true),
|
||||
'80E40080094F07F0414C4641610100');
|
||||
'80E40080094F07F0414C46416101');
|
||||
assert.strictEqual(ramDeleteApdu('A1130001180002FFF7100E8904000200', true),
|
||||
'80E40080124F10A1130001180002FFF7100E890400020000');
|
||||
'80E40080124F10A1130001180002FFF7100E8904000200');
|
||||
assert.strictEqual(ramDeleteApdu('', false), '');
|
||||
// the dead helper reference must not come back
|
||||
assert.ok(!html.includes('_ber_len('), 'undefined _ber_len() call is back');
|
||||
|
||||
@@ -77,7 +77,7 @@ test('accepted delete persists the consumed counter and drops the record', async
|
||||
decoded: { last_status_word: '9000' } });
|
||||
await ramDeleteFromExplorer('F0414C46416101', false);
|
||||
assert.strictEqual(calls.sent.cntr, '0000000005');
|
||||
assert.strictEqual(calls.sent.apdu, '80E40000094F07F0414C4641610100');
|
||||
assert.strictEqual(calls.sent.apdu, '80E40000094F07F0414C46416101');
|
||||
assert.strictEqual(calls.sent.spi2, '01', 'the computed SPI2 byte must be used');
|
||||
assert.strictEqual(cards[0].cntr, '0000000006',
|
||||
'the preset must carry the counter the card consumed');
|
||||
|
||||
@@ -84,9 +84,9 @@ test('scriptsParseApdus accepts comments and whitespace, rejects bad lines', ()
|
||||
|
||||
test('scp81DeleteApdus builds GP DELETE APDUs per AID', () => {
|
||||
assert.deepStrictEqual(scp81DeleteApdus(['A000000003000000'], '00'),
|
||||
['80E400000A4F08A00000000300000000']);
|
||||
['80E400000A4F08A000000003000000']);
|
||||
assert.deepStrictEqual(scp81DeleteApdus(['A000000003000000', 'A000000100'], '80'),
|
||||
['80E400800A4F08A00000000300000000', '80E40080074F05A00000010000']);
|
||||
['80E400800A4F08A000000003000000', '80E40080074F05A000000100']);
|
||||
assert.deepStrictEqual(scp81DeleteApdus([], '00'), []);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user