diff --git a/CHANGELOG.md b/CHANGELOG.md index 71f61eaf3..b768a5cd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff) - Fix serial of FPC. (@ryan) - Fix 'data shiftgraphzero' corrupting end of GraphBuffer (@doegox) - Fix 'hf legic info' - unsegmented card now uses card size to calc remaining length (@iceman) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 15aa93117..9d66997a5 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -34,8 +34,6 @@ #include "protocols.h" #include "apps.h" -uint8_t MifareCardType; - static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { uint8_t sector_trailer[16]; emlGetMem(sector_trailer, blockNo, 1); @@ -151,196 +149,194 @@ static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { } } -static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len) { +static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len, uint8_t **rats, uint8_t *rats_len) { // 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 + static uint8_t rATQA_1k[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID + static uint8_t rATQA_2k[] = {0x04, 0x00}; // indicate Mifare classic 2k 4Byte UID + static uint8_t rATQA_4k[] = {0x02, 0x00}; // indicate Mifare classic 4k 4Byte UID - static uint8_t rATQA_Mini_4B[] = {0x44, 0x00}; // indicate Mifare classic Mini 4Byte UID - static uint8_t rATQA_Mini_7B[] = {0x44, 0x00}; // indicate Mifare classic Mini 7Byte UID - static uint8_t rATQA_Mini_10B[] = {0x44, 0x00}; // indicate Mifare classic Mini 10Byte UID - - static uint8_t rATQA_1k_4B[] = {0x04, 0x00}; // indicate Mifare classic 1k 4Byte UID - static uint8_t rATQA_1k_7B[] = {0x44, 0x00}; // indicate Mifare classic 1k 7Byte UID - static uint8_t rATQA_1k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID - - static uint8_t rATQA_2k_4B[] = {0x04, 0x00}; // indicate Mifare classic 2k 4Byte UID - static uint8_t rATQA_2k_7B[] = {0x44, 0x00}; // indicate Mifare classic 2k 7Byte UID - static uint8_t rATQA_2k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID - - static uint8_t rATQA_4k_4B[] = {0x02, 0x00}; // indicate Mifare classic 4k 4Byte UID - static uint8_t rATQA_4k_7B[] = {0x42, 0x00}; // indicate Mifare classic 4k 7Byte UID - static uint8_t rATQA_4k_10B[] = {0x42, 0x00}; // indicate Mifare classic 4k 10Byte UID - - static uint8_t rATQA[] = {0x00, 0x00}; - - // SAK + CRC - static uint8_t rSAK_mini[] = {0x09, 0x3f, 0xcc}; // mifare Mini - static uint8_t rSAK_1[] = {0x08, 0xb6, 0xdd}; // mifare 1k - static uint8_t rSAK_2[] = {0x08, 0xb6, 0xdd}; // mifare 2k - static uint8_t rSAK_4[] = {0x18, 0x37, 0xcd}; // mifare 4k + // SAK + static uint8_t rSAK_Mini = 0x09; // mifare Mini + static uint8_t rSAK_1k = 0x08; // mifare 1k + static uint8_t rSAK_2k = 0x08; // mifare 2k with RATS support + static uint8_t rSAK_4k = 0x18; // mifare 4k static uint8_t rUIDBCC1[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 1st cascade level static uint8_t rUIDBCC2[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 2nd cascade level static uint8_t rUIDBCC3[] = {0x00, 0x00, 0x00, 0x00, 0x00}; // UID 3nd cascade level - static uint8_t rSAK1[] = {0x04, 0xda, 0x17}; // Acknowledge but indicate UID is not finished. Used for any MIFARE Classic CL1 with double UID size + static uint8_t rATQA[] = {0x00, 0x00}; // Current ATQA + static uint8_t rSAK[] = {0x00, 0x00, 0x00}; // Current SAK, CRC + static uint8_t rSAKuid[] = {0x04, 0xda, 0x17}; // UID incomplete cascade bit, CRC + // RATS answer for 2K NXP mifare classic (with CRC) + static uint8_t rRATS[] = {0x0c, 0x75, 0x77, 0x80, 0x02, 0xc1, 0x05, 0x2f, 0x2f, 0x01, 0xbc, 0xd6, 0x60, 0xd3}; + *uid_len = 0; + // By default use 1K tag + memcpy(rATQA, rATQA_1k, sizeof(rATQA)); + rSAK[0] = rSAK_1k; + + //by default RATS not supported + *rats_len = 0; + *rats = NULL; + // -- Determine the UID // 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) { - emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. + uint8_t block0[16]; + emlGetMemBt(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: Invalid dump. UID/SAK/ATQA not found"); + 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) { + memcpy(rATQA, rATQA_Mini, sizeof(rATQA)); + rSAK[0] = rSAK_Mini; + Dbprintf("Mifare Mini"); + } + else if ((flags & FLAG_MF_1K) == FLAG_MF_1K) { + memcpy(rATQA, rATQA_1k, sizeof(rATQA)); + rSAK[0] = rSAK_1k; + Dbprintf("Mifare 1K"); + } + else if ((flags & FLAG_MF_2K) == FLAG_MF_2K) { + memcpy(rATQA, rATQA_2k, sizeof(rATQA)); + rSAK[0] = rSAK_2k; + *rats = rRATS; + *rats_len = sizeof(rRATS); + Dbprintf("Mifare 2K with RATS support"); + } + else if ((flags & FLAG_MF_4K) == FLAG_MF_4K) { + memcpy(rATQA, rATQA_4k, sizeof(rATQA)); + rSAK[0] = rSAK_4k; + Dbprintf("Mifare 4K"); + } + + // Prepare UID arrays if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { // get UID from datain memcpy(rUIDBCC1, datain, 4); *uid_len = 4; if (MF_DBGLEVEL >= MF_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 (MF_DBGLEVEL >= MF_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) | 0x00; // 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); *uid_len = 7; if (MF_DBGLEVEL >= MF_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 + rUIDBCC1[0] = MIFARE_SELECT_CT; + // BCC + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + if (MF_DBGLEVEL >= MF_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]); + } + + // 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); *uid_len = 10; if (MF_DBGLEVEL >= MF_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 + rUIDBCC1[0] = MIFARE_SELECT_CT; + rUIDBCC2[0] = MIFARE_SELECT_CT; + // BCC + 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 (MF_DBGLEVEL >= MF_DBG_NONE) { + Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], + rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3], + rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3] + ); + } + + // Correct uid size bits in ATQA + rATQA[0] = (rATQA[0] & 0x3f) | 0x80; // triple size uid + } + else { + Dbprintf("[-] ERROR: UID size not defined"); + return false; } - switch (*uid_len) { + // Calculate actual CRC + AddCrc14A(rSAK, sizeof(rSAK) - 2); - // UID 4B - case 4: - switch (MifareCardType) { - case 0: // Mifare Mini - memcpy(rATQA, rATQA_Mini_4B, sizeof rATQA_Mini_4B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_4B"); - break; - case 1: // Mifare 1K - memcpy(rATQA, rATQA_1k_4B, sizeof rATQA_1k_4B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_4B"); - break; - case 2: // Mifare 2K - memcpy(rATQA, rATQA_2k_4B, sizeof rATQA_2k_4B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_4B"); - break; - case 4: // Mifare 4K - memcpy(rATQA, rATQA_4k_4B, sizeof rATQA_4k_4B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_4B"); - break; - } - - // save CUID - *cuid = bytes_to_num(rUIDBCC1, 4); - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= MF_DBG_NONE) { - Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); - } - break; - - // UID 7B - case 7: - - switch (MifareCardType) { - case 0: // Mifare Mini - memcpy(rATQA, rATQA_Mini_7B, sizeof rATQA_Mini_7B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_7B"); - break; - case 1: // Mifare 1K - memcpy(rATQA, rATQA_1k_7B, sizeof rATQA_1k_7B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_7B"); - break; - case 2: // Mifare 2K - memcpy(rATQA, rATQA_2k_7B, sizeof rATQA_2k_7B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_7B"); - break; - case 4: // Mifare 4K - memcpy(rATQA, rATQA_4k_7B, sizeof rATQA_4k_7B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_4B"); - break; - } - - // save CUID - *cuid = bytes_to_num(rUIDBCC2, 4); - // CascadeTag, CT - rUIDBCC1[0] = MIFARE_SELECT_CT; - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (MF_DBGLEVEL >= MF_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]); - } - break; - - // UID 10B - case 10: - switch (MifareCardType) { - case 0: // Mifare Mini - memcpy(rATQA, rATQA_Mini_10B, sizeof rATQA_Mini_10B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_Mini_10B"); - break; - case 1: // Mifare 1K - memcpy(rATQA, rATQA_1k_10B, sizeof rATQA_1k_10B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_10B"); - break; - case 2: // Mifare 2K - memcpy(rATQA, rATQA_2k_10B, sizeof rATQA_2k_10B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_10B"); - break; - case 4: // Mifare 4K - memcpy(rATQA, rATQA_4k_10B, sizeof rATQA_4k_10B); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_4k_10B"); - break; - } - - // save CUID - *cuid = bytes_to_num(rUIDBCC3, 4); - // CascadeTag, CT - rUIDBCC1[0] = MIFARE_SELECT_CT; - rUIDBCC2[0] = MIFARE_SELECT_CT; - // BCC - 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 (MF_DBGLEVEL >= MF_DBG_NONE) { - Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], - rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3], - rUIDBCC3[0], rUIDBCC3[1], rUIDBCC3[2], rUIDBCC3[3] - ); - } - break; - default: - break; - } - -#define TAG_RESPONSE_COUNT 9 +#define TAG_RESPONSE_COUNT 6 static tag_response_info_t responses_init[TAG_RESPONSE_COUNT] = { { .response = rATQA, .response_n = sizeof(rATQA) }, // Answer to request - respond with card type { .response = rUIDBCC1, .response_n = sizeof(rUIDBCC1) }, // Anticollision cascade1 - respond with first part of uid - { .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid - { .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid - { .response = rSAK_mini, .response_n = sizeof(rSAK_mini) }, // SAK Mifare Mini - { .response = rSAK_1, .response_n = sizeof(rSAK_1) }, // SAK Mifare 1K - { .response = rSAK_2, .response_n = sizeof(rSAK_2) }, // SAK Mifare 2K - { .response = rSAK_4, .response_n = sizeof(rSAK_4) }, // SAK Mifare 4K - { .response = rSAK1, .response_n = sizeof(rSAK1) } // Acknowledge select - Need another cascades + { .response = rUIDBCC2, .response_n = sizeof(rUIDBCC2) }, // Anticollision cascade2 - respond with 2nd part of uid + { .response = rUIDBCC3, .response_n = sizeof(rUIDBCC3) }, // Anticollision cascade3 - respond with 3th part of uid + { .response = rSAK, .response_n = sizeof(rSAK) }, // + { .response = rSAKuid, .response_n = sizeof(rSAKuid) } // }; // Prepare ("precompile") the responses of the anticollision phase. // There will be not enough time to do this at the moment the reader sends its REQA or SELECT - // There are 9 predefined responses with a total of 32 bytes data to transmit. + // There are 6 predefined responses with a total of 23 bytes data to transmit. // Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) - // 32 * 8 data bits, 32 * 1 parity bits, 9 start bits, 9 stop bits, 9 correction bits -> need 315 bytes buffer -#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 512 + // 23 * 8 data bits, 23 * 1 parity bits, 6 start bits, 6 stop bits, 6 correction bits -> need 225 bytes buffer +#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 225 uint8_t *free_buffer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); // modulation buffer pointer and current buffer free space size @@ -361,11 +357,8 @@ static bool MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * #define UIDBCC1 1 #define UIDBCC2 2 #define UIDBCC3 3 -#define SAK_MINI 4 -#define SAK_1 5 -#define SAK_2 6 -#define SAK_4 7 -#define SAK1 8 +#define SAK 4 +#define SAKuid 5 return true; } @@ -422,6 +415,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t *rats = NULL; + uint8_t rats_len = 0; + uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 @@ -447,27 +443,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t tUart *uart = GetUart(); - if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { - MifareCardType = 0; - Dbprintf("Mifare Mini"); - } - if ((flags & FLAG_MF_1K) == FLAG_MF_1K) { - MifareCardType = 1; - Dbprintf("Mifare 1K"); - } - if ((flags & FLAG_MF_2K) == FLAG_MF_2K) { - MifareCardType = 2; - Dbprintf("Mifare 2K"); - } - if ((flags & FLAG_MF_4K) == FLAG_MF_4K) { - MifareCardType = 4; - Dbprintf("Mifare 4K"); - } - // free eventually allocated BigBuf memory but keep Emulator Memory BigBuf_free_keep_EM(); - if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len) == false) { + if (MifareSimInit(flags, datain, &responses, &cuid, &uid_len, &rats, &rats_len) == false) { BigBuf_free_keep_EM(); return; } @@ -579,34 +558,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Send SAK according UID len switch (uid_len) { case 4: - switch (MifareCardType) { - case 0: // Mifare Mini - EmSendPrecompiledCmd(&responses[SAK_MINI]); - break; - case 1: // Mifare 1K - EmSendPrecompiledCmd(&responses[SAK_1]); - break; - case 2: // Mifare 2K - EmSendPrecompiledCmd(&responses[SAK_2]); - break; - case 4: // Mifare 4K - EmSendPrecompiledCmd(&responses[SAK_4]); - break; - } - + // UID completed + EmSendPrecompiledCmd(&responses[SAK]); LED_B_ON(); cardSTATE = MFEMUL_WORK; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK"); break; case 7: // SAK => Need another select round - EmSendPrecompiledCmd(&responses[SAK1]); + EmSendPrecompiledCmd(&responses[SAKuid]); cardSTATE = MFEMUL_SELECT2; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); break; case 10: // SAK => Need another select round - EmSendPrecompiledCmd(&responses[SAK1]); + EmSendPrecompiledCmd(&responses[SAKuid]); cardSTATE = MFEMUL_SELECT2; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); break; @@ -657,27 +623,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t switch (uid_len) { case 7: if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); - - switch (MifareCardType) { - case 0: // Mifare Mini - EmSendPrecompiledCmd(&responses[SAK_MINI]); - break; - case 1: // Mifare 1K - EmSendPrecompiledCmd(&responses[SAK_1]); - break; - case 2: // Mifare 2K - EmSendPrecompiledCmd(&responses[SAK_2]); - break; - case 4: // Mifare 4K - EmSendPrecompiledCmd(&responses[SAK_4]); - break; - } + // UID completed + EmSendPrecompiledCmd(&responses[SAK]); cardSTATE = MFEMUL_WORK; LED_B_ON(); break; case 10: // SAK => Need another select round - EmSendPrecompiledCmd(&responses[SAK1]); + EmSendPrecompiledCmd(&responses[SAKuid]); cardSTATE = MFEMUL_SELECT3; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3"); default: @@ -714,22 +667,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC3].response, 4) == 0)) { - - switch (MifareCardType) { - case 0: // Mifare Mini - EmSendPrecompiledCmd(&responses[SAK_MINI]); - break; - case 1: // Mifare 1K - EmSendPrecompiledCmd(&responses[SAK_1]); - break; - case 2: // Mifare 2K - EmSendPrecompiledCmd(&responses[SAK_2]); - break; - case 4: // Mifare 4K - EmSendPrecompiledCmd(&responses[SAK_4]); - break; - } - + // UID completed + EmSendPrecompiledCmd(&responses[SAK]); cardSTATE = MFEMUL_WORK; LED_B_ON(); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { @@ -1003,9 +942,41 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } // case MFEMUL_WORK => CMD RATS - if (receivedCmd_dec[0] == ISO14443A_CMD_RATS) { - EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); + if (receivedCmd_len == 4 && receivedCmd_dec[0] == ISO14443A_CMD_RATS && receivedCmd_dec[1] == 0x80) { + if (rats && rats_len) { + if (encrypted_data) { + memcpy(response, rats, rats_len); + mf_crypto1_encrypt(pcs, response, rats_len, response_par); + EmSendCmdPar(response, rats_len, response_par); + } + else + EmSendCmd(rats, rats_len); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => ACK"); + } + else { + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); + } + break; + } + + // case MFEMUL_WORK => ISO14443A_CMD_NXP_DESELECT + if (receivedCmd_len == 3 && receivedCmd_dec[0] == ISO14443A_CMD_NXP_DESELECT) { + if (rats && rats_len) { + // response back NXP_DESELECT + if (encrypted_data) { + memcpy(response, receivedCmd_dec, receivedCmd_len); + mf_crypto1_encrypt(pcs, response, receivedCmd_len, response_par); + EmSendCmdPar(response, receivedCmd_len, response_par); + } + else + EmSendCmd(receivedCmd_dec, receivedCmd_len); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => ACK"); + } + else { + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV NXP DESELECT => NACK"); + } break; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 0e91c784e..3d8ad1957 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2140,7 +2140,7 @@ static int CmdHF14AMf1kSim(const char *Cmd) { uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t exitAfterNReads = 0; - uint16_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA); + uint16_t flags = 0; int uidlen = 0; uint8_t cmdp = 0; bool errors = false, verbose = false, setEmulatorMem = false; @@ -2191,13 +2191,13 @@ static int CmdHF14AMf1kSim(const char *Cmd) { param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen); switch (uidlen) { case 20: - flags = FLAG_10B_UID_IN_DATA; + flags |= FLAG_10B_UID_IN_DATA; break; case 14: - flags = FLAG_7B_UID_IN_DATA; + flags |= FLAG_7B_UID_IN_DATA; break; case 8: - flags = FLAG_4B_UID_IN_DATA; + flags |= FLAG_4B_UID_IN_DATA; break; default: return usage_hf14_mf1ksim(); @@ -2221,6 +2221,10 @@ static int CmdHF14AMf1kSim(const char *Cmd) { //Validations if (errors) return usage_hf14_mf1ksim(); + // 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; + PrintAndLogEx(NORMAL, " uid:%s, numreads:%d, flags:%d (0x%02x) " , (uidlen == 0) ? "N/A" : sprint_hex(uid, uidlen >> 1) , exitAfterNReads diff --git a/common/protocols.h b/common/protocols.h index f85ebb49b..cef339dc4 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -151,6 +151,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO14443A_CMD_WRITEBLOCK 0xA0 #define ISO14443A_CMD_HALT 0x50 #define ISO14443A_CMD_RATS 0xE0 +#define ISO14443A_CMD_NXP_DESELECT 0xC2 #define MIFARE_SELECT_CT 0x88 #define MIFARE_AUTH_KEYA 0x60 @@ -167,7 +168,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define MIFARE_EV1_SETMODE 0x43 #define MIFARE_ULC_WRITE 0xA2 -#define MIFARE_ULC_COMP_WRITE 0xA0 +#define MIFARE_ULC_COMP_WRITE 0xA0 #define MIFARE_ULC_AUTH_1 0x1A #define MIFARE_ULC_AUTH_2 0xAF