The DESFire simulation could only be reached over the air. A conformance
suite that has recorded a genuine card's session needs to replay it byte
for byte, which takes two things the simulation did not have: a way in
over USB, and control of the card's random draws.
CMD_HF_DESFIRE_SIM_TEST carries one operation per packet into the same
state machine the RF loop drives: BEGIN, SCAN, APDU, RANDOM, FIELDOFF,
STATE, END. SCAN runs the RF-reset path (init, reset, random id, FSD) and
APDU goes through desfire_sim_apdu(), so native and ISO 7816 wrapped
commands answer exactly as they do on air. No FPGA involvement.
Randomness goes through a small host-fed byte queue: RndB and the random
id draw from it first and fall back to the existing fixed value or tick
counter when it is short, raising a sticky underflow flag. With nothing
queued the RF simulation is byte-identical to before; SimulateDesfireTag()
clears the queue so a host session cannot leak into a reader session.
Co-Authored-By: Claude Fable 5.1 (claude-fable-5-1) <noreply@anthropic.com>
foundKeys was indexed [keytype][keyno] with no AID dimension and was
never reset between applications, so a key number recovered on one AID
was skipped without a single auth attempt on every later AID. On a card
with AES key 00 set on two apps, only the first one was ever reported.
Give every application its own desfire_app_keys_t and hand that to the
checker. Saving to json now uses a new 'mfdes v2' format keyed by AID,
with a loader that round-trips it; v1 is kept for existing files.
Also in the same path:
- one auth error below 7 broke out of the key number loop, abandoning
every remaining key number for the AID. Only an algo mismatch (4, 50,
51) skips the key type now; an invalid key number (3) skips just that
key number, and a transmit error retries after a reselect
- 3TDEA keys were stored 16 bytes wide and written out as 24
- -k with a 24 byte key was rejected by the parser, making the 24 byte
branch unreachable
- DesfireGetAIDList() wrote unbounded into a 78 byte app_ids buffer
Co-Authored-By: Claude Opus 5 (1M context)