From fcd6de8b7b4fcb27bf16ddf33c0e592de8860369 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 12 Feb 2025 09:06:04 +0100 Subject: [PATCH] 4A emulation: avoid overflow and don't rely on TL --- armsrc/iso14443a.c | 18 ++++++++++-------- client/src/cmdhf14a.c | 12 ++++++------ 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 41b4aa546..ad21732bc 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1131,7 +1131,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) // TC(1) = 0x02: CID supported, NAD not supported // static uint8_t rATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; - static uint8_t rATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 }; + static uint8_t rATS[40] = { 0x06, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 }; uint8_t rATS_len = 8; // GET_VERSION response for EV1/NTAG @@ -1275,15 +1275,17 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // ats is a pointer to 20 byte array // rATS is a 40 byte array if ((flags & FLAG_ATS_IN_DATA) == FLAG_ATS_IN_DATA) { - memcpy(rATS, ats, ats_len); - // rats len is dictated by the first char of the string, add 2 crc bytes - rATS_len = (ats[0] + 2); - // Since its Varible length we can send value > 40 and overflow our array. - // Even if RATS protocol defined as max 40 bytes doesn't mean people try stuff - if (rATS_len > sizeof(rATS)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: ATS overflow. Max %zu, got %zu", sizeof(rATS), rATS_len); + // Even if RATS protocol defined as max 40 bytes doesn't mean people try stuff. Check for overflow before copy + if (ats_len + 2 > sizeof(rATS)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: ATS overflow. Max %zu, got %zu", sizeof(rATS) - 2, ats_len); return false; } + memcpy(rATS, ats, ats_len); + rATS_len = ats_len + 2; + // ATS length (without CRC) is supposed to match its first byte TL + if (ats_len != ats[0]) { + if (g_dbglevel >= DBG_INFO) Dbprintf("[-] WARNING: actual ATS length (%zu) differs from its TL value (%u).", ats_len, ats[0]); + } } // if uid not supplied then get from emulator memory diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index 6f9032017..ac99ea229 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -3715,12 +3715,12 @@ int CmdHF14AAIDSim(const char *Cmd) { CLIParserInit(&ctx, "hf 14a simaid", "Simulate ISO/IEC 14443 type A tag with 4,7 or 10 byte UID, and filter for AID Values\n" "These AID Values can be responded to and include extra APDU commands on GetData after response\n", - "hf 14a simaid -t 3 -> MIFARE Desfire\n" - "hf 14a simaid -t 4 -> ISO/IEC 14443-4\n" - "hf 14a simaid -t 11 -> Javacard (JCOP)\n" - "hf 14a simaid -t 3 --aid a000000000000000000000 --selectaid_response 9000 --getdata_response 9000 -> Custom AID and responses\n" - "hf 14a simaid -t 3 --ats 05788172220101 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses\n" - "hf 14a simaid -t 3 --ats 05788172220101 -x -> Enumerate AID Values\n" + "hf 14a simaid -t 3 -> MIFARE Desfire\n" + "hf 14a simaid -t 4 -> ISO/IEC 14443-4\n" + "hf 14a simaid -t 11 -> Javacard (JCOP)\n" + "hf 14a simaid -t 3 --aid a000000000000000000000 --selectaid_response 9000 --getdata_response 9000 -> Custom AID and responses\n" + "hf 14a simaid -t 3 --ats 0578817222 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses\n" + "hf 14a simaid -t 3 --ats 0578817222 -x -> Enumerate AID Values\n" ); void *argtable[] = {