From 1acc030fd4166029d36d465b11193b4592972aef Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 12 Feb 2025 08:32:13 +0100 Subject: [PATCH] rework simaid & rename few vars --- armsrc/Standalone/hf_msdsal.c | 2 +- armsrc/Standalone/hf_reblay.c | 2 +- armsrc/Standalone/hf_tcprst.c | 4 +- armsrc/appmain.c | 21 +++--- armsrc/iso14443a.c | 98 +++++++++++++--------------- armsrc/iso14443a.h | 9 +-- client/src/cmdhf14a.c | 119 ++++++++++++++++++++-------------- include/pm3_cmd.h | 3 +- 8 files changed, 137 insertions(+), 121 deletions(-) diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c index 4ea27b082..711e653a4 100644 --- a/armsrc/Standalone/hf_msdsal.c +++ b/armsrc/Standalone/hf_msdsal.c @@ -445,7 +445,7 @@ void RunMod(void) { // received a RATS request } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { prevCmd = 0; - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; } else { if (g_dbglevel == DBG_DEBUG) { diff --git a/armsrc/Standalone/hf_reblay.c b/armsrc/Standalone/hf_reblay.c index 51a30f64e..1b84eb3f7 100644 --- a/armsrc/Standalone/hf_reblay.c +++ b/armsrc/Standalone/hf_reblay.c @@ -338,7 +338,7 @@ void RunMod() { } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && len == 9) { // Received a SELECT (cascade 1) p_response = &responses[RESP_INDEX_SAKC1]; } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; resp = 1; } else if (receivedCmd[0] == 0xf2 && len == 4) { // ACKed - Time extension DbpString(_YELLOW_("!!") " Reader accepted time extension!"); diff --git a/armsrc/Standalone/hf_tcprst.c b/armsrc/Standalone/hf_tcprst.c index 9b42d0fd0..e6f75bc75 100644 --- a/armsrc/Standalone/hf_tcprst.c +++ b/armsrc/Standalone/hf_tcprst.c @@ -247,7 +247,7 @@ void RunMod(void) { } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2) p_response = &responses[RESP_INDEX_SAKC2]; } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; } else if (receivedCmd[0] == ISO14443A_CMD_PPS) { p_response = &responses[RESP_INDEX_PPS]; } else { @@ -425,7 +425,7 @@ void RunMod(void) { } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && len == 9) { // Received a SELECT (cascade 2) p_response = &responses[RESP_INDEX_SAKC2]; } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; } else if (receivedCmd[0] == ISO14443A_CMD_PPS) { p_response = &responses[RESP_INDEX_PPS]; } else { diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e9c1fc48d..aeff70df2 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1696,20 +1696,21 @@ static void PacketReceived(PacketCommandNG *packet) { uint8_t tagtype; uint16_t flags; uint8_t uid[10]; - uint8_t rats[20]; + uint8_t ats[20]; uint8_t aid[30]; - uint8_t response[100]; - uint8_t apdu[100]; - int aid_len; - int respond_len; - int apdu_len; - bool enumerate; + uint8_t selectaid_response[100]; + uint8_t getdata_response[100]; + uint32_t ats_len; + uint32_t aid_len; + uint32_t selectaid_response_len; + uint32_t getdata_response_len; } PACKED; struct p *payload = (struct p *) packet->data.asBytes; + // ## Simulate iso14443a tag - pass tag type, UID, ATS, AID, responses SimulateIso14443aTagAID(payload->tagtype, payload->flags, payload->uid, - payload->rats, sizeof(payload->rats), payload->aid, payload->response, - payload->apdu, payload->aid_len, payload->respond_len, - payload->apdu_len, payload->enumerate); // ## Simulate iso14443a tag - pass tag type, UID, rats, aid, resp, apdu + payload->ats, payload->ats_len, payload->aid, payload->aid_len, + payload->selectaid_response, payload->selectaid_response_len, + payload->getdata_response, payload->getdata_response_len); break; } case CMD_HF_ISO14443A_ANTIFUZZ: { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 619842c12..41b4aa546 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1108,7 +1108,7 @@ bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_ } bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, - uint8_t *iRATs, size_t irats_len, tag_response_info_t **responses, + uint8_t *ats, size_t ats_len, tag_response_info_t **responses, uint32_t *cuid, uint32_t counters[3], uint8_t tearings[3], uint8_t *pages) { uint8_t sak = 0; // The first response contains the ATQA (note: bytes are transmitted in reverse order). @@ -1130,9 +1130,9 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 // 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 rRATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; - static uint8_t rRATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 }; - uint8_t rRATS_len = 8; +// static uint8_t rATS[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; + static uint8_t rATS[40] = { 0x05, 0x75, 0x80, 0x60, 0x02, 0x00, 0x00, 0x00 }; + uint8_t rATS_len = 8; // GET_VERSION response for EV1/NTAG static uint8_t rVERSION[10] = { 0x00 }; @@ -1184,8 +1184,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, rATQA[0] = 0x44; rATQA[1] = 0x03; sak = 0x20; - memcpy(rRATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8); - rRATS_len = 8; // including CRC + memcpy(rATS, "\x06\x75\x77\x81\x02\x80\x00\x00", 8); + rATS_len = 8; // including CRC break; } case 4: { // ISO/IEC 14443-4 - javacard (JCOP) @@ -1254,8 +1254,8 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, } case 11: { // ISO/IEC 14443-4 - javacard (JCOP) / EMV - memcpy(rRATS, "\x13\x78\x80\x72\x02\x80\x31\x80\x66\xb1\x84\x0c\x01\x6e\x01\x83\x00\x90\x00\x00\x00", 21); - rRATS_len = 21; // including CRC + memcpy(rATS, "\x13\x78\x80\x72\x02\x80\x31\x80\x66\xb1\x84\x0c\x01\x6e\x01\x83\x00\x90\x00\x00\x00", 21); + rATS_len = 21; // including CRC rATQA[0] = 0x04; sak = 0x20; break; @@ -1271,17 +1271,17 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, } } - // copy the iRATs if supplied. - // iRATs is a pointer to 20 byte array - // rRATS is a 40 byte array - if ((flags & FLAG_RATS_IN_DATA) == FLAG_RATS_IN_DATA) { - memcpy(rRATS, iRATs, irats_len); + // copy the ats if supplied. + // 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 - rRATS_len = (iRATs[0] + 2); + 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 (rRATS_len > sizeof(rRATS)) { - if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: iRATS overflow. Max %zu, got %zu", sizeof(rRATS), rRATS_len); + if (rATS_len > sizeof(rATS)) { + if (g_dbglevel >= DBG_ERROR) Dbprintf("[-] ERROR: ATS overflow. Max %zu, got %zu", sizeof(rATS), rATS_len); return false; } } @@ -1379,7 +1379,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, return false; } - AddCrc14A(rRATS, rRATS_len - 2); + AddCrc14A(rATS, rATS_len - 2); AddCrc14A(rPPS, sizeof(rPPS) - 2); @@ -1407,7 +1407,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, { .response = rSAKc1, .response_n = sizeof(rSAKc1) }, // Acknowledge select - cascade 1 { .response = rSAKc2, .response_n = sizeof(rSAKc2) }, // Acknowledge select - cascade 2 { .response = rSAKc3, .response_n = sizeof(rSAKc3) }, // Acknowledge select - cascade 3 - { .response = rRATS, .response_n = sizeof(rRATS) }, // dummy ATS (pseudo-ATR), answer to RATS + { .response = rATS, .response_n = sizeof(rATS) }, // dummy ATS (pseudo-ATR), answer to RATS { .response = rVERSION, .response_n = sizeof(rVERSION) }, // EV1/NTAG GET_VERSION response { .response = rSIGN, .response_n = sizeof(rSIGN) }, // EV1/NTAG READ_SIG response { .response = rPPS, .response_n = sizeof(rPPS) }, // PPS response @@ -1415,7 +1415,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, }; // since rats len is variable now. - responses_init[RESP_INDEX_RATS].response_n = rRATS_len; + responses_init[RESP_INDEX_ATS].response_n = rATS_len; // "precompiled" responses. // These exist for speed reasons. There are no time in the anti collision phase to calculate responses. @@ -1428,7 +1428,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // 85 bytes normally (rats = 8 bytes) // 77 bytes + ratslen, -#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE ( ((77 + rRATS_len) * 8) + 77 + rRATS_len + 12 + 12 + 12) +#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE ( ((77 + rATS_len) * 8) + 77 + rATS_len + 12 + 12 + 12) uint8_t *free_buffer = BigBuf_calloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); // modulation buffer pointer and current buffer free space size @@ -1455,7 +1455,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, // 'hf 14a sim' //----------------------------------------------------------------------------- void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, - uint8_t *iRATs, size_t irats_len) { + uint8_t *ats, size_t ats_len) { #define ATTACK_KEY_COUNT 16 @@ -1497,7 +1497,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_ .modulation_n = 0 }; - if (SimulateIso14443aInit(tagType, flags, data, iRATs, irats_len, &responses, &cuid, counters, tearings, &pages) == false) { + if (SimulateIso14443aInit(tagType, flags, data, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; @@ -1820,7 +1820,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_ EmSend4bit(CARD_NACK_NA); p_response = NULL; } else { - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; } } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1) { // ULC authentication, or Desfire Authentication LogTrace(receivedCmd, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); @@ -3941,9 +3941,10 @@ It can also continue after the AID has been selected, and respond to other reque This was forked from the original function to allow for more flexibility in the future, and to increase the processing speed of the original function. /// */ -void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, - uint8_t *iRATs, size_t irats_len, uint8_t *aid, uint8_t *resp, - uint8_t *apdu, int aidLen, int respondLen, int apduLen, bool enumerate) { +void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, + uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len, + uint8_t *selectaid_response, size_t selectaid_response_len, + uint8_t *getdata_response, size_t getdata_response_len) { tag_response_info_t *responses; uint32_t cuid = 0; uint32_t counters[3] = { 0x00, 0x00, 0x00 }; @@ -3954,6 +3955,12 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t receivedCmd[MAX_FRAME_SIZE] = { 0x00 }; uint8_t receivedCmdPar[MAX_PARITY_SIZE] = { 0x00 }; + // Buffers must be provided by the caller, even if lengths are 0 + // Copy the AID, AID Response, and the GetData APDU response into our variables + if ((aid == NULL) || (selectaid_response == NULL) || (getdata_response == NULL)) { + reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINVARG, NULL, 0); + } + // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); @@ -3970,7 +3977,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, .modulation_n = 0 }; - if (SimulateIso14443aInit(tagType, flags, data, iRATs, irats_len, &responses, &cuid, counters, tearings, &pages) == false) { + if (SimulateIso14443aInit(tagType, flags, uid, ats, ats_len, &responses, &cuid, counters, tearings, &pages) == false) { BigBuf_free_keep_EM(); reply_ng(CMD_HF_MIFARE_SIMULATE, PM3_EINIT, NULL, 0); return; @@ -3990,23 +3997,6 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, set_tracing(true); LED_A_ON(); - // Filters for when this comes through - static uint8_t aidFilter[30] = { 0x00 }; // Default AID Value - static uint8_t aidResponse[100] = { 0x00 }; // Default AID Response - static uint8_t apduCommand [100] = { 0x00 }; // Default APDU GetData Response - - // Copy the AID, AID Response, and the GetData APDU response into our variables - if (aid != 0) { - memcpy(aidFilter, aid, aidLen); - } - if (resp != 0) { - memcpy(aidResponse, resp, respondLen); - } - if (apdu != 0) { - memcpy(apduCommand, apdu, apduLen); - } - - // main loop bool finished = false; bool got_rats = false; @@ -4051,7 +4041,7 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, finished = true; } } else if (receivedCmd[0] == ISO14443A_CMD_RATS && len == 4) { // Received a RATS request - p_response = &responses[RESP_INDEX_RATS]; + p_response = &responses[RESP_INDEX_ATS]; got_rats = true; } else { // clear old dynamic responses @@ -4081,19 +4071,19 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, // xx in this case is len of the AID value in hex // aid len is found as a hex value in receivedCmd[6] (Index Starts at 0) - int aid_len = receivedCmd[5+offset]; + int received_aid_len = receivedCmd[5+offset]; uint8_t *received_aid = &receivedCmd[6+offset]; // aid enumeration flag - if (enumerate == true) { - Dbprintf("Received AID (%d):", aid_len); - Dbhexdump(aid_len, received_aid, false); + if ((flags & FLAG_ENUMERATE_AID) == FLAG_ENUMERATE_AID) { + Dbprintf("Received AID (%d):", received_aid_len); + Dbhexdump(received_aid_len, received_aid, false); } - if (memcmp(aidFilter, received_aid, aid_len) == 0) { // Evaluate the AID sent by the Reader to the AID supplied + if ((received_aid_len == aid_len) && (memcmp(aid, received_aid, aid_len) == 0)) { // Evaluate the AID sent by the Reader to the AID supplied // AID Response will be parsed here - memcpy(dynamic_response_info.response + 1 + offset, aidResponse, respondLen + 1 + offset); - dynamic_response_info.response_n = respondLen + 2; + memcpy(dynamic_response_info.response + 1 + offset, selectaid_response, selectaid_response_len + 1 + offset); + dynamic_response_info.response_n = selectaid_response_len + 2; } else { // Any other SELECT FILE command will return with a Not Found dynamic_response_info.response[1 + offset] = 0x6A; dynamic_response_info.response[2 + offset] = 0x82; @@ -4113,8 +4103,8 @@ void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, case 0xCA: { // GET DATA if (sentCount == 0) { // APDU Command will just be parsed here - memcpy(dynamic_response_info.response + 1 + offset, apduCommand, apduLen + 2); - dynamic_response_info.response_n = respondLen + 1 + offset; + memcpy(dynamic_response_info.response + 1 + offset, getdata_response, getdata_response_len + 2); + dynamic_response_info.response_n = selectaid_response_len + 1 + offset; } else { finished = true; break; diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 24b388252..34a94dbb5 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -105,7 +105,7 @@ typedef enum { RESP_INDEX_SAKC1, RESP_INDEX_SAKC2, RESP_INDEX_SAKC3, - RESP_INDEX_RATS, + RESP_INDEX_ATS, RESP_INDEX_VERSION, RESP_INDEX_SIGNATURE, RESP_INDEX_PPS, @@ -145,9 +145,10 @@ void RAMFUNC SniffIso14443a(uint8_t param); void SimulateIso14443aTag(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t exitAfterNReads, uint8_t *iRATs, size_t irats_len); -void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *data, - uint8_t *iRATs, size_t irats_len, uint8_t *aid, uint8_t *resp, - uint8_t *apdu, int aid_len, int respond_len, int apdu_len, bool enumerate); +void SimulateIso14443aTagAID(uint8_t tagType, uint16_t flags, uint8_t *uid, + uint8_t *ats, size_t ats_len, uint8_t *aid, size_t aid_len, + uint8_t *selectaid_response, size_t selectaid_response_len, + uint8_t *getdata_response, size_t getdata_response_len); bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8_t *iRATs, size_t irats_len, tag_response_info_t **responses, diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index c627f4504..6f9032017 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -3715,58 +3715,61 @@ 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 --response 9000 --apdu 9000 -> AID, Response and APDU\n" - "hf 14a simaid -t 3 --rats 05788172220101 --response 01009000 --apdu 86009000 -> Custom RATS Added\n" - "hf 14a simaid -t 3 --rats 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 05788172220101 --selectaid_response 01009000 --getdata_response 86009000 -> Custom ATS and responses\n" + "hf 14a simaid -t 3 --ats 05788172220101 -x -> Enumerate AID Values\n" ); void *argtable[] = { arg_param_begin, arg_int1("t", "type", "<1-12> ", "Simulation type to use"), arg_str0("u", "uid", "", "<4|7|10> hex bytes UID"), - arg_str0("r", "rats", "", "<0-20> hex bytes RATS"), - arg_str0("a", "aid", "", "<0-100> hex bytes for AID to respond to (Default: A000000000000000000000)"), - arg_str0("e", "response", "", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"), - arg_str0("p", "apdu", "", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"), + arg_str0("r", "ats", "", "<0-20> hex bytes ATS"), + arg_str0("a", "aid", "", "<0-30> hex bytes for AID to respond to (Default: A000000000000000000000)"), + arg_str0("e", "selectaid_response", "", "<0-100> hex bytes for APDU Response to AID Select (Default: 9000)"), + arg_str0("p", "getdata_response", "", "<0-100> hex bytes for APDU Response to Get Data request after AID (Default: 9000)"), arg_lit0("x", "enumerate", "Enumerate all AID values via returning Not Found and print them to console "), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); - int tagtype = arg_get_int_def(ctx, 1, 1); - - bool enumerate = arg_get_lit(ctx, 7); - int uid_len = 0; - int rats_len = 0; + int ats_len = 0; int aid_len = 0; - int respond_len = 0; - int apdu_len = 0; + int selectaid_response_len = 0; + int getdata_response_len = 0; uint8_t uid[10] = {0}; - uint8_t rats[20] = {0}; - uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - uint8_t response[100] = {0x90, 0x00}; - uint8_t apdu[100] = {0x90, 0x00}; + uint8_t ats[20] = {0}; + uint8_t aid[30] = {0xA0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + uint8_t default_aid_len = 11; + uint8_t selectaid_response[100] = {0x90, 0x00}; + uint8_t default_selectaid_response_len = 2; + uint8_t getdata_response[100] = {0x90, 0x00}; + uint8_t default_getdata_response_len = 2; + int tagtype = arg_get_int_def(ctx, 1, 1); CLIGetHexWithReturn(ctx, 2, uid, &uid_len); - CLIGetHexWithReturn(ctx, 3, rats, &rats_len); + CLIGetHexWithReturn(ctx, 3, ats, &ats_len); CLIGetHexWithReturn(ctx, 4, aid, &aid_len); - CLIGetHexWithReturn(ctx, 5, response, &respond_len); - CLIGetHexWithReturn(ctx, 6, apdu, &apdu_len); + CLIGetHexWithReturn(ctx, 5, selectaid_response, &selectaid_response_len); + CLIGetHexWithReturn(ctx, 6, getdata_response, &getdata_response_len); + bool enumerate = arg_get_lit(ctx, 7); + CLIParserFree(ctx); - // default value fill for the AID, response, and apdu + // default value fill for the AID, selectaid_response, and getdata_response if (aid_len == 0) { - aid_len = 11; + aid_len = default_aid_len; } - if (respond_len == 0) { - respond_len = 2; + + if (selectaid_response_len == 0) { + selectaid_response_len = default_selectaid_response_len; } - if (apdu_len == 0) { - apdu_len = 2; + if (getdata_response_len == 0) { + getdata_response_len = default_getdata_response_len; } uint16_t flags = 0; @@ -3776,19 +3779,39 @@ int CmdHF14AAIDSim(const char *Cmd) { FLAG_SET_UID_IN_DATA(flags, uid_len); if (IS_FLAG_UID_IN_EMUL(flags)) { PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID"); - CLIParserFree(ctx); return PM3_EINVARG; } PrintAndLogEx(SUCCESS, "Emulating " _YELLOW_("ISO/IEC 14443 type A tag")" with " _GREEN_("%d byte UID (%s)"), uid_len, sprint_hex(uid, uid_len)); useUIDfromEML = false; } - if (rats_len > 0) { - flags |= FLAG_RATS_IN_DATA; + if (ats_len > sizeof(ats)) { + PrintAndLogEx(ERR, "Provided ATS too long"); + return PM3_EINVARG; } + if (aid_len > sizeof(aid)) { + PrintAndLogEx(ERR, "Provided AID too long"); + return PM3_EINVARG; + } - CLIParserFree(ctx); + if (selectaid_response_len > sizeof(selectaid_response)) { + PrintAndLogEx(ERR, "Provided SelectAID response too long"); + return PM3_EINVARG; + } + + if (getdata_response_len > sizeof(getdata_response)) { + PrintAndLogEx(ERR, "Provided GetData response too long"); + return PM3_EINVARG; + } + + if (ats_len > 0) { + flags |= FLAG_ATS_IN_DATA; + } + + if (enumerate) { + flags |= FLAG_ENUMERATE_AID; + } if (tagtype > 12) { PrintAndLogEx(ERR, "Undefined tag %d", tagtype); @@ -3803,31 +3826,31 @@ int CmdHF14AAIDSim(const char *Cmd) { uint8_t tagtype; uint16_t flags; uint8_t uid[10]; - uint8_t rats[20]; + uint8_t ats[20]; uint8_t aid[30]; - uint8_t response[100]; - uint8_t apdu[100]; - int aid_len; - int respond_len; - int apdu_len; - bool enumerate; + uint8_t selectaid_response[100]; + uint8_t getdata_response[100]; + uint32_t ats_len; + uint32_t aid_len; + uint32_t selectaid_response_len; + uint32_t getdata_response_len; } PACKED payload; payload.tagtype = tagtype; payload.flags = flags; - payload.enumerate = enumerate; // Copy data to payload memcpy(payload.uid, uid, uid_len); - memcpy(payload.rats, rats, rats_len); + memcpy(payload.ats, ats, ats_len); memcpy(payload.aid, aid, aid_len); - memcpy(payload.response, response, respond_len); - memcpy(payload.apdu, apdu, apdu_len); + memcpy(payload.selectaid_response, selectaid_response, selectaid_response_len); + memcpy(payload.getdata_response, getdata_response, getdata_response_len); // copy the lengths data to the payload - memcpy(&payload.aid_len, &aid_len, sizeof(aid_len)); - memcpy(&payload.respond_len, &respond_len, sizeof(respond_len)); - memcpy(&payload.apdu_len, &apdu_len, sizeof(apdu_len)); + payload.ats_len = ats_len; + payload.aid_len = aid_len; + payload.selectaid_response_len = selectaid_response_len; + payload.getdata_response_len = getdata_response_len; clearCommandBuffer(); SendCommandNG(CMD_HF_ISO14443A_SIM_AID, (uint8_t *)&payload, sizeof(payload)); diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index 996b04079..9128dbb90 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -772,7 +772,8 @@ typedef struct { #define FLAG_INTERACTIVE 0x0001 #define FLAG_ATQA_IN_DATA 0x0002 #define FLAG_SAK_IN_DATA 0x0004 -#define FLAG_RATS_IN_DATA 0x0008 +#define FLAG_ATS_IN_DATA 0x0008 +#define FLAG_ENUMERATE_AID 0x0010 // internal constants, use the function macros instead #define FLAG_MASK_UID 0x0030