From 838e0adfa74f16399377135f2e2bc9e1d735f58f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 19 Oct 2024 19:01:17 +0200 Subject: [PATCH] rework Mifare simulation flags --- armsrc/Standalone/hf_aveful.c | 3 +- armsrc/Standalone/hf_cardhopper.c | 2 +- armsrc/Standalone/hf_colin.c | 29 +------ armsrc/Standalone/hf_craftbyte.c | 9 +-- armsrc/Standalone/hf_mattyrun.c | 14 +--- armsrc/Standalone/hf_mfcsim.c | 4 +- armsrc/Standalone/hf_msdsal.c | 3 +- armsrc/Standalone/hf_reblay.c | 3 +- armsrc/Standalone/hf_tcprst.c | 3 +- armsrc/Standalone/hf_young.c | 5 +- armsrc/iso14443a.c | 16 ++-- armsrc/mifaresim.c | 121 +++++++++++++----------------- armsrc/mifaresim.h | 2 +- client/src/cmdhf14a.c | 56 +++++--------- client/src/cmdhfjooki.c | 3 +- client/src/cmdhfmf.c | 46 ++++-------- include/pm3_cmd.h | 81 ++++++++++++++++---- 17 files changed, 185 insertions(+), 215 deletions(-) diff --git a/armsrc/Standalone/hf_aveful.c b/armsrc/Standalone/hf_aveful.c index 1ca06ddb0..039a22601 100644 --- a/armsrc/Standalone/hf_aveful.c +++ b/armsrc/Standalone/hf_aveful.c @@ -248,7 +248,8 @@ void RunMod(void) { state = STATE_SEARCH; } } else if (state == STATE_EMUL) { - uint16_t flags = FLAG_7B_UID_IN_DATA; + uint16_t flags = 0; + FLAG_SET_UID_IN_DATA(flags, 7); Dbprintf("Starting simulation, press " _GREEN_("pm3 button") " to stop and go back to search state."); SimulateIso14443aTag(7, flags, card.uid, 0, NULL); diff --git a/armsrc/Standalone/hf_cardhopper.c b/armsrc/Standalone/hf_cardhopper.c index 68088a72c..f1aef76e6 100644 --- a/armsrc/Standalone/hf_cardhopper.c +++ b/armsrc/Standalone/hf_cardhopper.c @@ -297,7 +297,7 @@ static void prepare_emulation(uint8_t *tagType, uint16_t *flags, uint8_t *data, } memcpy(data, uidRx.dat, uidRx.len); - *flags = (uidRx.len == 10 ? FLAG_10B_UID_IN_DATA : (uidRx.len == 7 ? FLAG_7B_UID_IN_DATA : FLAG_4B_UID_IN_DATA)); + FLAG_SET_UID_IN_DATA(*flags, uidRx.len); DbpString(_CYAN_("[@]") " UID:"); Dbhexdump(uidRx.len, data, false); Dbprintf(_CYAN_("[@]") " Flags: %hu", *flags); diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 143f97c4f..ad45cda1a 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -717,33 +717,10 @@ readysim: SpinOff(100); LED_C_ON(); - /* uint16_t flags = 0; - switch (colin_p_card.uidlen) { - case 10: - flags = FLAG_10B_UID_IN_DATA; - break; - case 7: - flags = FLAG_7B_UID_IN_DATA; - break; - case 4: - flags = FLAG_4B_UID_IN_DATA; - break; - default: - flags = FLAG_UID_IN_EMUL; - break; - } - // Use UID, SAK, ATQA from EMUL, if uid not defined - if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { - flags |= FLAG_UID_IN_EMUL; - } - flags |= FLAG_MF_1K; - if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { - flags |= FLAG_UID_IN_EMUL; - } - flags = 0x10; - */ - uint16_t flags = FLAG_UID_IN_EMUL; +// FLAG_SET_UID_IN_DATA(flags, colin_p_card.uidlen); + FLAG_SET_UID_IN_EMUL(flags); + FLAG_SET_MF_SIZE(flags, MIFARE_1K_MAX_BYTES); DbprintfEx(FLAG_NEWLINE, "\n\n\n\n\n\n\n\nn\n\nn\n\n\nflags: %d (0x%02x)", flags, flags); cjSetCursLeft(); SpinOff(1000); diff --git a/armsrc/Standalone/hf_craftbyte.c b/armsrc/Standalone/hf_craftbyte.c index 06d032f27..2bc09d9fe 100644 --- a/armsrc/Standalone/hf_craftbyte.c +++ b/armsrc/Standalone/hf_craftbyte.c @@ -79,13 +79,8 @@ void RunMod(void) { } } else if (state == STATE_EMUL) { uint16_t flags = 0; - if (card.uidlen == 4) { - flags |= FLAG_4B_UID_IN_DATA; - } else if (card.uidlen == 7) { - flags |= FLAG_7B_UID_IN_DATA; - } else if (card.uidlen == 10) { - flags |= FLAG_10B_UID_IN_DATA; - } else { + FLAG_SET_UID_IN_DATA(flags, card.uidlen); + if (IS_FLAG_UID_IN_EMUL(flags)) { Dbprintf("Unusual UID length, something is wrong. Try again please."); state = STATE_READ; continue; diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index c899aefe2..ad1e6b863 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -556,19 +556,7 @@ void RunMod(void) { } uint16_t simflags = 0; - switch (mattyrun_card.uidlen) { - case 4: - simflags |= FLAG_4B_UID_IN_DATA; - break; - case 7: - simflags |= FLAG_7B_UID_IN_DATA; - break; - case 10: - simflags |= FLAG_10B_UID_IN_DATA; - break; - default: - break; - } + FLAG_SET_UID_IN_DATA(simflags, mattyrun_card.uidlen); uint16_t atqa = (uint16_t)bytes_to_num(mattyrun_card.atqa, 2); SpinDelay(1000); diff --git a/armsrc/Standalone/hf_mfcsim.c b/armsrc/Standalone/hf_mfcsim.c index bba01d472..667696f86 100644 --- a/armsrc/Standalone/hf_mfcsim.c +++ b/armsrc/Standalone/hf_mfcsim.c @@ -143,7 +143,9 @@ void RunMod(void) { //Start to simulate Dbprintf(_YELLOW_("[Slot: %d] Simulation start, Press button to change next card."), i); - uint16_t simflags = FLAG_UID_IN_EMUL | FLAG_MF_1K; + uint16_t simflags = 0; + FLAG_SET_MF_SIZE(simflags, MIFARE_1K_MAX_BYTES); + FLAG_SET_UID_IN_EMUL(simflags); Mifare1ksim(simflags, 0, NULL, 0, 0); Dbprintf(_YELLOW_("[Slot: %d] Simulation end, Write Back to dump file!"), i); diff --git a/armsrc/Standalone/hf_msdsal.c b/armsrc/Standalone/hf_msdsal.c index 93848b986..c26ef07de 100644 --- a/armsrc/Standalone/hf_msdsal.c +++ b/armsrc/Standalone/hf_msdsal.c @@ -209,7 +209,8 @@ void RunMod(void) { bool chktoken = false; // UID 4 bytes(could be 7 bytes if needed it) - uint8_t flags = FLAG_4B_UID_IN_DATA; + uint8_t flags = 0; + FLAG_SET_UID_IN_DATA(flags, 4); // in case there is a read command received we shouldn't break uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; diff --git a/armsrc/Standalone/hf_reblay.c b/armsrc/Standalone/hf_reblay.c index 0655e1d92..d9f60abcf 100644 --- a/armsrc/Standalone/hf_reblay.c +++ b/armsrc/Standalone/hf_reblay.c @@ -81,7 +81,8 @@ void RunMod() { // UID 4 bytes(could be 7 bytes if needed it) - uint8_t flags = FLAG_4B_UID_IN_DATA; + uint8_t flags = 0; + FLAG_SET_UID_IN_DATA(flags, 4); // in case there is a read command received we shouldn't break uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; diff --git a/armsrc/Standalone/hf_tcprst.c b/armsrc/Standalone/hf_tcprst.c index c07bd1de8..8fb8621b3 100644 --- a/armsrc/Standalone/hf_tcprst.c +++ b/armsrc/Standalone/hf_tcprst.c @@ -110,7 +110,8 @@ void RunMod(void) { #define DYNAMIC_RESPONSE_BUFFER_SIZE 64 #define DYNAMIC_MODULATION_BUFFER_SIZE 512 - uint8_t flags = FLAG_7B_UID_IN_DATA; // ST25TA have 7B UID + uint8_t flags = 0; + FLAG_SET_UID_IN_DATA(flags, 7); // ST25TA have 7B UID uint8_t data[PM3_CMD_DATA_SIZE] = {0x00}; // in case there is a read command received we shouldn't break // to initialize the emulation diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index aefc6da71..a887c2bb5 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -236,7 +236,8 @@ void RunMod(void) { int button_pressed = BUTTON_HELD(1000); if (button_pressed == BUTTON_NO_CLICK) { // No button action, proceed with sim - uint16_t flags = FLAG_4B_UID_IN_DATA; + uint16_t flags = 0 + FLAG_SET_UID_IN_DATA(flags, 4); uint8_t data[PM3_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break memcpy(data, uids[selected].uid, uids[selected].uidlen); @@ -244,7 +245,7 @@ void RunMod(void) { uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); if (uids[selected].uidlen == 7) { - flags = FLAG_7B_UID_IN_DATA; + FLAG_SET_UID_IN_DATA(flags, 7); Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); } else { Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 16ba37c65..0aabc64be 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1263,21 +1263,21 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8 } // if uid not supplied then get from emulator memory - if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL)) { + if ((memcmp(data, "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 10) == 0) || IS_FLAG_UID_IN_EMUL(flags)) { if (tagType == 2 || tagType == 7) { uint16_t start = MFU_DUMP_PREFIX_LENGTH; uint8_t emdata[8]; emlGet(emdata, start, sizeof(emdata)); memcpy(data, emdata, 3); // uid bytes 0-2 memcpy(data + 3, emdata + 4, 4); // uid bytes 3-7 - flags |= FLAG_7B_UID_IN_DATA; + FLAG_SET_UID_IN_DATA(flags, 7); } else { emlGet(data, 0, 4); - flags |= FLAG_4B_UID_IN_DATA; + FLAG_SET_UID_IN_DATA(flags, 4); } } - if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { + if (IS_FLAG_UID_IN_DATA(flags, 4)) { rUIDc1[0] = data[0]; rUIDc1[1] = data[1]; rUIDc1[2] = data[2]; @@ -1296,7 +1296,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8 AddCrc14A(rSAKc1, sizeof(rSAKc1) - 2); *cuid = bytes_to_num(data, 4); - } else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { + } else if (IS_FLAG_UID_IN_DATA(flags, 7)) { rUIDc1[0] = MIFARE_SELECT_CT; // Cascade Tag marker rUIDc1[1] = data[0]; rUIDc1[2] = data[1]; @@ -1319,7 +1319,7 @@ bool SimulateIso14443aInit(uint8_t tagType, uint16_t flags, uint8_t *data, uint8 *cuid = bytes_to_num(data + 3, 4); - } else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) { + } else if (IS_FLAG_UID_IN_DATA(flags, 10)) { rUIDc1[0] = MIFARE_SELECT_CT; // Cascade Tag marker rUIDc1[1] = data[0]; @@ -2560,7 +2560,7 @@ void iso14443a_antifuzz(uint32_t flags) { resp[0] = 0x04; resp[1] = 0x00; - if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { + if (IS_FLAG_UID_IN_DATA(flags, 7)) { resp[0] = 0x44; } @@ -2578,7 +2578,7 @@ void iso14443a_antifuzz(uint32_t flags) { resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3]; colpos = 0; - if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { + if (IS_FLAG_UID_IN_DATA(flags, 7)) { resp[0] = MIFARE_SELECT_CT; colpos = 8; } diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 6fb3287fa..0d9f99287 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -184,8 +184,9 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { } } -static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { +static bool MifareSimInit(uint16_t flags, uint8_t *uid, uint16_t atqa, uint8_t sak, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { + uint8_t uid_tmp[10] = {0}; // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf // ATQA static uint8_t rATQA_Mini[] = {0x04, 0x00}; // indicate Mifare classic Mini 4Byte UID @@ -236,84 +237,79 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ // Can be set from emulator memory or incoming data // Length: 4,7,or 10 bytes - // Get UID, SAK, ATQA from EMUL - if ((flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) { + if (IS_FLAG_UID_IN_EMUL(flags)) { + if (uid == NULL) { + uid = uid_tmp; + } + // Get UID, SAK, ATQA from EMUL uint8_t block0[16]; emlGet(block0, 0, 16); - - // If uid size defined, copy only uid from EMUL to use, backward compatibility for 'hf_colin.c', 'hf_mattyrun.c' - if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) != 0) { - memcpy(datain, block0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. - } else { - // Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA - if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) { - flags |= FLAG_4B_UID_IN_DATA; - memcpy(datain, block0, 4); - rSAK[0] = block0[5]; - memcpy(rATQA, &block0[6], sizeof(rATQA)); - } - // Check for 7 bytes UID: double size uid bits in ATQA - else if ((block0[8] & 0xc0) == 0x40) { - flags |= FLAG_7B_UID_IN_DATA; - memcpy(datain, block0, 7); - rSAK[0] = block0[7]; - memcpy(rATQA, &block0[8], sizeof(rATQA)); - } else { - Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found")); - return false; - } + // Check for 4 bytes uid: bcc corrected and single size uid bits in ATQA + if ((block0[0] ^ block0[1] ^ block0[2] ^ block0[3]) == block0[4] && (block0[6] & 0xc0) == 0) { + FLAG_SET_UID_IN_DATA(flags, 4); + memcpy(uid, block0, 4); + rSAK[0] = block0[5]; + memcpy(rATQA, &block0[6], sizeof(rATQA)); + } + // Check for 7 bytes UID: double size uid bits in ATQA + else if ((block0[8] & 0xc0) == 0x40) { + FLAG_SET_UID_IN_DATA(flags, 7); + memcpy(uid, block0, 7); + rSAK[0] = block0[7]; + memcpy(rATQA, &block0[8], sizeof(rATQA)); + } else { + Dbprintf("ERROR: " _RED_("Invalid dump. UID/SAK/ATQA not found")); + return false; + } + } else { + if (uid == NULL) { + Dbprintf("ERROR: " _RED_("Missing UID")); + return false; } - } // Tune tag type, if defined directly // Otherwise use defined by default or extracted from EMUL - if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { + if (IS_FLAG_MF_SIZE(flags, MIFARE_MINI_MAX_BYTES)) { memcpy(rATQA, rATQA_Mini, sizeof(rATQA)); rSAK[0] = rSAK_Mini; if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare Mini ATQA/SAK"); - } else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) { + } else if (IS_FLAG_MF_SIZE(flags, MIFARE_1K_MAX_BYTES)) { memcpy(rATQA, rATQA_1k, sizeof(rATQA)); rSAK[0] = rSAK_1k; if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 1K ATQA/SAK"); - } else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) { + } else if (IS_FLAG_MF_SIZE(flags, MIFARE_2K_MAX_BYTES)) { memcpy(rATQA, rATQA_2k, sizeof(rATQA)); rSAK[0] = rSAK_2k; *rats = rRATS; *rats_len = sizeof(rRATS); if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 2K ATQA/SAK with RATS support"); - } else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) { + } else if (IS_FLAG_MF_SIZE(flags, MIFARE_4K_MAX_BYTES)) { memcpy(rATQA, rATQA_4k, sizeof(rATQA)); rSAK[0] = rSAK_4k; if (g_dbglevel > DBG_NONE) Dbprintf("Enforcing Mifare 4K ATQA/SAK"); } // Prepare UID arrays - if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain - memcpy(rUIDBCC1, datain, 4); + if (IS_FLAG_UID_IN_DATA(flags, 4)) { + memcpy(rUIDBCC1, uid, 4); *uid_len = 4; - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("MifareSimInit - FLAG_4B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_4B_UID_IN_DATA, flags, rUIDBCC1); - - // save CUID *cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X", flags, rUIDBCC1[4]); if (g_dbglevel > DBG_NONE) { Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); } // Correct uid size bits in ATQA rATQA[0] = (rATQA[0] & 0x3f); // single size uid - - } else if ((flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { - memcpy(&rUIDBCC1[1], datain, 3); - memcpy(rUIDBCC2, datain + 3, 4); + } else if (IS_FLAG_UID_IN_DATA(flags, 7)) { + memcpy(&rUIDBCC1[1], uid, 3); + memcpy(rUIDBCC2, uid + 3, 4); *uid_len = 7; - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("MifareSimInit - FLAG_7B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_7B_UID_IN_DATA, flags, rUIDBCC1); - // save CUID *cuid = bytes_to_num(rUIDBCC2, 4); // CascadeTag, CT @@ -321,6 +317,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X - BCC2: %02X", flags, rUIDBCC1[4], rUIDBCC2[4]); if (g_dbglevel > DBG_NONE) { Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]); @@ -328,15 +326,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ // Correct uid size bits in ATQA rATQA[0] = (rATQA[0] & 0x3f) | 0x40; // double size uid - - } else if ((flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) { - memcpy(&rUIDBCC1[1], datain, 3); - memcpy(&rUIDBCC2[1], datain + 3, 3); - memcpy(rUIDBCC3, datain + 6, 4); + } else if (IS_FLAG_UID_IN_DATA(flags, 10)) { + memcpy(&rUIDBCC1[1], uid, 3); + memcpy(&rUIDBCC2[1], uid + 3, 3); + memcpy(rUIDBCC3, uid + 6, 4); *uid_len = 10; - if (g_dbglevel >= DBG_EXTENDED) - Dbprintf("MifareSimInit - FLAG_10B_UID_IN_DATA => Get UID from datain: %02X - Flag: %02X - UIDBCC1: %02X", FLAG_10B_UID_IN_DATA, flags, rUIDBCC1); - // save CUID *cuid = bytes_to_num(rUIDBCC3, 4); // CascadeTag, CT @@ -346,7 +340,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - + if (g_dbglevel >= DBG_EXTENDED) + Dbprintf("MifareSimInit - Flags: %04X - BCC1: %02X - BCC2: %02X - BCC3: %02X", flags, rUIDBCC1[4], rUIDBCC2[4], rUIDBCC3[4]); if (g_dbglevel > DBG_NONE) { Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], @@ -361,11 +356,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ Dbprintf("ERROR: " _RED_("UID size not defined")); return false; } - if (flags & FLAG_FORCED_ATQA) { + if (flags & FLAG_ATQA_IN_DATA) { rATQA[0] = atqa >> 8; rATQA[1] = atqa & 0xff; } - if (flags & FLAG_FORCED_SAK) { + if (flags & FLAG_SAK_IN_DATA) { rSAK[0] = sak; } if (g_dbglevel > DBG_NONE) { @@ -454,17 +449,11 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, uint16_t atqa, uint8_ /** *MIFARE 1K simulate. * -*@param flags : -* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK -* FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that -* FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that -* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished -* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later -* FLAG_NESTED_AUTH_ATTACK - means that we support nested authentication attack +*@param flags: See pm3_cmd.h for the full definitions *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attempted) */ -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak) { +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t atqa, uint8_t sak) { tag_response_info_t *responses; uint8_t cardSTATE = MFEMUL_NOFIELD; uint8_t uid_len = 0; // 4, 7, 10 @@ -498,12 +487,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 uint8_t rats_len = 0; - // if fct is called with NULL we need to assign some memory since this pointer is passed around - uint8_t datain_tmp[10] = {0}; - if (datain == NULL) { - datain = datain_tmp; - } - //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 // This will be used in the reader-only attack. @@ -522,7 +505,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint1 // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); - if (MifareSimInit(flags, datain, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { + if (MifareSimInit(flags, uid, atqa, sak, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { BigBuf_free_keep_EM(); return; } diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index b22659df6..575ec1d83 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -41,6 +41,6 @@ #define AUTHKEYB 1 #define AUTHKEYNONE 0xff -void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain, uint16_t atqa, uint8_t sak); +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *uid, uint16_t atqa, uint8_t sak); #endif diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index a662710a0..3d8d50626 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -830,20 +830,11 @@ int CmdHF14ASim(const char *Cmd) { bool useUIDfromEML = true; if (uid_len > 0) { - switch (uid_len) { - case 10: - flags |= FLAG_10B_UID_IN_DATA; - break; - case 7: - flags |= FLAG_7B_UID_IN_DATA; - break; - case 4: - flags |= FLAG_4B_UID_IN_DATA; - break; - default: - PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID"); - CLIParserFree(ctx); - return PM3_EINVARG; + 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; @@ -866,7 +857,7 @@ int CmdHF14ASim(const char *Cmd) { } if (useUIDfromEML) { - flags |= FLAG_UID_IN_EMUL; + FLAG_SET_UID_IN_EMUL(flags); } struct { @@ -1660,12 +1651,14 @@ static int CmdHF14AAntiFuzz(const char *Cmd) { struct { uint8_t flag; } PACKED param; - param.flag = FLAG_4B_UID_IN_DATA; - - if (arg_get_lit(ctx, 2)) - param.flag = FLAG_7B_UID_IN_DATA; - if (arg_get_lit(ctx, 3)) - param.flag = FLAG_10B_UID_IN_DATA; + param.flag = 0; + FLAG_SET_UID_IN_DATA(param.flag, 4); + if (arg_get_lit(ctx, 2)) { + FLAG_SET_UID_IN_DATA(param.flag, 7); + } + if (arg_get_lit(ctx, 3)) { + FLAG_SET_UID_IN_DATA(param.flag, 10); + } CLIParserFree(ctx); clearCommandBuffer(); @@ -3725,20 +3718,11 @@ int CmdHF14AAIDSim(const char *Cmd) { bool useUIDfromEML = true; if (uid_len > 0) { - switch (uid_len) { - case 10: - flags |= FLAG_10B_UID_IN_DATA; - break; - case 7: - flags |= FLAG_7B_UID_IN_DATA; - break; - case 4: - flags |= FLAG_4B_UID_IN_DATA; - break; - default: - PrintAndLogEx(ERR, "Please specify a 4, 7, or 10 byte UID"); - CLIParserFree(ctx); - return PM3_EINVARG; + 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; @@ -3757,7 +3741,7 @@ int CmdHF14AAIDSim(const char *Cmd) { } if (useUIDfromEML) { - flags |= FLAG_UID_IN_EMUL; + FLAG_SET_UID_IN_EMUL(flags); } struct { diff --git a/client/src/cmdhfjooki.c b/client/src/cmdhfjooki.c index 4e6cea649..b0126ff77 100644 --- a/client/src/cmdhfjooki.c +++ b/client/src/cmdhfjooki.c @@ -565,7 +565,8 @@ static int CmdHF14AJookiSim(const char *Cmd) { // NTAG, 7 byte UID in eloaded data. payload.tagtype = 7; - payload.flags = FLAG_UID_IN_EMUL; + payload.flags = 0; + FLAG_SET_UID_IN_EMUL(payload.flags); payload.exitAfter = 0; memcpy(payload.uid, uid, sizeof(uid)); diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index 10c4efc00..b275b847f 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -4129,25 +4129,15 @@ static int CmdHF14AMfSim(const char *Cmd) { uint8_t uid[10] = {0}; CLIGetHexWithReturn(ctx, 1, uid, &uidlen); - char uidsize[8] = {0}; + char uidsize[9] = {0}; if (uidlen > 0) { - switch (uidlen) { - case 10: - flags |= FLAG_10B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "10 byte"); - break; - case 7: - flags |= FLAG_7B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "7 byte"); - break; - case 4: - flags |= FLAG_4B_UID_IN_DATA; - snprintf(uidsize, sizeof(uidsize), "4 byte"); - break; - default: - PrintAndLogEx(WARNING, "Invalid parameter for UID"); - CLIParserFree(ctx); - return PM3_EINVARG; + FLAG_SET_UID_IN_DATA(flags, uidlen); + if (IS_FLAG_UID_IN_EMUL(flags)) { + PrintAndLogEx(WARNING, "Invalid parameter for UID"); + CLIParserFree(ctx); + return PM3_EINVARG; + } else { + snprintf(uidsize, sizeof(uidsize), "%i bytes", uidlen); } } @@ -4193,7 +4183,7 @@ static int CmdHF14AMfSim(const char *Cmd) { PrintAndLogEx(WARNING, "Wrong ATQA length"); return PM3_EINVARG; } - flags |= FLAG_FORCED_ATQA; + flags |= FLAG_ATQA_IN_DATA; } if (saklen > 0) { @@ -4201,12 +4191,7 @@ static int CmdHF14AMfSim(const char *Cmd) { PrintAndLogEx(WARNING, "Wrong SAK length"); return PM3_EINVARG; } - flags |= FLAG_FORCED_SAK; - } - - // Use UID, SAK, ATQA from EMUL, if uid not defined - if ((flags & (FLAG_4B_UID_IN_DATA | FLAG_7B_UID_IN_DATA | FLAG_10B_UID_IN_DATA)) == 0) { - flags |= FLAG_UID_IN_EMUL; + flags |= FLAG_SAK_IN_DATA; } size_t k_sectors_cnt = MIFARE_4K_MAXSECTOR; @@ -4218,19 +4203,19 @@ static int CmdHF14AMfSim(const char *Cmd) { } if (m0) { - flags |= FLAG_MF_MINI; + FLAG_SET_MF_SIZE(flags, MIFARE_MINI_MAX_BYTES); snprintf(csize, sizeof(csize), "MINI"); k_sectors_cnt = MIFARE_MINI_MAXSECTOR; } else if (m1) { - flags |= FLAG_MF_1K; + FLAG_SET_MF_SIZE(flags, MIFARE_1K_MAX_BYTES); snprintf(csize, sizeof(csize), "1K"); k_sectors_cnt = MIFARE_1K_MAXSECTOR; } else if (m2) { - flags |= FLAG_MF_2K; + FLAG_SET_MF_SIZE(flags, MIFARE_2K_MAX_BYTES); snprintf(csize, sizeof(csize), "2K with RATS"); k_sectors_cnt = MIFARE_2K_MAXSECTOR; } else if (m4) { - flags |= FLAG_MF_4K; + FLAG_SET_MF_SIZE(flags, MIFARE_4K_MAX_BYTES); snprintf(csize, sizeof(csize), "4K"); k_sectors_cnt = MIFARE_4K_MAXSECTOR; } else { @@ -4262,9 +4247,8 @@ static int CmdHF14AMfSim(const char *Cmd) { , (uidlen == 0) ? "n/a" : sprint_hex(uid, uidlen) ); - PrintAndLogEx(INFO, "Options [ numreads: %d, flags: %d (0x%02x) ]" + PrintAndLogEx(INFO, "Options [ numreads: %d, flags: 0x%04x ]" , exitAfterNReads - , flags , flags); struct { diff --git a/include/pm3_cmd.h b/include/pm3_cmd.h index e3eb64978..1213e7d4d 100644 --- a/include/pm3_cmd.h +++ b/include/pm3_cmd.h @@ -766,21 +766,72 @@ typedef struct { #define CMD_UNKNOWN 0xFFFF //Mifare simulation flags -#define FLAG_INTERACTIVE 0x01 -#define FLAG_4B_UID_IN_DATA 0x02 -#define FLAG_7B_UID_IN_DATA 0x04 -#define FLAG_10B_UID_IN_DATA 0x08 -#define FLAG_UID_IN_EMUL 0x10 -#define FLAG_NR_AR_ATTACK 0x20 -#define FLAG_MF_MINI 0x80 -#define FLAG_MF_1K 0x100 -#define FLAG_MF_2K 0x200 -#define FLAG_MF_4K 0x400 -#define FLAG_FORCED_ATQA 0x800 -#define FLAG_FORCED_SAK 0x1000 -#define FLAG_CVE21_0430 0x2000 -#define FLAG_RATS_IN_DATA 0x4000 -#define FLAG_NESTED_AUTH_ATTACK 0x8000 +// In interactive mode, we are expected to finish the operation with an ACK +#define FLAG_INTERACTIVE 0x0001 +#define FLAG_ATQA_IN_DATA 0x0002 +#define FLAG_SAK_IN_DATA 0x0004 +#define FLAG_RATS_IN_DATA 0x0008 + +// internal constants, use the function macros instead +#define FLAG_MASK_UID 0x0030 +#define FLAG_UID_IN_EMUL 0x0000 +#define FLAG_4B_UID_IN_DATA 0x0010 +#define FLAG_7B_UID_IN_DATA 0x0020 +#define FLAG_10B_UID_IN_DATA 0x0030 +// if there is a UID in the data-section to be used: +// note: if UIDLEN is wrong, we default to FLAG_UID_IN_EMUL +#define FLAG_SET_UID_IN_DATA(flags, len) {\ + flags = (flags & (~FLAG_MASK_UID))|\ + (len == 4 ? FLAG_4B_UID_IN_DATA : \ + (len == 7 ? FLAG_7B_UID_IN_DATA : \ + (len == 10 ? FLAG_10B_UID_IN_DATA : \ + FLAG_UID_IN_EMUL)));\ + } +// else we tell to take UID from block 0: +#define FLAG_SET_UID_IN_EMUL(flags) {flags = (flags & (~FLAG_MASK_UID))|FLAG_UID_IN_EMUL;} +#define IS_FLAG_UID_IN_DATA(flags, len) (\ + (flags & FLAG_MASK_UID) == \ + (len == 4 ? FLAG_4B_UID_IN_DATA : \ + (len == 7 ? FLAG_7B_UID_IN_DATA : \ + (len == 10 ? FLAG_10B_UID_IN_DATA : \ + FLAG_UID_IN_EMUL)))\ + ) +#define IS_FLAG_UID_IN_EMUL(flags) ((flags & FLAG_MASK_UID) == FLAG_UID_IN_EMUL) + +// internal constants, use the function macros instead +#define MIFARE_4K_MAX_BYTES 4096 +#define MIFARE_2K_MAX_BYTES 2048 +#define MIFARE_1K_MAX_BYTES 1024 +#define MIFARE_MINI_MAX_BYTES 320 +#define FLAG_MASK_MF_SIZE 0x00C0 +#define FLAG_MF_MINI 0x0000 +#define FLAG_MF_1K 0x0040 +#define FLAG_MF_2K 0x0080 +#define FLAG_MF_4K 0x00C0 +#define FLAG_SET_MF_SIZE(flags, size) {\ + flags = (flags & (~FLAG_MASK_MF_SIZE))|\ + (size == MIFARE_MINI_MAX_BYTES ? FLAG_MF_MINI : \ + (size == MIFARE_1K_MAX_BYTES ? FLAG_MF_1K : \ + (size == MIFARE_2K_MAX_BYTES ? FLAG_MF_2K : \ + (size == MIFARE_4K_MAX_BYTES ? FLAG_MF_4K : \ + 0))));\ + } +// else we tell to take UID from block 0: +#define IS_FLAG_MF_SIZE(flags, size) (\ + (flags & FLAG_MASK_MF_SIZE) == \ + (size == MIFARE_MINI_MAX_BYTES ? FLAG_MF_MINI : \ + (size == MIFARE_1K_MAX_BYTES ? FLAG_MF_1K : \ + (size == MIFARE_2K_MAX_BYTES ? FLAG_MF_2K : \ + (size == MIFARE_4K_MAX_BYTES ? FLAG_MF_4K : \ + 0))))\ + ) + +#define FLAG_MF_USE_READ_KEYB 0x0100 +#define FLAG_CVE21_0430 0x0200 +// collect NR_AR responses for bruteforcing later +#define FLAG_NR_AR_ATTACK 0x0400 +// support nested authentication attack +#define FLAG_NESTED_AUTH_ATTACK 0x0800 #define MODE_SIM_CSN 0