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:
Philippe Teuwen 2019-04-06 19:07:29 +02:00
commit 05b4b27823
12 changed files with 1458 additions and 662 deletions

View file

@ -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

View file

@ -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);

View file

@ -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);
}

View file

@ -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

File diff suppressed because it is too large Load diff

44
armsrc/mifaresim.h Normal file
View 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

View file

@ -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) {

View file

@ -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);

View file

@ -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) {

View file

@ -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

View file

@ -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

View file

@ -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