mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-03-19 11:33:51 +08:00
Merge branch 'vratiskol-hf_mf_sim'
* vratiskol-hf_mf_sim: Astyle Verbose mode ReSync file Add Encrypted data test Mifare 10B UID cardAUTHKEY log Remove FLAG_RANDOM_NONCE Mifare Sim LogTrace Log Level Use Variable Add Variable for MAX_MIFARE_FRAME_SIZE Add Data Block debug Correct flags & test Correct return Revert "Merge branch 'master' into hf_mf_sim" Sync from Upstream Astyle update hf mf sim
This commit is contained in:
commit
05b4b27823
12 changed files with 1458 additions and 662 deletions
|
@ -60,8 +60,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \
|
|||
|
||||
SRC_LF = lfops.c hitag2_crypto.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c
|
||||
SRC_ISO15693 = iso15693.c iso15693tools.c
|
||||
#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c
|
||||
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
|
||||
SRC_ISO14443b = iso14443b.c
|
||||
SRC_FELICA = felica.c
|
||||
SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
|
||||
|
|
|
@ -133,8 +133,8 @@ void ReaderIso14443a(UsbCommand *c);
|
|||
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
// also used in emv
|
||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
|
||||
int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
|
||||
//bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
|
||||
//int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
|
||||
|
||||
// epa.h
|
||||
void EPA_PACE_Collect_Nonce(UsbCommand *c);
|
||||
|
@ -154,7 +154,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags,
|
|||
void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
|
||||
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void Mifare1ksim(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
|
||||
void MifareSetDbgLvl(uint16_t arg0);
|
||||
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
|
||||
|
|
|
@ -16,9 +16,6 @@ static uint32_t iso14a_timeout;
|
|||
|
||||
uint8_t colpos = 0;
|
||||
int rsamples = 0;
|
||||
//int ReqCount;
|
||||
//char CollisionIndicators[10*8];
|
||||
|
||||
uint8_t trigger = 0;
|
||||
// the block number for the ISO14443-4 PCB
|
||||
static uint8_t iso14_pcb_blocknum = 0;
|
||||
|
@ -53,17 +50,6 @@ static uint8_t *free_buffer_pointer;
|
|||
// 1 tick to assign mod_sig_coil
|
||||
#define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1)
|
||||
|
||||
// When the PM acts as tag and is receiving it takes
|
||||
// 2 ticks delay in the RF part (for the first falling edge),
|
||||
// 3 ticks for the A/D conversion,
|
||||
// 8 ticks on average until the start of the SSC transfer,
|
||||
// 8 ticks until the SSC samples the first data
|
||||
// 7*16 ticks to complete the transfer from FPGA to ARM
|
||||
// 8 ticks until the next ssp_clk rising edge
|
||||
// 4*16 ticks until we measure the time
|
||||
// - 8*16 ticks because we measure the time of the previous transfer
|
||||
#define DELAY_AIR2ARM_AS_TAG (2 + 3 + 8 + 8 + 7*16 + 8 + 4*16 - 8*16)
|
||||
|
||||
// The FPGA will report its internal sending delay in
|
||||
uint16_t FpgaSendQueueDelay;
|
||||
// the 5 first bits are the number of bits buffered in mod_sig_buf
|
||||
|
@ -755,12 +741,40 @@ static void Code4bitAnswerAsTag(uint8_t cmd) {
|
|||
ToSendMax++;
|
||||
}
|
||||
|
||||
static uint8_t *LastReaderTraceTime = NULL;
|
||||
|
||||
void EmLogTraceReader(void) {
|
||||
// remember last reader trace start to fix timing info later
|
||||
LastReaderTraceTime = BigBuf_get_addr() + BigBuf_get_traceLen();
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
}
|
||||
|
||||
static void FixLastReaderTraceTime(uint32_t tag_StartTime) {
|
||||
uint32_t reader_EndTime = Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG;
|
||||
uint32_t reader_StartTime = Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG;
|
||||
uint16_t reader_modlen = reader_EndTime - reader_StartTime;
|
||||
uint16_t approx_fdt = tag_StartTime - reader_EndTime;
|
||||
uint16_t exact_fdt = (approx_fdt - 20 + 32) / 64 * 64 + 20;
|
||||
reader_StartTime = tag_StartTime - exact_fdt - reader_modlen;
|
||||
LastReaderTraceTime[0] = (reader_StartTime >> 0) & 0xff;
|
||||
LastReaderTraceTime[1] = (reader_StartTime >> 8) & 0xff;
|
||||
LastReaderTraceTime[2] = (reader_StartTime >> 16) & 0xff;
|
||||
LastReaderTraceTime[3] = (reader_StartTime >> 24) & 0xff;
|
||||
}
|
||||
|
||||
static void EmLogTraceTag(uint8_t *tag_data, uint16_t tag_len, uint8_t *tag_Parity, uint32_t ProxToAirDuration) {
|
||||
uint32_t tag_StartTime = LastTimeProxToAirStart * 16 + DELAY_ARM2AIR_AS_TAG;
|
||||
uint32_t tag_EndTime = (LastTimeProxToAirStart + ProxToAirDuration) * 16 + DELAY_ARM2AIR_AS_TAG;
|
||||
LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false);
|
||||
FixLastReaderTraceTime(tag_StartTime);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Wait for commands from reader
|
||||
// stop when button is pressed
|
||||
// or return TRUE when command is captured
|
||||
//-----------------------------------------------------------------------------
|
||||
int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) {
|
||||
static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) {
|
||||
// Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen
|
||||
// only, since we are receiving, not transmitting).
|
||||
// Signal field is off with the appropriate LED
|
||||
|
@ -780,6 +794,7 @@ int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len)
|
|||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
if (MillerDecoding(b, 0)) {
|
||||
*len = Uart.len;
|
||||
EmLogTraceReader();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -787,7 +802,7 @@ int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len)
|
|||
return false;
|
||||
}
|
||||
|
||||
bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size) {
|
||||
static bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffer_size) {
|
||||
// Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes
|
||||
// This will need the following byte array for a modulation sequence
|
||||
// 144 data bits (18 * 8)
|
||||
|
@ -825,23 +840,21 @@ bool prepare_tag_modulation(tag_response_info_t *response_info, size_t max_buffe
|
|||
// 47 * 8 data bits, 47 * 1 parity bits, 10 start bits, 10 stop bits, 10 correction bits
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 453
|
||||
|
||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info) {
|
||||
// Retrieve and store the current buffer index
|
||||
response_info->modulation = free_buffer_pointer;
|
||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size) {
|
||||
|
||||
// Determine the maximum size we can use from our buffer
|
||||
size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
|
||||
// Retrieve and store the current buffer index
|
||||
response_info->modulation = *buffer;
|
||||
|
||||
// Forward the prepare tag modulation function to the inner function
|
||||
if (prepare_tag_modulation(response_info, max_buffer_size)) {
|
||||
// Update the free buffer offset
|
||||
free_buffer_pointer += ToSendMax;
|
||||
if (prepare_tag_modulation(response_info, *max_buffer_size)) {
|
||||
// Update the free buffer offset and the remaining buffer size
|
||||
*buffer += ToSendMax;
|
||||
*max_buffer_size -= ToSendMax;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Main loop of simulated tag: receive commands from reader, decide what
|
||||
// response to send, and send it.
|
||||
|
@ -1040,12 +1053,13 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) {
|
|||
// allocate buffers:
|
||||
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
|
||||
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
|
||||
free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
|
||||
//free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE);
|
||||
size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE;
|
||||
|
||||
// Prepare the responses of the anticollision phase
|
||||
// there will be not enough time to do this at the moment the reader sends it REQA
|
||||
for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++)
|
||||
prepare_allocated_tag_modulation(&responses[i]);
|
||||
prepare_allocated_tag_modulation(&responses[i], &free_buffer_pointer, &free_buffer_size);
|
||||
|
||||
int len = 0;
|
||||
|
||||
|
@ -1634,7 +1648,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) {
|
|||
analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF];
|
||||
AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START;
|
||||
if (analogCnt >= 32) {
|
||||
if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
if ((MAX_ADC_HF_VOLTAGE_RDV40 * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) {
|
||||
vtime = GetTickCount();
|
||||
if (!timer) timer = vtime;
|
||||
// 50ms no field --> card to idle state
|
||||
|
@ -1650,6 +1664,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) {
|
|||
b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
|
||||
if (MillerDecoding(b, 0)) {
|
||||
*len = Uart.len;
|
||||
EmLogTraceReader();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -1768,11 +1783,30 @@ int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision) {
|
|||
return EmSendCmdParEx(resp, respLen, par, collision);
|
||||
}
|
||||
|
||||
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
|
||||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) {
|
||||
int EmSendPrecompiledCmd(tag_response_info_t *response_info) {
|
||||
int ret = EmSendCmd14443aRaw(response_info->modulation, response_info->modulation_n);
|
||||
|
||||
// do the tracing for the previous reader request and this tag answer:
|
||||
EmLogTraceTag(response_info->response, response_info->response_n,
|
||||
&(response_info->par), response_info->ProxToAirDuration);
|
||||
|
||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) {
|
||||
Dbprintf("response_info->response %02X", response_info->response);
|
||||
Dbprintf("response_info->response_n %02X", response_info->response_n);
|
||||
Dbprintf("response_info->par %02X", &(response_info->par));
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime,
|
||||
uint32_t reader_EndTime, uint8_t *reader_Parity, uint8_t *tag_data,
|
||||
uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) {
|
||||
|
||||
// we cannot exactly measure the end and start of a received command from reader. However we know that the delay from
|
||||
// end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp.
|
||||
// with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated:
|
||||
|
||||
uint16_t reader_modlen = reader_EndTime - reader_StartTime;
|
||||
uint16_t approx_fdt = tag_StartTime - reader_EndTime;
|
||||
uint16_t exact_fdt = (approx_fdt - 20 + 32) / 64 * 64 + 20;
|
||||
|
@ -2962,619 +2996,6 @@ void DetectNACKbug() {
|
|||
set_tracing(false);
|
||||
}
|
||||
|
||||
/**
|
||||
*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 - use 4-byte UID in the data-section
|
||||
* FLAG_7B_UID_IN_DATA - use 7-byte UID in the data-section
|
||||
* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section
|
||||
* FLAG_UID_IN_EMUL - use 4-byte UID from emulator memory
|
||||
* FLAG_NR_AR_ATTACK - collect NR_AR responses for bruteforcing later
|
||||
*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite
|
||||
* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted)
|
||||
*/
|
||||
void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) {
|
||||
|
||||
int cardSTATE = MFEMUL_NOFIELD;
|
||||
int _UID_LEN = 0; // 4, 7, 10
|
||||
int vHf = 0; // in mV
|
||||
int res = 0;
|
||||
uint32_t selTimer = 0;
|
||||
uint32_t authTimer = 0;
|
||||
uint16_t len = 0;
|
||||
uint8_t cardWRBL = 0;
|
||||
uint8_t cardAUTHSC = 0;
|
||||
uint8_t cardAUTHKEY = 0xff; // no authentication
|
||||
uint32_t cuid = 0;
|
||||
uint32_t ans = 0;
|
||||
uint32_t cardINTREG = 0;
|
||||
uint8_t cardINTBLOCK = 0;
|
||||
struct Crypto1State mpcs = {0, 0};
|
||||
struct Crypto1State *pcs;
|
||||
pcs = &mpcs;
|
||||
uint32_t numReads = 0; // Counts numer of times reader read a block
|
||||
uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00};
|
||||
uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00};
|
||||
|
||||
uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k
|
||||
uint8_t sak_4[] = {0x0C, 0x00, 0x00}; // CL1 - 4b uid
|
||||
uint8_t sak_7[] = {0x0C, 0x00, 0x00}; // CL2 - 7b uid
|
||||
uint8_t sak_10[] = {0x0C, 0x00, 0x00}; // CL3 - 10b uid
|
||||
// uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini
|
||||
|
||||
uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||
uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||
uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62};
|
||||
|
||||
// TAG Nonce - Authenticate response
|
||||
uint8_t rAUTH_NT[4];
|
||||
uint32_t nonce = prng_successor(GetTickCount(), 32);
|
||||
num_to_bytes(nonce, 4, rAUTH_NT);
|
||||
|
||||
// uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this?
|
||||
uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00};
|
||||
|
||||
// Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2
|
||||
// This can be used in a reader-only attack.
|
||||
nonces_t ar_nr_nonces[ATTACK_KEY_COUNT];
|
||||
memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces));
|
||||
|
||||
// -- Determine the UID
|
||||
// Can be set from emulator memory or incoming data
|
||||
// Length: 4,7,or 10 bytes
|
||||
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.
|
||||
|
||||
if ((flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) {
|
||||
memcpy(rUIDBCC1, datain, 4);
|
||||
_UID_LEN = 4;
|
||||
} 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;
|
||||
} 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;
|
||||
}
|
||||
|
||||
switch (_UID_LEN) {
|
||||
case 4:
|
||||
sak_4[0] &= 0xFB;
|
||||
// save CUID
|
||||
cuid = bytes_to_num(rUIDBCC1, 4);
|
||||
// BCC
|
||||
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
||||
if (MF_DBGLEVEL >= 2) {
|
||||
Dbprintf("4B UID: %02x%02x%02x%02x",
|
||||
rUIDBCC1[0],
|
||||
rUIDBCC1[1],
|
||||
rUIDBCC1[2],
|
||||
rUIDBCC1[3]
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 7:
|
||||
atqa[0] |= 0x40;
|
||||
sak_7[0] &= 0xFB;
|
||||
// save CUID
|
||||
cuid = bytes_to_num(rUIDBCC2, 4);
|
||||
// CascadeTag, CT
|
||||
rUIDBCC1[0] = 0x88;
|
||||
// BCC
|
||||
rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3];
|
||||
rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3];
|
||||
if (MF_DBGLEVEL >= 2) {
|
||||
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;
|
||||
case 10:
|
||||
atqa[0] |= 0x80;
|
||||
sak_10[0] &= 0xFB;
|
||||
// save CUID
|
||||
cuid = bytes_to_num(rUIDBCC3, 4);
|
||||
// CascadeTag, CT
|
||||
rUIDBCC1[0] = 0x88;
|
||||
rUIDBCC2[0] = 0x88;
|
||||
// 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 >= 2) {
|
||||
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;
|
||||
}
|
||||
// calc some crcs
|
||||
compute_crc(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]);
|
||||
compute_crc(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]);
|
||||
compute_crc(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]);
|
||||
|
||||
// We need to listen to the high-frequency, peak-detected path.
|
||||
iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN);
|
||||
|
||||
// free eventually allocated BigBuf memory but keep Emulator Memory
|
||||
BigBuf_free_keep_EM();
|
||||
clear_trace();
|
||||
set_tracing(true);
|
||||
LED_D_ON();
|
||||
|
||||
bool finished = false;
|
||||
while (!BUTTON_PRESS() && !finished && !usb_poll_validate_length()) {
|
||||
WDT_HIT();
|
||||
|
||||
// find reader field
|
||||
if (cardSTATE == MFEMUL_NOFIELD) {
|
||||
|
||||
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
|
||||
if (vHf > MF_MINFIELDV) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LED_A_ON();
|
||||
}
|
||||
}
|
||||
if (cardSTATE == MFEMUL_NOFIELD) continue;
|
||||
|
||||
// Now, get data
|
||||
res = EmGetCmd(receivedCmd, &len, receivedCmd_par);
|
||||
if (res == 2) { //Field is off!
|
||||
cardSTATE = MFEMUL_NOFIELD;
|
||||
LEDsoff();
|
||||
continue;
|
||||
} else if (res == 1) {
|
||||
break; // return value 1 means button press
|
||||
}
|
||||
|
||||
// REQ or WUP request in ANY state and WUP in HALTED state
|
||||
// this if-statement doesn't match the specification above. (iceman)
|
||||
if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) {
|
||||
selTimer = GetTickCount();
|
||||
EmSendCmd(atqa, sizeof(atqa));
|
||||
cardSTATE = MFEMUL_SELECT1;
|
||||
crypto1_destroy(pcs);
|
||||
cardAUTHKEY = 0xff;
|
||||
nonce = prng_successor(selTimer, 32);
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (cardSTATE) {
|
||||
case MFEMUL_NOFIELD:
|
||||
case MFEMUL_HALTED:
|
||||
case MFEMUL_IDLE: {
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
case MFEMUL_SELECT1: {
|
||||
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received");
|
||||
EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1));
|
||||
break;
|
||||
}
|
||||
// select card
|
||||
if (len == 9 &&
|
||||
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT &&
|
||||
receivedCmd[1] == 0x70 &&
|
||||
memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) {
|
||||
|
||||
// SAK 4b
|
||||
EmSendCmd(sak_4, sizeof(sak_4));
|
||||
switch (_UID_LEN) {
|
||||
case 4:
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
LED_B_ON();
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer);
|
||||
continue;
|
||||
case 7:
|
||||
case 10:
|
||||
cardSTATE = MFEMUL_SELECT2;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
cardSTATE_TO_IDLE();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFEMUL_SELECT2: {
|
||||
if (!len) {
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) {
|
||||
EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2));
|
||||
break;
|
||||
}
|
||||
if (len == 9 &&
|
||||
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 &&
|
||||
receivedCmd[1] == 0x70 &&
|
||||
memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0)) {
|
||||
|
||||
EmSendCmd(sak_7, sizeof(sak_7));
|
||||
switch (_UID_LEN) {
|
||||
case 7:
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
LED_B_ON();
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer);
|
||||
continue;
|
||||
case 10:
|
||||
cardSTATE = MFEMUL_SELECT3;
|
||||
continue;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
cardSTATE_TO_IDLE();
|
||||
break;
|
||||
}
|
||||
case MFEMUL_SELECT3: {
|
||||
if (!len) {
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) {
|
||||
EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3));
|
||||
break;
|
||||
}
|
||||
if (len == 9 &&
|
||||
(receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 &&
|
||||
receivedCmd[1] == 0x70 &&
|
||||
memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0)) {
|
||||
|
||||
EmSendCmd(sak_10, sizeof(sak_10));
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
LED_B_ON();
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer);
|
||||
break;
|
||||
}
|
||||
cardSTATE_TO_IDLE();
|
||||
break;
|
||||
}
|
||||
case MFEMUL_AUTH1: {
|
||||
if (len != 8) {
|
||||
cardSTATE_TO_IDLE();
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
|
||||
uint32_t nr = bytes_to_num(receivedCmd, 4);
|
||||
uint32_t ar = bytes_to_num(&receivedCmd[4], 4);
|
||||
|
||||
// Collect AR/NR per keytype & sector
|
||||
if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) {
|
||||
|
||||
int8_t index = -1;
|
||||
int8_t empty = -1;
|
||||
for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) {
|
||||
// find which index to use
|
||||
if ((cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype))
|
||||
index = i;
|
||||
|
||||
// keep track of empty slots.
|
||||
if (ar_nr_nonces[i].state == EMPTY)
|
||||
empty = i;
|
||||
}
|
||||
// if no empty slots. Choose first and overwrite.
|
||||
if (index == -1) {
|
||||
if (empty == -1) {
|
||||
index = 0;
|
||||
ar_nr_nonces[index].state = EMPTY;
|
||||
} else {
|
||||
index = empty;
|
||||
}
|
||||
}
|
||||
|
||||
switch (ar_nr_nonces[index].state) {
|
||||
case EMPTY: {
|
||||
// first nonce collect
|
||||
ar_nr_nonces[index].cuid = cuid;
|
||||
ar_nr_nonces[index].sector = cardAUTHSC;
|
||||
ar_nr_nonces[index].keytype = cardAUTHKEY;
|
||||
ar_nr_nonces[index].nonce = nonce;
|
||||
ar_nr_nonces[index].nr = nr;
|
||||
ar_nr_nonces[index].ar = ar;
|
||||
ar_nr_nonces[index].state = FIRST;
|
||||
break;
|
||||
}
|
||||
case FIRST : {
|
||||
// second nonce collect
|
||||
ar_nr_nonces[index].nonce2 = nonce;
|
||||
ar_nr_nonces[index].nr2 = nr;
|
||||
ar_nr_nonces[index].ar2 = ar;
|
||||
ar_nr_nonces[index].state = SECOND;
|
||||
|
||||
// send to client
|
||||
cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t));
|
||||
|
||||
ar_nr_nonces[index].state = EMPTY;
|
||||
ar_nr_nonces[index].sector = 0;
|
||||
ar_nr_nonces[index].keytype = 0;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
crypto1_word(pcs, nr, 1);
|
||||
uint32_t cardRr = ar ^ crypto1_word(pcs, 0, 0);
|
||||
|
||||
//test if auth OK
|
||||
if (cardRr != prng_successor(nonce, 64)) {
|
||||
|
||||
if (MF_DBGLEVEL >= 3) {
|
||||
Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]"
|
||||
, cardAUTHSC
|
||||
, (cardAUTHKEY == 0) ? 'A' : 'B'
|
||||
, nr
|
||||
, cardRr
|
||||
, nonce // nt
|
||||
, prng_successor(nonce, 64)
|
||||
);
|
||||
}
|
||||
// Shouldn't we respond anything here?
|
||||
// Right now, we don't nack or anything, which causes the
|
||||
// reader to do a WUPA after a while. /Martin
|
||||
// -- which is the correct response. /piwi
|
||||
cardSTATE_TO_IDLE();
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0);
|
||||
num_to_bytes(ans, 4, rAUTH_AT);
|
||||
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
|
||||
*/
|
||||
|
||||
ans = prng_successor(nonce, 96);
|
||||
num_to_bytes(ans, 4, response);
|
||||
mf_crypto1_encrypt(pcs, response, 4, response_par);
|
||||
EmSendCmdPar(response, 4, response_par);
|
||||
|
||||
LED_C_ON();
|
||||
|
||||
if (MF_DBGLEVEL >= 3) {
|
||||
Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d",
|
||||
cardAUTHSC,
|
||||
cardAUTHKEY == 0 ? 'A' : 'B',
|
||||
GetTickCount() - authTimer
|
||||
);
|
||||
}
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
break;
|
||||
}
|
||||
case MFEMUL_WORK: {
|
||||
if (len == 0) {
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
bool encrypted_data = (cardAUTHKEY != 0xFF) ;
|
||||
|
||||
if (encrypted_data)
|
||||
mf_crypto1_decrypt(pcs, receivedCmd, len);
|
||||
|
||||
if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA ||
|
||||
receivedCmd[0] == MIFARE_AUTH_KEYB)) {
|
||||
|
||||
authTimer = GetTickCount();
|
||||
cardAUTHSC = receivedCmd[1] / 4; // received block -> sector
|
||||
cardAUTHKEY = receivedCmd[0] & 0x1;
|
||||
crypto1_destroy(pcs);
|
||||
|
||||
// load key into crypto
|
||||
crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY));
|
||||
|
||||
if (!encrypted_data) {
|
||||
// first authentication
|
||||
// Update crypto state init (UID ^ NONCE)
|
||||
crypto1_word(pcs, cuid ^ nonce, 0);
|
||||
num_to_bytes(nonce, 4, rAUTH_AT);
|
||||
} else {
|
||||
// nested authentication
|
||||
ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0);
|
||||
num_to_bytes(ans, 4, rAUTH_AT);
|
||||
|
||||
if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B');
|
||||
}
|
||||
|
||||
EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT));
|
||||
cardSTATE = MFEMUL_AUTH1;
|
||||
break;
|
||||
}
|
||||
|
||||
// rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued
|
||||
// BUT... ACK --> NACK
|
||||
if (len == 1 && receivedCmd[0] == CARD_ACK) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
break;
|
||||
}
|
||||
|
||||
// rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK)
|
||||
if (len == 1 && receivedCmd[0] == CARD_NACK_NA) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
|
||||
break;
|
||||
}
|
||||
|
||||
if (len != 4) {
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
|
||||
if (receivedCmd[0] == ISO14443A_CMD_READBLOCK ||
|
||||
receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK ||
|
||||
receivedCmd[0] == MIFARE_CMD_INC ||
|
||||
receivedCmd[0] == MIFARE_CMD_DEC ||
|
||||
receivedCmd[0] == MIFARE_CMD_RESTORE ||
|
||||
receivedCmd[0] == MIFARE_CMD_TRANSFER) {
|
||||
|
||||
if (receivedCmd[1] >= 16 * 4) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
|
||||
break;
|
||||
}
|
||||
|
||||
if (receivedCmd[1] / 4 != cardAUTHSC) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd[0], receivedCmd[1], cardAUTHSC);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// read block
|
||||
if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("Reader reading block %d (0x%02x)", receivedCmd[1], receivedCmd[1]);
|
||||
|
||||
emlGetMem(response, receivedCmd[1], 1);
|
||||
AddCrc14A(response, 16);
|
||||
mf_crypto1_encrypt(pcs, response, 18, response_par);
|
||||
EmSendCmdPar(response, 18, response_par);
|
||||
numReads++;
|
||||
if (exitAfterNReads > 0 && numReads >= exitAfterNReads) {
|
||||
Dbprintf("%d reads done, exiting", numReads);
|
||||
finished = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
// write block
|
||||
if (receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", receivedCmd[1], receivedCmd[1]);
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
|
||||
cardSTATE = MFEMUL_WRITEBL2;
|
||||
cardWRBL = receivedCmd[1];
|
||||
break;
|
||||
}
|
||||
// increment, decrement, restore
|
||||
if (receivedCmd[0] == MIFARE_CMD_INC ||
|
||||
receivedCmd[0] == MIFARE_CMD_DEC ||
|
||||
receivedCmd[0] == MIFARE_CMD_RESTORE) {
|
||||
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
|
||||
|
||||
if (emlCheckValBl(receivedCmd[1])) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking");
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
break;
|
||||
}
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
|
||||
if (receivedCmd[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC;
|
||||
if (receivedCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC;
|
||||
if (receivedCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST;
|
||||
cardWRBL = receivedCmd[1];
|
||||
break;
|
||||
}
|
||||
// transfer
|
||||
if (receivedCmd[0] == MIFARE_CMD_TRANSFER) {
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]);
|
||||
if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1]))
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
else
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
|
||||
break;
|
||||
}
|
||||
// halt
|
||||
if (receivedCmd[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) {
|
||||
LED_B_OFF();
|
||||
LED_C_OFF();
|
||||
cardSTATE = MFEMUL_HALTED;
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer);
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
break;
|
||||
}
|
||||
// RATS
|
||||
if (receivedCmd[0] == ISO14443A_CMD_RATS) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
break;
|
||||
}
|
||||
// command not allowed
|
||||
if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking");
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
break;
|
||||
}
|
||||
case MFEMUL_WRITEBL2: {
|
||||
if (len == 18) {
|
||||
mf_crypto1_decrypt(pcs, receivedCmd, len);
|
||||
emlSetMem(receivedCmd, cardWRBL, 1);
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK));
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
} else {
|
||||
cardSTATE_TO_IDLE();
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MFEMUL_INTREG_INC: {
|
||||
mf_crypto1_decrypt(pcs, receivedCmd, len);
|
||||
memcpy(&ans, receivedCmd, 4);
|
||||
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
cardSTATE_TO_IDLE();
|
||||
break;
|
||||
}
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
cardINTREG = cardINTREG + ans;
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
break;
|
||||
}
|
||||
case MFEMUL_INTREG_DEC: {
|
||||
mf_crypto1_decrypt(pcs, receivedCmd, len);
|
||||
memcpy(&ans, receivedCmd, 4);
|
||||
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
cardSTATE_TO_IDLE();
|
||||
break;
|
||||
}
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
cardINTREG = cardINTREG - ans;
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
break;
|
||||
}
|
||||
case MFEMUL_INTREG_REST: {
|
||||
mf_crypto1_decrypt(pcs, receivedCmd, len);
|
||||
memcpy(&ans, receivedCmd, 4);
|
||||
if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) {
|
||||
EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA));
|
||||
cardSTATE_TO_IDLE();
|
||||
break;
|
||||
}
|
||||
LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true);
|
||||
cardSTATE = MFEMUL_WORK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (MF_DBGLEVEL >= 1)
|
||||
Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
|
||||
|
||||
cmd_send(CMD_ACK, 1, 0, 0, 0, 0);
|
||||
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
|
||||
LEDsoff();
|
||||
set_tracing(false);
|
||||
void AppendCrc14443a(uint8_t *data, int len) {
|
||||
compute_crc(CRC_14443_A, data, len, data + len, data + len + 1);
|
||||
}
|
||||
|
|
|
@ -30,6 +30,17 @@ extern "C" {
|
|||
#include "random.h"
|
||||
#include "mifare.h" // structs
|
||||
|
||||
// When the PM acts as tag and is receiving it takes
|
||||
// 2 ticks delay in the RF part (for the first falling edge),
|
||||
// 3 ticks for the A/D conversion,
|
||||
// 8 ticks on average until the start of the SSC transfer,
|
||||
// 8 ticks until the SSC samples the first data
|
||||
// 7*16 ticks to complete the transfer from FPGA to ARM
|
||||
// 8 ticks until the next ssp_clk rising edge
|
||||
// 4*16 ticks until we measure the time
|
||||
// - 8*16 ticks because we measure the time of the previous transfer
|
||||
#define DELAY_AIR2ARM_AS_TAG (2 + 3 + 8 + 8 + 7*16 + 8 + 4*16 - 8*16)
|
||||
|
||||
typedef struct {
|
||||
enum {
|
||||
DEMOD_UNSYNCD,
|
||||
|
@ -123,6 +134,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uin
|
|||
int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
|
||||
void iso14a_set_trigger(bool enable);
|
||||
|
||||
int EmSendPrecompiledCmd(tag_response_info_t *response_info);
|
||||
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
|
||||
int EmSend4bit(uint8_t resp);
|
||||
int EmSendCmd(uint8_t *resp, uint16_t respLen);
|
||||
|
@ -132,14 +144,18 @@ int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
|
|||
int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision);
|
||||
int EmSendPrecompiledCmd(tag_response_info_t *response_info);
|
||||
|
||||
void EmLogTraceReader(void);
|
||||
|
||||
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size);
|
||||
|
||||
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
|
||||
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
|
||||
|
||||
//bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size);
|
||||
|
||||
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
|
||||
void DetectNACKbug();
|
||||
|
||||
void AppendCrc14443a(uint8_t *data, int len);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
1253
armsrc/mifaresim.c
Normal file
1253
armsrc/mifaresim.c
Normal file
File diff suppressed because it is too large
Load diff
44
armsrc/mifaresim.h
Normal file
44
armsrc/mifaresim.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Merlok - June 2011, 2012
|
||||
// Gerhard de Koning Gans - May 2008
|
||||
// Hagen Fritsch - June 2010
|
||||
//
|
||||
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
|
||||
// at your option, any later version. See the LICENSE.txt file for the text of
|
||||
// the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// Mifare Classic Card Simulation
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef __MIFARESIM_H
|
||||
#define __MIFARESIM_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain);
|
||||
|
||||
#define AC_DATA_READ 0
|
||||
#define AC_DATA_WRITE 1
|
||||
#define AC_DATA_INC 2
|
||||
#define AC_DATA_DEC_TRANS_REST 3
|
||||
#define AC_KEYA_READ 0
|
||||
#define AC_KEYA_WRITE 1
|
||||
#define AC_KEYB_READ 2
|
||||
#define AC_KEYB_WRITE 3
|
||||
#define AC_AC_READ 4
|
||||
#define AC_AC_WRITE 5
|
||||
|
||||
#define AUTHKEYA 0
|
||||
#define AUTHKEYB 1
|
||||
#define AUTHKEYNONE 0xff
|
||||
|
||||
#define TAG_RESPONSE_COUNT 9 // number of precompiled responses
|
||||
|
||||
// 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 7 predefined responses with a total of 18 bytes data to transmit.
|
||||
// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction)
|
||||
// 18 * 8 data bits, 18 * 1 parity bits, 5 start bits, 5 stop bits, 5 correction bits -> need 177 bytes buffer
|
||||
#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 512 // number of bytes required for precompiled response
|
||||
|
||||
#endif
|
|
@ -592,7 +592,7 @@ void emlClearMem(void) {
|
|||
memset(emCARD, 0, CARD_MEMORY_SIZE);
|
||||
|
||||
// fill sectors trailer data
|
||||
for (uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16)))
|
||||
for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK) ? (b += 4) : (b += 16)))
|
||||
emlSetMem((uint8_t *)trailer, b, 1);
|
||||
|
||||
// uid
|
||||
|
@ -600,6 +600,19 @@ void emlClearMem(void) {
|
|||
return;
|
||||
}
|
||||
|
||||
uint8_t SectorTrailer(uint8_t blockNo) {
|
||||
if (blockNo <= MIFARE_2K_MAXBLOCK) {
|
||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
|
||||
return (blockNo | 0x03);
|
||||
} else {
|
||||
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
|
||||
return (blockNo | 0x0f);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsSectorTrailer(uint8_t blockNo) {
|
||||
return (blockNo == SectorTrailer(blockNo));
|
||||
}
|
||||
|
||||
// Mifare desfire commands
|
||||
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
|
||||
|
|
|
@ -33,12 +33,26 @@
|
|||
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
|
||||
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
|
||||
|
||||
// mifare 4bit card answers
|
||||
#define CARD_ACK 0x0A // 1010 - ACK
|
||||
#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed)
|
||||
#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error
|
||||
// reader voltage field detector
|
||||
#define MF_MINFIELDV 4000
|
||||
|
||||
// debug
|
||||
// 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode
|
||||
#define MF_DBG_NONE 0
|
||||
#define MF_DBG_ERROR 1
|
||||
#define MF_DBG_ALL 2
|
||||
#define MF_DBG_EXTENDED 4
|
||||
|
||||
// Mifare 4k/2k/1k/mini Max Block / Max Sector
|
||||
#define MIFARE_4K_MAXBLOCK 256
|
||||
#define MIFARE_2K_MAXBLOCK 128
|
||||
#define MIFARE_1K_MAXBLOCK 64
|
||||
#define MIFARE_MINI_MAXBLOCK 20
|
||||
|
||||
#define MIFARE_MINI_MAXSECTOR 5
|
||||
#define MIFARE_1K_MAXSECTOR 16
|
||||
#define MIFARE_2K_MAXSECTOR 32
|
||||
#define MIFARE_4K_MAXSECTOR 40
|
||||
|
||||
//mifare emulator states
|
||||
#define MFEMUL_NOFIELD 0
|
||||
|
@ -47,7 +61,6 @@
|
|||
#define MFEMUL_SELECT2 3
|
||||
#define MFEMUL_SELECT3 4
|
||||
#define MFEMUL_AUTH1 5
|
||||
#define MFEMUL_AUTH2 6
|
||||
#define MFEMUL_WORK 7
|
||||
#define MFEMUL_WRITEBL2 8
|
||||
#define MFEMUL_INTREG_INC 9
|
||||
|
@ -93,6 +106,9 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
|
|||
uint8_t NumBlocksPerSector(uint8_t sectorNo);
|
||||
uint8_t FirstBlockOfSector(uint8_t sectorNo);
|
||||
|
||||
bool IsSectorTrailer(uint8_t blockNo);
|
||||
uint8_t SectorTrailer(uint8_t blockNo);
|
||||
|
||||
// emulator functions
|
||||
void emlClearMem(void);
|
||||
void emlSetMem(uint8_t *data, int blockNum, int blocksCount);
|
||||
|
|
|
@ -69,6 +69,10 @@ int usage_hf14_mf1ksim(void) {
|
|||
PrintAndLogEx(NORMAL, "Options:");
|
||||
PrintAndLogEx(NORMAL, " h this help");
|
||||
PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used");
|
||||
PrintAndLogEx(NORMAL, " t (Optional) 0 = MIFARE Mini");
|
||||
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 1k (Default)");
|
||||
PrintAndLogEx(NORMAL, " 1 = MIFARE Classic 2k");
|
||||
PrintAndLogEx(NORMAL, " 4 = MIFARE Classic 4k");
|
||||
PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after <numreads> blocks have been read by reader. 0 = infinite");
|
||||
PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted");
|
||||
PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader");
|
||||
|
@ -2132,7 +2136,7 @@ int CmdHF14AMf1kSim(const char *Cmd) {
|
|||
|
||||
uint8_t uid[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||
uint8_t exitAfterNReads = 0;
|
||||
uint8_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA);
|
||||
uint16_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA);
|
||||
int uidlen = 0;
|
||||
uint8_t cmdp = 0;
|
||||
bool errors = false, verbose = false, setEmulatorMem = false;
|
||||
|
@ -2154,6 +2158,31 @@ int CmdHF14AMf1kSim(const char *Cmd) {
|
|||
exitAfterNReads = param_get8(Cmd, cmdp + 1);
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 't':
|
||||
switch (param_get8(Cmd, cmdp + 1)) {
|
||||
case 0:
|
||||
// Mifare MINI
|
||||
flags |= FLAG_MF_MINI;
|
||||
break;
|
||||
case 1:
|
||||
// Mifare Classic 1k
|
||||
flags |= FLAG_MF_1K;
|
||||
break;
|
||||
case 2:
|
||||
// Mifare Classic 2k
|
||||
flags |= FLAG_MF_2K;
|
||||
break;
|
||||
case 4:
|
||||
// Mifare Classic 4k
|
||||
flags |= FLAG_MF_4K;
|
||||
break;
|
||||
default:
|
||||
// Mifare Classic 1k
|
||||
flags |= FLAG_MF_1K;
|
||||
break;
|
||||
}
|
||||
cmdp += 2;
|
||||
break;
|
||||
case 'u':
|
||||
param_gethex_ex(Cmd, cmdp + 1, uid, &uidlen);
|
||||
switch (uidlen) {
|
||||
|
|
|
@ -152,6 +152,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's.
|
|||
#define ISO14443A_CMD_HALT 0x50
|
||||
#define ISO14443A_CMD_RATS 0xE0
|
||||
|
||||
#define MIFARE_SELECT_CT 0x88
|
||||
#define MIFARE_AUTH_KEYA 0x60
|
||||
#define MIFARE_AUTH_KEYB 0x61
|
||||
#define MIFARE_MAGICWUPC1 0x40
|
||||
|
|
|
@ -47,10 +47,11 @@ typedef enum ISO14A_COMMAND {
|
|||
|
||||
typedef struct {
|
||||
uint8_t *response;
|
||||
size_t response_n;
|
||||
uint8_t *modulation;
|
||||
size_t modulation_n;
|
||||
uint16_t response_n;
|
||||
uint16_t modulation_n;
|
||||
uint32_t ProxToAirDuration;
|
||||
uint8_t par; // enough for precalculated parity of 8 Byte responses
|
||||
} tag_response_info_t;
|
||||
//-----------------------------------------------------------------------------
|
||||
// ISO 14443B
|
||||
|
|
|
@ -296,7 +296,10 @@ typedef struct {
|
|||
#define FLAG_10B_UID_IN_DATA 0x08
|
||||
#define FLAG_UID_IN_EMUL 0x10
|
||||
#define FLAG_NR_AR_ATTACK 0x20
|
||||
//#define FLAG_RANDOM_NONCE 0x40
|
||||
#define FLAG_MF_MINI 0x80
|
||||
#define FLAG_MF_1K 0x100
|
||||
#define FLAG_MF_2K 0x200
|
||||
#define FLAG_MF_4K 0x400
|
||||
|
||||
//Iclass reader flags
|
||||
#define FLAG_ICLASS_READER_ONLY_ONCE 0x01
|
||||
|
|
Loading…
Add table
Reference in a new issue