mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2024-11-10 09:32:41 +08:00
'hf mf sim' bugs fix, RATS support, etc
This commit is contained in:
parent
436910605b
commit
63f9f11066
4 changed files with 205 additions and 228 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue