From 64c3ae8b34fa9ffdd5d4fd98ce14ae960d185e86 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 21:04:25 +0100 Subject: [PATCH 01/19] hf mf sim --- armsrc/Makefile | 3 +- armsrc/apps.h | 6 +- armsrc/iso14443a.c | 704 +++----------------------- armsrc/iso14443a.h | 20 +- armsrc/mifaresim.c | 1149 +++++++++++++++++++++++++++++++++++++++++++ armsrc/mifaresim.h | 59 +++ armsrc/mifareutil.c | 11 + armsrc/mifareutil.h | 22 + client/cmdhfmf.c | 31 +- common/protocols.h | 1 + include/mifare.h | 5 +- include/usb_cmd.h | 6 +- 12 files changed, 1369 insertions(+), 648 deletions(-) create mode 100644 armsrc/mifaresim.c create mode 100644 armsrc/mifaresim.h diff --git a/armsrc/Makefile b/armsrc/Makefile index 382407e1d..3c93c4af8 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -62,8 +62,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ SRC_LCD = fonts.c LCD.c SRC_LF = lfops.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 diff --git a/armsrc/apps.h b/armsrc/apps.h index 36c865900..5bb92dc18 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -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); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a22a79390..e556e0ff1 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -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; @@ -1621,7 +1635,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 @@ -1637,6 +1651,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; } } @@ -1755,11 +1770,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; @@ -2949,610 +2983,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)); - 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); +} \ No newline at end of file diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 4d28a8dfb..747f0c529 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -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, @@ -119,6 +130,7 @@ extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_da extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); extern void iso14a_set_trigger(bool enable); +extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); extern int EmSend4bit(uint8_t resp); extern int EmSendCmd(uint8_t *resp, uint16_t respLen); @@ -128,14 +140,18 @@ extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); extern int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision); extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); +extern void EmLogTraceReader(void); + +extern 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); -//extern 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(); +extern void AppendCrc14443a(uint8_t *data, int len); + #ifdef __cplusplus } #endif diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c new file mode 100644 index 000000000..f5aec6f0e --- /dev/null +++ b/armsrc/mifaresim.c @@ -0,0 +1,1149 @@ +//----------------------------------------------------------------------------- +// 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 +//----------------------------------------------------------------------------- + +#include "iso14443a.h" +#include "mifaresim.h" +#include "iso14443crc.h" +#include "crapto1/crapto1.h" +#include "BigBuf.h" +#include "string.h" +#include "mifareutil.h" +#include "fpgaloader.h" +#include "proxmark3.h" +#include "usb_cdc.h" +#include "cmd.h" +#include "protocols.h" +#include "apps.h" + +static tUart Uart; + +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); + uint8_t AC = ((sector_trailer[7] >> 5) & 0x04) + | ((sector_trailer[8] >> 2) & 0x02) + | ((sector_trailer[8] >> 7) & 0x01); + switch (action) { + case AC_KEYA_READ: { + return false; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); + break; + } + case AC_KEYA_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); + break; + } + case AC_KEYB_READ: { + return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); + break; + } + case AC_KEYB_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); + break; + } + case AC_AC_READ: { + return ((keytype == AUTHKEYA) + || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); + break; + } + case AC_AC_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); + break; + } + default: + return false; + } +} + + +static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { + + uint8_t sector_trailer[16]; + emlGetMem(sector_trailer, SectorTrailer(blockNo), 1); + + uint8_t sector_block; + if (blockNo < MIFARE_2K_MAXBLOCK) { + sector_block = blockNo & 0x03; + } else { + sector_block = (blockNo & 0x0f) / 5; + } + + uint8_t AC; + switch (sector_block) { + case 0x00: { + AC = ((sector_trailer[7] >> 2) & 0x04) + | ((sector_trailer[8] << 1) & 0x02) + | ((sector_trailer[8] >> 4) & 0x01); + break; + } + case 0x01: { + AC = ((sector_trailer[7] >> 3) & 0x04) + | ((sector_trailer[8] >> 0) & 0x02) + | ((sector_trailer[8] >> 5) & 0x01); + break; + } + case 0x02: { + AC = ((sector_trailer[7] >> 4) & 0x04) + | ((sector_trailer[8] >> 1) & 0x02) + | ((sector_trailer[8] >> 6) & 0x01); + break; + } + default: + return false; + } + + switch (action) { + case AC_DATA_READ: { + return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07)) + || (keytype == AUTHKEYB && !(AC == 0x07))); + if (MF_DBGLEVEL >= 2) Dbprintf("AC_DATA_READ: OK"); + break; + } + case AC_DATA_WRITE: { + return ((keytype == AUTHKEYA && (AC == 0x00)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); + break; + } + case AC_DATA_INC: { + return ((keytype == AUTHKEYA && (AC == 0x00)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); + break; + } + case AC_DATA_DEC_TRANS_REST: { + return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01)) + || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01))); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_DEC_TRANS_REST: OK"); + break; + } + } + + return false; +} + +static bool IsAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action) { + if (IsSectorTrailer(blockNo)) { + return IsTrailerAccessAllowed(blockNo, keytype, action); + } else { + return IsDataAccessAllowed(blockNo, keytype, action); + } +} + +static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t **responses, uint32_t *cuid, uint8_t *uid_len) { + + // SPEC: https://www.nxp.com/docs/en/application-note/AN10833.pdf + // ATQA + + 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 + + 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 + + *uid_len = 0; + + // -- 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) { // 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); + } 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); + } 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) { + + // 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 2L + 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 >= 1) { + Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); + } + break; + + // UID 7B + case 7: + + switch (MifareCardType) { + case 1: + memcpy(rATQA, rATQA_1k_7B, sizeof rATQA_1k_7B); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_7B"); + break; + case 2: + memcpy(rATQA, rATQA_2k_7B, sizeof rATQA_2k_7B); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_7B"); + break; + case 4: + 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 >= 1) { + 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 1: + memcpy(rATQA, rATQA_1k_10B, sizeof rATQA_1k_10B); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_10B"); + break; + case 2: + memcpy(rATQA, rATQA_2k_10B, sizeof rATQA_2k_10B); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_2k_10B"); + break; + case 4: + 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 >= 1) { + 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; + } + + 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) }, // + { .response = rSAK_1, .response_n = sizeof(rSAK_1) }, // + { .response = rSAK_2, .response_n = sizeof(rSAK_2) }, // + { .response = rSAK_4, .response_n = sizeof(rSAK_4) }, // + { .response = rSAK1, .response_n = sizeof(rSAK1) } // Acknowledge select - New another cascades + }; + + // 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 + + uint8_t *free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); + size_t free_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; + + for (size_t i = 0; i < TAG_RESPONSE_COUNT; i++) { + prepare_allocated_tag_modulation(&responses_init[i], &free_buffer_pointer, &free_buffer_size); + } + + *responses = responses_init; + + // indices into responses array: +#define ATQA 0 +#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 + +} + +static bool HasValidCRC(uint8_t *receivedCmd, uint16_t receivedCmd_len) { + uint8_t CRC_byte_1, CRC_byte_2; + compute_crc(CRC_14443_A, receivedCmd, receivedCmd_len - 2, &CRC_byte_1, &CRC_byte_2); + return (receivedCmd[receivedCmd_len - 2] == CRC_byte_1 && receivedCmd[receivedCmd_len - 1] == CRC_byte_2); +} + + +/** +*MIFARE 1K simulate. +* +*@param flags : +* FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK +* FLAG_4B_UID_IN_DATA - means that there is a 4-byte UID in the data-section, we're expected to use that +* FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that +* FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished +* FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later +* FLAG_RANDOM_NONCE - means we should generate some pseudo-random nonce data (only allows moebius attack) +*@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... +* (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) +*/ +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) { + tag_response_info_t *responses; + uint8_t cardSTATE = MFEMUL_NOFIELD; + uint8_t uid_len = 0; // 4,7, 10 + uint32_t cuid = 0; + + int vHf = 0; // in mV + + uint32_t selTimer = 0; + uint32_t authTimer = 0; + + uint8_t blockNo; + + uint8_t cardWRBL = 0; + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication + uint32_t cardRr = 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 reads a block + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmd_dec[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint16_t receivedCmd_len; + + uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + uint8_t rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; + uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; + + //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 + // This will be used in the reader-only attack. + + //allow collecting up to 7 sets of nonces to allow recovery of up to 7 keys +#define ATTACK_KEY_COUNT 7 // keep same as define in cmdhfmf.c -> readerAttack() (Cannot be more than 7) + nonces_t ar_nr_resp[ATTACK_KEY_COUNT * 2]; //*2 for 2 separate attack types (nml, moebius) 36 * 7 * 2 bytes = 504 bytes + memset(ar_nr_resp, 0x00, sizeof(ar_nr_resp)); + + uint8_t ar_nr_collected[ATTACK_KEY_COUNT * 2]; //*2 for 2nd attack type (moebius) + memset(ar_nr_collected, 0x00, sizeof(ar_nr_collected)); + uint8_t nonce1_count = 0; + uint8_t nonce2_count = 0; + uint8_t moebius_n_count = 0; + bool gettingMoebius = false; + uint8_t mM = 0; //moebius_modifier for collection storage + + // Authenticate response - nonce + uint32_t nonce; + if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) { + nonce = prand(); + } else { + nonce = bytes_to_num(rAUTH_NT, 4); + } + + + 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"); + } + + MifareSimInit(flags, datain, &responses, &cuid, &uid_len); + + // 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 + clear_trace(); + set_tracing(true); + LED_D_ON(); + ResetSspClk(); + + bool finished = false; + bool button_pushed = BUTTON_PRESS(); + + while (!button_pushed && !finished && !usb_poll_validate_length()) { + WDT_HIT(); + + // find reader field + if (cardSTATE == MFEMUL_NOFIELD) { + vHf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF)) >> 10; + if (vHf > MF_MINFIELDV) { + cardSTATE_TO_IDLE(); + LED_A_ON(); + } + button_pushed = BUTTON_PRESS(); + continue; + } + + //Now, get data + int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par); + + if (res == 2) { //Field is off! + LEDsoff(); + cardSTATE = MFEMUL_NOFIELD; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_NOFIELD"); + continue; + } else if (res == 1) { // button pressed + button_pushed = true; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Button pressed"); + break; + } + + // WUPA in HALTED state or REQA or WUPA in any other state + if (receivedCmd_len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { + selTimer = GetTickCount(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("EmSendPrecompiledCmd(&responses[ATQA]);"); + EmSendPrecompiledCmd(&responses[ATQA]); + + // init crypto block + crypto1_destroy(pcs); + cardAUTHKEY = AUTHKEYNONE; + //nonce = prng_successor(selTimer, 32) // RRG Repo, same as prand() ??? + if (flags & FLAG_RANDOM_NONCE) { + nonce = prand(); + } + LED_B_OFF(); + LED_C_OFF(); + cardSTATE = MFEMUL_SELECT1; + continue; + } + + switch (cardSTATE) { + case MFEMUL_NOFIELD: + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_NOFIELD"); + case MFEMUL_HALTED: + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("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); Need to be convert ? + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_IDLE"); + break; + } + + + // The anti-collision sequence, which is a mandatory part of the card activation sequence. + // It auto with 4-byte UID (= Single Size UID), + // 7 -byte UID (= Double Size UID) or 10-byte UID (= Triple Size UID). + + // Cascade Level 1 + // + // In the Cascade Level 1, the card send the anti-collision command CL1 (0x93) and the PICC returns + // either the 4-byte UID (UID0...UID4) and one-byte BCC + // or a Cascade Tag (CT) followed by the first 3 byte of the UID (UID0...UID2) and onebyte BCC. + // + // The CT (0x88) indicates that the UID is not yet complete, and another Cascade Level is needed + // + // The UID0 byte of a 4-byte UID must not be 0x88. + // The CL1 then must be selected, using the Select command CL1 (0x93). The PICC returns its SAK CL1, which indicates + // whether the UID is complete or not, and (if so), + // the type of card and whether the card supports T=CL. + + case MFEMUL_SELECT1: { + // select all - 0x93 0x20 (Anti Collision CL1) + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT1 - receivedCmd_len: %d - receivedCmd[0]: %02x - receivedCmd[1]: %02x", receivedCmd_len, receivedCmd[0], receivedCmd[1]); + if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL1 received - EmSendPrecompiledCmd(%02x)", &responses[UIDBCC1]); + EmSendPrecompiledCmd(&responses[UIDBCC1]); + break; + } + + // select card - 0x93 0x70 (Select CL1) + if (receivedCmd_len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL1 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); + switch (uid_len) { + case 4: + switch (MifareCardType) { + case 0: + EmSendPrecompiledCmd(&responses[SAK_MINI]); + break; + case 1: + EmSendPrecompiledCmd(&responses[SAK_1]); + break; + case 2: + EmSendPrecompiledCmd(&responses[SAK_2]); + break; + case 4: + EmSendPrecompiledCmd(&responses[SAK_4]); + break; + } + + LED_B_ON(); + cardSTATE = MFEMUL_WORK; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); + continue; + case 7: + // SAK => Need another select round + EmSendPrecompiledCmd(&responses[SAK1]); + cardSTATE = MFEMUL_SELECT2; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); + continue; + case 10: + // SAK => Need another select round + EmSendPrecompiledCmd(&responses[SAK1]); + cardSTATE = MFEMUL_SELECT2; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); + continue; + default: + break; + } + } + + // IDLE + cardSTATE_TO_IDLE(); + break; + } + + + // Cascade Level 2 + // + // If the UID is not yet complete, the PCD continues with an anti-collision CL2 command (0x95), + // and the PICC returns + // • either the last 4 bytes of the Double Size UID (UID3...UID6) and one-byte BCC, + // • or a Cascade Tag (CT) followed by the next 3 bytes of the Triple Size UID (UID3...UID5) and one-byte BCC. + // The CT (0x88) indicates that the UID is not yet complete, and another Cascade Level has to follow. + // + // The UID3 byte of a 7 byte or 10-byte UID must not be 0x88 + // The CL2 then must be selected, using the Select command CL2 (0x95). + // The PICC returns its SAK CL2, which indicates + // whether the UID is complete or not, and (if so), + // the type of card and whether the card supports T=CL. + + // select all cl2 - 0x95 0x20 + + case MFEMUL_SELECT2: { + if (receivedCmd_len == 2 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL2 received"); + EmSendPrecompiledCmd(&responses[UIDBCC2]); + continue; + } + + // select cl2 card - 0x95 0x70 xxxxxxxxxxxx + if (receivedCmd_len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], responses[UIDBCC2].response, 4) == 0)) { + + switch (uid_len) { + case 7: + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); + + switch (MifareCardType) { + case 0: + EmSendPrecompiledCmd(&responses[SAK_MINI]); + break; + case 1: + EmSendPrecompiledCmd(&responses[SAK_1]); + break; + case 2: + EmSendPrecompiledCmd(&responses[SAK_2]); + break; + case 4: + EmSendPrecompiledCmd(&responses[SAK_4]); + break; + } + cardSTATE = MFEMUL_WORK; + LED_B_ON(); + continue; + case 10: + // SAK => Need another select round + EmSendPrecompiledCmd(&responses[SAK1]); + cardSTATE = MFEMUL_SELECT3; + continue; + default: + break; + } + } + + cardSTATE_TO_IDLE(); + break; + } + + + // Cascade Level 3 + // Select command CL3 (0x97) + // + // If the UID is not yet complete, the PCD continues with an anti-collision CL3 command (0x97) + // and the PICC returns the last 4 bytes of the Triple Size UID (UID6...UID9) and one-byte BCC. + // The PICC returns its SAK CL3, which indicates the type of card and whether the card supports T=CL + + case MFEMUL_SELECT3: { + if (!uid_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 (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) { + EmSendPrecompiledCmd(&responses[UIDBCC3]); + break; + } + if (receivedCmd_len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], responses[UIDBCC3].response, 4) == 0)) { + + switch (MifareCardType) { + case 0: + EmSendPrecompiledCmd(&responses[SAK_MINI]); + break; + case 1: + EmSendPrecompiledCmd(&responses[SAK_1]); + break; + case 2: + EmSendPrecompiledCmd(&responses[SAK_2]); + break; + case 4: + EmSendPrecompiledCmd(&responses[SAK_4]); + break; + } + + cardSTATE = MFEMUL_WORK; + LED_B_ON(); + if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); + break; + } + cardSTATE_TO_IDLE(); + break; + } + + + case MFEMUL_WORK: { + if (receivedCmd_len == 0) { + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have exactly 4 bytes: receivedCmd_len=%d", receivedCmd_len); + break; + } + bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; + if (encrypted_data) { + // decrypt seqence + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("decrypt seqence"); + } else { + memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len); + } + if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have a valid CRC %d", receivedCmd_dec); + break; + } + + if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB)) { + // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack + if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK && !((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); + break; + } + cardAUTHSC = receivedCmd_dec[1] / 4; // received block num, Need to check if ok for 4k card ??? + cardAUTHKEY = receivedCmd_dec[0] & 0x01; + crypto1_destroy(pcs); + crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); + + // first authentication + if (!encrypted_data) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + crypto1_word(pcs, cuid ^ nonce, 0); //Update crypto state + num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce + } else { // nested authentication + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); + num_to_bytes(ans, 4, rAUTH_AT); + } + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + cardSTATE = MFEMUL_AUTH1; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("cardSTATE = MFEMUL_AUTH1"); + } + break; + } + if (!encrypted_data) { // all other commands must be encrypted (authenticated) + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Commands must be encrypted (authenticated)"); + break; + } + + // if Cmd is Read, Write, Inc, Dec, Restore, Transfert + if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK + || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK + || receivedCmd_dec[0] == MIFARE_CMD_INC + || receivedCmd_dec[0] == MIFARE_CMD_DEC + || receivedCmd_dec[0] == MIFARE_CMD_RESTORE + || receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { + // Check if Block num is not too far + if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); + break; + } + if (receivedCmd_dec[1] / 4 != cardAUTHSC) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); + break; + } + } + + // CMD READ block + if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { + blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); + emlGetMem(response, blockNo, 1); + if (MF_DBGLEVEL >= 2) Dbprintf("Data Block: %02x%02x%02x%02x%02x%02x%02x%02x%02x", response); + + + if (IsSectorTrailer(blockNo)) { + memset(response, 0x00, 6); // keyA can never be read + if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { + memset(response + 10, 0x00, 6); // keyB cannot be read + if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); + } + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { + memset(response + 6, 0x00, 4); // AC bits cannot be read + if (MF_DBGLEVEL >= 2) Dbprintf("[IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); + } + } else { + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) { + memset(response, 0x00, 16); // datablock cannot be read + if (MF_DBGLEVEL >= 2) Dbprintf("[IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); + } + } + AppendCrc14443a(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; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[ISO14443A_CMD_READBLOCK] Finish"); + break; + } + + // CMD WRITEBLOCK + if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { + blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardWRBL = blockNo; + cardSTATE = MFEMUL_WRITEBL2; + break; + } + + // CMD INC/DEC/RES + if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { + blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); + if (emlCheckValBl(blockNo)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) 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)); + cardWRBL = blockNo; + + // INC + if (receivedCmd_dec[0] == MIFARE_CMD_INC) { + cardSTATE = MFEMUL_INTREG_INC; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_INC"); + } + + // DEC + if (receivedCmd_dec[0] == MIFARE_CMD_DEC) { + cardSTATE = MFEMUL_INTREG_DEC; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_DEC"); + } + + // REST + if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { + cardSTATE = MFEMUL_INTREG_REST; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_REST"); + break; + } + } + + // TRANSFER + if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { + blockNo = receivedCmd_dec[1]; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); + if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1])) + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + else + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + break; + } + + // HALT + if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) { + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + LED_B_OFF(); + LED_C_OFF(); + cardSTATE = MFEMUL_HALTED; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_HALTED;"); + break; + } + + // RATS + if (receivedCmd[0] == ISO14443A_CMD_RATS) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + + // command not allowed + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + + case MFEMUL_AUTH1: { + if (receivedCmd_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); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 => cardSTATE_TO_IDLE())"); + 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) { + + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if (ar_nr_collected[i + mM] == 0 || ((cardAUTHSC == ar_nr_resp[i + mM].sector) && (cardAUTHKEY == ar_nr_resp[i + mM].keytype) && (ar_nr_collected[i + mM] > 0))) { + // if first auth for sector, or matches sector and keytype of previous auth + if (ar_nr_collected[i + mM] < 2) { + // if we haven't already collected 2 nonces for this sector + if (ar_nr_resp[ar_nr_collected[i + mM]].ar != ar) { + // Avoid duplicates... probably not necessary, ar should vary. + if (ar_nr_collected[i + mM] == 0) { + // first nonce collect + ar_nr_resp[i + mM].cuid = cuid; + ar_nr_resp[i + mM].sector = cardAUTHSC; + ar_nr_resp[i + mM].keytype = cardAUTHKEY; + ar_nr_resp[i + mM].nonce = nonce; + ar_nr_resp[i + mM].nr = nr; + ar_nr_resp[i + mM].ar = ar; + nonce1_count++; + // add this nonce to first moebius nonce + ar_nr_resp[i + ATTACK_KEY_COUNT].cuid = cuid; + ar_nr_resp[i + ATTACK_KEY_COUNT].sector = cardAUTHSC; + ar_nr_resp[i + ATTACK_KEY_COUNT].keytype = cardAUTHKEY; + ar_nr_resp[i + ATTACK_KEY_COUNT].nonce = nonce; + ar_nr_resp[i + ATTACK_KEY_COUNT].nr = nr; + ar_nr_resp[i + ATTACK_KEY_COUNT].ar = ar; + ar_nr_collected[i + ATTACK_KEY_COUNT]++; + } else { // second nonce collect (std and moebius) + ar_nr_resp[i + mM].nonce2 = nonce; + ar_nr_resp[i + mM].nr2 = nr; + ar_nr_resp[i + mM].ar2 = ar; + if (!gettingMoebius) { + nonce2_count++; + // check if this was the last second nonce we need for std attack + if (nonce2_count == nonce1_count) { + // done collecting std test switch to moebius + // first finish incrementing last sample + ar_nr_collected[i + mM]++; + // switch to moebius collection + gettingMoebius = true; + mM = ATTACK_KEY_COUNT; + if (flags & FLAG_RANDOM_NONCE) { + nonce = prand(); + } else { + nonce = nonce * 7; + } + break; + } + } else { + moebius_n_count++; + // if we've collected all the nonces we need - finish. + if (nonce1_count == moebius_n_count) finished = true; + } + } + ar_nr_collected[i + mM]++; + } + } + // we found right spot for this nonce stop looking + break; + } + } + } + + // --- crypto + crypto1_word(pcs, nr, 1); + cardRr = ar ^ crypto1_word(pcs, 0, 0); + + // test if auth OK + if (cardRr != prng_successor(nonce, 64)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + 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) + ); + } + + cardAUTHKEY = AUTHKEYNONE; // not authenticated + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + cardSTATE_TO_IDLE(); + break; + } + + ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); + num_to_bytes(ans, 4, rAUTH_AT); + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", + cardAUTHSC, + cardAUTHKEY == 0 ? 'A' : 'B', + GetTickCount() - authTimer + ); + } + LED_C_ON(); + //cardSTATE = MFEMUL_WORK; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf ("cardSTATE = MFEMUL_WORK"); + break; + } + + + // WRITE BL2 + case MFEMUL_WRITEBL2: { + if (receivedCmd_len == 18) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); + if (HasValidCRC(receivedCmd_dec, receivedCmd_len)) { + if (IsSectorTrailer(cardWRBL)) { + emlGetMem(response, cardWRBL, 1); + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYA_WRITE)) { + memcpy(receivedCmd_dec, response, 6); // don't change KeyA + } + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_KEYB_WRITE)) { + memcpy(receivedCmd_dec + 10, response + 10, 6); // don't change KeyA + } + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_AC_WRITE)) { + memcpy(receivedCmd_dec + 6, response + 6, 4); // don't change AC bits + } + } else { + if (!IsAccessAllowed(cardWRBL, cardAUTHKEY, AC_DATA_WRITE)) { + memcpy(receivedCmd_dec, response, 16); // don't change anything + } + } + emlSetMem(receivedCmd_dec, cardWRBL, 1); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? + cardSTATE = MFEMUL_WORK; + break; + } + } 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; + } + + // INC + case MFEMUL_INTREG_INC: { + if (receivedCmd_len == 6) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); + 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; + } + } + + // DEC + case MFEMUL_INTREG_DEC: { + if (receivedCmd_len == 6) { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); + 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; + } + + // REST + case MFEMUL_INTREG_REST: { + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); + 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; + } + + } // End Switch Loop + + button_pushed = BUTTON_PRESS(); + + } // End While Loop + + + // NR AR ATTACK + if (flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + if (ar_nr_collected[i] == 2) { + Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector); + Dbprintf("../tools/mfkey/mfkey32 %08x %08x %08x %08x %08x %08x", + ar_nr_resp[i].cuid, //UID + ar_nr_resp[i].nonce, //NT + ar_nr_resp[i].nr, //NR1 + ar_nr_resp[i].ar, //AR1 + ar_nr_resp[i].nr2, //NR2 + ar_nr_resp[i].ar2 //AR2 + ); + } + } + } + + for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) { + if (ar_nr_collected[i] == 2) { + Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector); + Dbprintf("../tools/mfkey/mfkey32v2 %08x %08x %08x %08x %08x %08x %08x", + ar_nr_resp[i].cuid, //UID + ar_nr_resp[i].nonce, //NT + ar_nr_resp[i].nr, //NR1 + ar_nr_resp[i].ar, //AR1 + ar_nr_resp[i].nonce2,//NT2 + ar_nr_resp[i].nr2, //NR2 + ar_nr_resp[i].ar2 //AR2 + ); + } + } + +if (MF_DBGLEVEL >= 1) { + Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); +} + +// Need to be debug - Card not recognize by my phone if uncommented +//if ((flags &FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK + //Send the collected ar_nr in the response + +// cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); +//} + +FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +LEDsoff(); +set_tracing(false); + +} diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h new file mode 100644 index 000000000..f62071966 --- /dev/null +++ b/armsrc/mifaresim.h @@ -0,0 +1,59 @@ +//----------------------------------------------------------------------------- +// 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 + +extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); + +//mifare emulator states +#define MFEMUL_NOFIELD 0 +#define MFEMUL_IDLE 1 +#define MFEMUL_SELECT1 2 +#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 +#define MFEMUL_INTREG_DEC 10 +#define MFEMUL_INTREG_REST 11 +#define MFEMUL_HALTED 12 + +#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 \ No newline at end of file diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index f61987f09..929851b4b 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -600,6 +600,17 @@ void emlClearMem(void) { return; } +uint8_t SectorTrailer(uint8_t blockNo) { + if (blockNo < 32 * 4) { + return (blockNo | 0x03); + } else { + 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) { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 971ba77f9..521d80202 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -38,7 +38,26 @@ #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 @@ -93,6 +112,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); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e3b8cb957..71bdb2ec8 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -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 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"); @@ -2134,7 +2138,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; @@ -2156,6 +2160,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) { diff --git a/common/protocols.h b/common/protocols.h index fde10f38a..00e3ef902 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -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 diff --git a/include/mifare.h b/include/mifare.h index 104d5cf09..d0b1168fa 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -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 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 94ae66eaa..7ee961466 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -290,7 +290,11 @@ 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_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 From b66152feb2da37fe87bffae9a37054935c8707e9 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 21:07:15 +0100 Subject: [PATCH 02/19] Astyle update --- armsrc/mifaresim.c | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index f5aec6f0e..a0978a53c 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -478,7 +478,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t button_pushed = BUTTON_PRESS(); continue; } - + //Now, get data int res = EmGetCmd(receivedCmd, &receivedCmd_len, receivedCmd_par); @@ -756,8 +756,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); cardSTATE = MFEMUL_AUTH1; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("cardSTATE = MFEMUL_AUTH1"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("cardSTATE = MFEMUL_AUTH1"); } break; } @@ -765,7 +765,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Commands must be encrypted (authenticated)"); break; } - + // if Cmd is Read, Write, Inc, Dec, Restore, Transfert if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK @@ -785,21 +785,21 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t break; } } - + // CMD READ block if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { blockNo = receivedCmd_dec[1]; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); emlGetMem(response, blockNo, 1); if (MF_DBGLEVEL >= 2) Dbprintf("Data Block: %02x%02x%02x%02x%02x%02x%02x%02x%02x", response); - - + + if (IsSectorTrailer(blockNo)) { memset(response, 0x00, 6); // keyA can never be read if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { memset(response + 10, 0x00, 6); // keyB cannot be read - if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { memset(response + 6, 0x00, 4); // AC bits cannot be read @@ -819,11 +819,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t Dbprintf("%d reads done, exiting", numReads); finished = true; } - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[ISO14443A_CMD_READBLOCK] Finish"); break; - } - + } + // CMD WRITEBLOCK if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { blockNo = receivedCmd_dec[1]; @@ -865,7 +865,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t break; } } - + // TRANSFER if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { blockNo = receivedCmd_dec[1]; @@ -906,7 +906,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 => cardSTATE_TO_IDLE())"); break; } - + uint32_t nr = bytes_to_num(receivedCmd, 4); uint32_t ar = bytes_to_num(&receivedCmd[4], 4); @@ -988,14 +988,14 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t , nonce // nt , prng_successor(nonce, 64) ); - } - - cardAUTHKEY = AUTHKEYNONE; // not authenticated - LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardSTATE_TO_IDLE(); - break; } - + + cardAUTHKEY = AUTHKEYNONE; // not authenticated + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + cardSTATE_TO_IDLE(); + break; + } + ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); num_to_bytes(ans, 4, rAUTH_AT); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); @@ -1008,7 +1008,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } LED_C_ON(); //cardSTATE = MFEMUL_WORK; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf ("cardSTATE = MFEMUL_WORK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); break; } @@ -1095,7 +1095,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } // End Switch Loop button_pushed = BUTTON_PRESS(); - + } // End While Loop @@ -1115,7 +1115,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } } } - + for (uint8_t i = ATTACK_KEY_COUNT; i < ATTACK_KEY_COUNT * 2; i++) { if (ar_nr_collected[i] == 2) { Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector); @@ -1131,19 +1131,19 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } } -if (MF_DBGLEVEL >= 1) { - Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); -} + if (MF_DBGLEVEL >= 1) { + Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); + } -// Need to be debug - Card not recognize by my phone if uncommented +// Need to be debug - Card not recognize by my phone if uncommented //if ((flags &FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK //Send the collected ar_nr in the response - + // cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); //} -FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); -LEDsoff(); -set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } From 6a52b6074fec0c6aefcbcc277d3a06d8b70f9d6a Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 21:17:07 +0100 Subject: [PATCH 03/19] Sync from Upstream --- .gitignore | 1 + CHANGELOG.md | 29 + HACKING.txt | 195 +++---- Makefile | 8 +- README.md | 4 +- armsrc/BigBuf.c | 41 -- armsrc/BigBuf.h | 1 - armsrc/Makefile | 4 +- armsrc/Standalone/hf_mattyrun.c | 2 +- armsrc/Standalone/hf_mattyrun.h | 2 +- armsrc/Standalone/hf_young.c | 2 +- armsrc/Standalone/hf_young.h | 2 +- armsrc/Standalone/lf_hidbrute.h | 2 +- armsrc/Standalone/lf_proxbrute.c | 2 +- armsrc/Standalone/lf_proxbrute.h | 2 +- armsrc/Standalone/lf_samyrun.c | 2 +- armsrc/Standalone/lf_samyrun.h | 2 +- armsrc/Standalone/standalone.h | 2 +- armsrc/aes.c | 2 +- armsrc/aes.h | 2 +- armsrc/appmain.c | 33 +- armsrc/apps.h | 20 +- armsrc/buzzer.c | 2 +- armsrc/desfire_crypto.c | 2 +- armsrc/desfire_key.c | 2 +- armsrc/desfire_key.h | 2 +- armsrc/epa.c | 7 +- armsrc/felica.c | 2 +- armsrc/flashmem.h | 2 +- armsrc/hfsnoop.c | 10 +- armsrc/hitag2.c | 463 +++++----------- armsrc/hitag2.h | 23 + armsrc/hitag2_crypto.c | 116 ++++ armsrc/hitag2_crypto.h | 36 ++ armsrc/hitagS.c | 766 +++++++++++--------------- armsrc/hitagS.h | 31 ++ armsrc/iclass.c | 4 +- armsrc/iso14443a.c | 2 +- armsrc/iso14443b.c | 8 +- armsrc/iso15693.c | 39 +- armsrc/lfops.c | 98 ++-- armsrc/lfsampling.c | 22 +- armsrc/lfsampling.h | 6 +- armsrc/mifarecmd.c | 4 +- armsrc/mifarecmd.h | 2 +- armsrc/mifaresniff.c | 2 +- armsrc/mifaresniff.h | 2 +- armsrc/pcf7931.c | 2 +- armsrc/pcf7931.h | 2 +- armsrc/start.c | 2 +- armsrc/string.h | 2 +- armsrc/ticks.h | 2 +- armsrc/util.h | 39 ++ client/amiitool/amiitool.c | 2 +- client/cli.c | 2 +- client/cmdcrc.c | 2 +- client/cmddata.c | 40 +- client/cmddata.h | 2 +- client/cmdflashmem.c | 2 +- client/cmdflashmem.h | 2 +- client/cmdhf.c | 4 +- client/cmdhf14a.c | 2 +- client/cmdhf14b.c | 30 +- client/cmdhf15.c | 14 +- client/cmdhfepa.c | 2 +- client/cmdhffelica.c | 4 +- client/cmdhffido.h | 2 +- client/cmdhficlass.c | 8 +- client/cmdhflegic.c | 2 +- client/cmdhflist.c | 2 +- client/cmdhfmf.c | 6 +- client/cmdhfmfdesfire.h | 2 +- client/cmdhfmfp.h | 2 +- client/cmdlf.c | 29 +- client/cmdlfhitag.c | 552 ++++++++++++++----- client/cmdlfhitag.h | 9 +- client/cmdlft55xx.c | 6 +- client/cmdlfti.c | 2 +- client/cmdmain.c | 2 +- client/cmdscript.c | 2 +- client/cmdsmartcard.c | 167 ++++-- client/cmdsmartcard.h | 3 +- client/cmdtrace.c | 46 +- client/crypto/libpcrypto.c | 15 + client/crypto/libpcrypto.h | 1 + client/emv/cmdemv.c | 2 + client/emv/emvjson.h | 2 +- client/fpga_compress.c | 18 +- client/hardnested/hardnested_tables.c | 2 +- client/hid-flasher/usb_cmd.h | 12 +- client/loclass/elite_crack.c | 2 +- client/loclass/fileutils.c | 54 +- client/loclass/fileutils.h | 8 +- client/lualibs/7816_error.lua | 2 +- client/lualibs/hf_reader.lua | 2 +- client/lualibs/precalc.lua | 2 +- client/lualibs/read14b.lua | 2 +- client/lualibs/taglib.lua | 2 +- client/lualibs/utils.lua | 2 +- client/mifare/mifarehost.h | 2 +- client/pm3_eml_mfd_test.py | 2 +- client/reveng/preset.c | 2 +- client/scandir.h | 2 +- client/scripting.c | 2 +- client/scripts/Legic_clone.lua | 2 +- client/scripts/brutesim.lua | 2 +- client/scripts/calc_di.lua | 2 +- client/scripts/calc_ev1_it.lua | 2 +- client/scripts/calc_mizip.lua | 2 +- client/scripts/calypso.lua | 2 +- client/scripts/e.lua | 2 +- client/scripts/emul2dump.lua | 2 +- client/scripts/emul2html.lua | 2 +- client/scripts/formatMifare.lua | 2 +- client/scripts/hf_read.lua | 2 +- client/scripts/htmldump.lua | 2 +- client/scripts/lf_bulk.lua | 2 +- client/scripts/mfkeys.lua | 2 +- client/scripts/ndef_dump.lua | 2 +- client/scripts/ntag_3d.lua | 2 +- client/scripts/parameters.lua | 2 +- client/scripts/test_t55x7_ask.lua | 2 +- client/scripts/test_t55x7_fsk.lua | 2 +- client/scripts/tnp3dump.lua | 2 +- client/scripts/tracetest.lua | 2 +- client/scripts/ufodump.lua | 2 +- client/snooper.c | 6 +- client/util.c | 60 +- client/util.h | 4 +- client/util_darwin.h | 2 +- common/bucketsort.h | 2 +- common/cmd.c | 2 +- common/crc.c | 2 +- common/crc16.h | 2 +- common/crc32.c | 2 +- common/crc64.c | 2 +- common/i2c.h | 2 +- common/iso15693tools.c | 5 +- common/iso15693tools.h | 2 +- common/legic_prng.c | 2 +- common/lfdemod.c | 5 +- common/lfdemod.h | 2 +- common/prng.h | 2 +- common/protocols.h | 1 + common/radixsort.c | 2 +- common/radixsort.h | 2 +- common/random.h | 2 +- common/tea.h | 2 +- common/usart.c | 2 +- common/usb_cdc.c | 2 +- common/wiegand.c | 2 +- include/at91sam7s512.h | 2 +- include/common.h | 2 +- include/hitag.h | 117 ++++ include/mifare.h | 3 +- include/usb_cmd.h | 14 +- proxmark3.sh | 2 +- tools/Makefile | 2 +- tools/findbits_test.py | 2 +- tools/mkversion.pl | 6 +- uart/uart_win32.c | 2 +- 161 files changed, 2002 insertions(+), 1463 deletions(-) create mode 100644 armsrc/hitag2.h create mode 100644 armsrc/hitag2_crypto.c create mode 100644 armsrc/hitag2_crypto.h create mode 100644 armsrc/hitagS.h create mode 100644 include/hitag.h diff --git a/.gitignore b/.gitignore index 785934f46..9a12efbe5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ # don't push these files to the repository .history +.bash_history *.log *.eml *.o diff --git a/CHANGELOG.md b/CHANGELOG.md index 34bf817bd..95c590a52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,35 @@ 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] + - Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox) + - Change - printing of fault bit markers (7) using a dot (@doegox) + - Change 'sc upgrade' - firmware file integrity check (@piwi) + - Fix 'data rawdemod am' - last bit was missing (@doegox) + - Fix 'hf 15 dump f' - also selects tag first (@iceman) + - Fix 'hf iclass clone' - missing fileclose (@iceman) + - Add 'trace list hitag' - old hitag annotations now use the new trace (@iceman) + - Change 'lf hitag sim' - loads bin/eml/json (@iceman) + - Change 'lf hitag reader 21' - saves in bin/eml/json (@iceman) + - Change 'lf hitag' - refactoring (@iceman) + - Change 'lf hitag' - refactoring (@piwi) + - Fix 'lf hitag' - generic fix for missing clock init (@piwi) + - Fix fsk sim operations on deviceside - avoid division by zero (@doegox) + - Fix 'hf mf fchk' - condition always false (@doegox) + - Fix 'lf t55xx recoverpw' - shift as u32 (@doegox) + - Fix 'lf ti demod' - shift as u32 (@doegox) + - Fix 'lf ti read' - shift as u32 (@doegox) + - Fix 'lf t55xx chk' - condition always false (@doegox) + - Change 'lf sim' - ledcontrol refactoring (@doegox) + - Fix 'hf mf nack' - signedness bug (@doegox) + - Fix 'hf epa cnonce' - check return value (@doegox) + - Fix 'lf hitag write' - condition always true (@doegox) + - Fix 'mem write' - added extra check (@doegox) + - Fix 'iso15693' - bad string cpy (@doegox) + - Fix 'make style' - EOF LF support (@doegox) + - Add 'hf 14b raw' - added -t for timeout (@iceman) + - Rename 'lf hitag snoop' - renamed to 'lf hitag sniff' (@iceman) + - Rename 'lf snoop' - renamed to 'lf sniff' (@iceman) + - Rename 'hf snoop' - renamed to 'hf sniff' (@iceman) - Fix 'hf mfp wrbl' - more blocks available (@merlokk) - Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox) - Change Makefiles optimizations when recompiling (@doegox) diff --git a/HACKING.txt b/HACKING.txt index fb68142e9..9d7bdaedc 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -1,38 +1,26 @@ - "Coding styles are like assholes, everyone has one and no one likes anyone elses." - --Eric Warmenhoven + "Coding styles are like assholes, everyone has one and no one likes anyone elses." + --Eric Warmenhoven The Proxmark3 codebase is pretty messy and in the process of being cleaned up, so we don't have clear guidelines on how to place new code just yet. However, please don't make things worse. However, we have established a set of coding style guidelines in order to -clean up the code consistently and keep it consistent in the future. Use common -sense and good taste. If breaking a rule leads to cleaner code, you can do so, -but laziness is not an excuse. +clean up the code consistently and keep it consistent in the future. +Look around and respect the same style. +Helper script to get some uniformity in the style: + +$ make style + +It makes use of "astyle" so be sure to install it first. + === INDENTATION === -Use tabs for indentation, but use spaces for alignment: +Don't use tabs, editors are messing them up too easily. +Increment unit is four spaces. - if (foo(this, that, there) - && bar == baz) - { - dostuff(); - } - -Notice it's like this (T___ for tab, S for space, for a 4-char tab setting): - -T___if (foo(this, that, there) -T___SSSS&& bar == baz) - -Another example: - -#define THIS 0x10 -#define THAT_THING 0x20 -#define SOMETHING_ELSE 0x80 - -These should look good no matter what your editor's tab setting is, so go nuts -and pick whatever you like best. +If you use "make style", this will be done for you. === WIDTH === @@ -65,24 +53,28 @@ use microsoft-style DWORD and the like, we're getting rid of those. Avoid char for buffers, uint8_t is more obvious when you're not working with strings. Use 'const' where things are const. Try to use size_t for sizes. -Pointers are: - void *ptr; +Pointers and reference operators are attached to the variable name: + void *ptr; not: - void* ptr; + void* ptr; otherwise you're tempted to write: - void* in, out; + void* in, out; and you'll fail. +"make style" will take care of pointers & reference operators. + === EXPRESSIONS === In general, use whitespace around binary operators - no unspaced blobs of an -expression. This rule may be broken if it makes things clearer. For example, +expression. "make style" will take care of whitespaces around operators. - if (5*a < b && some_bool_var) +For example, + + if (5 * a < b && some_bool_var) but not - if (5*a 1 line, put braces -around them all. +You can skip braces around 1 line statements but don't mix braces vs. no braces. === FUNCTIONS === -Functions with no arguments are declared as f(void), not f(). Put the return -type on the same line. Use static for functions that aren't exported, and put -exported functions in a header file (one header file per source file with -exported functions usually, no huge headers with all functions). Put a space -after a comma in argument lists. +Put the return type on the same line. +Put a space after a comma in argument lists. +Open the brace after the declaration (after a space). +"make style" will take care of all that. -void foo(int a_thing, int something_else) -{ - ... +void foo(int a_thing, int something_else) { + ... } -void baz(void) -{ - foo(bluh, blah); +Functions with no arguments are declared as f(void), not f(). +Use static for functions that aren't exported, and put exported functions +in a header file (one header file per source file with exported functions +usually, no huge headers with all functions). + +void baz(void) { + foo(bluh, blah); } Function names should be separated_with_underscores(), except for standard functions (memcpy, etc.). It may make sense to break this rule for very common, generic functions that look like library functions (e.g. dprintf()). -Don't use single-character arguments. Exception: very short functions with one -argument that's really obvious: +Don't use single-character arguments. +Exception: very short functions with one argument that's really obvious: -static int ascii(char c) -{ - if (c < 0x20 || c >= 0x7f) - return '.'; - else - return c; +static int ascii(char c) { + if (c < 0x20 || c >= 0x7f) + return '.'; + else + return c; } vs. -static void hexdump(void *buf, size_t len) -{ - ... +static void hexdump(void *buf, size_t len) { + ... } As a general guideline, functions shouldn't usually be much more than 30-50 @@ -188,7 +160,7 @@ probably missing some factoring/restructuring opportunity. Use typedefs when defining structs. The type should be named something_t. typedef struct { - blah blah; + blah blah; } prox_cmd_t; You can use anonymous enums to replace lots of sequential or mostly-sequential @@ -199,16 +171,18 @@ You can use anonymous enums to replace lots of sequential or mostly-sequential Indent once for the case: labels, then again for the body. Like this: switch(bar) { - case OPTION_A: - do_stuff(); - break; - case OPTION_B: - do_other_stuff(); - break; + case OPTION_A: + do_stuff(); + break; + case OPTION_B: + do_other_stuff(); + break; } -If you fall through into another case, add an explicit comment; otherwise, it -can look confusing. +"make style" will take care of the indentation. + +If you fall through into another case, add an explicit comment; +otherwise, it can look confusing. If your switch() is too long or has too many cases, it should be cleaned up. Split off the cases into functions, break the switch() into parent and children @@ -218,12 +192,12 @@ the like. In other words, use common sense and your brain. If you need local scope variables for a case, you can add braces: switch(bar) { - case OPTION_A: { - int baz = 5*bar; - do_stuff(baz); - break; - } - ... + case OPTION_A: { + int baz = 5 * bar; + do_stuff(baz); + break; + } + ... But at that point you should probably consider using a separate function. @@ -266,7 +240,7 @@ License/description header first: //----------------------------------------------------------------------------- If you modify a file in any non-trivial way (add code, etc.), add your copyright -to the top. +to the top with the current year. === HEADER FILES === @@ -284,8 +258,7 @@ you shouldn't use it (same for _FOOBAR_H). === WHITESPACE === -Avoid trailing whitespace (no line should end in tab or space). People forget -this all the time if their editor doesn't handle it, but don't be surprised if -you see someone fixing it from time to time. - +Avoid trailing whitespace (no line should end in tab or space). Keep a newline (blank line) at the end of each file. + +"make style" will take care of both. diff --git a/Makefile b/Makefile index 14bf98074..6e7c9abd5 100644 --- a/Makefile +++ b/Makefile @@ -106,8 +106,14 @@ endif print-%: ; @echo $* = $($*) style: + # Make sure astyle is installed @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) - find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "Makefile" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; + # Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile + find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \ + -exec perl -pi -e 's/[ \t\r]+$$//' {} \; \ + -exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \ + -exec sh -c "echo >> {}" \; + # Apply astyle on *.c, *.h, *.cpp find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \ --indent=spaces=4 --indent-switches --indent-preprocessor \ --keep-one-line-blocks --max-instatement-indent=60 \ diff --git a/README.md b/README.md index c8c04f852..cfdbacc61 100644 --- a/README.md +++ b/README.md @@ -286,7 +286,7 @@ You will need to run these commands to make sure your rdv4 is prepared ### Verify sim module firmware version To make sure you got the latest sim module firmware. -_Lastest version is v3.10_ +_Lastest version is v3.11_ pm3 --> hw status @@ -298,7 +298,7 @@ Find version in the long output, look for these two lines This version is obselete. The following command upgrades your device sim module firmware. Don't not turn of your device during the execution of this command. - pm3 --> sc upgrade f ../tools/simmodule/SIM010.BIN + pm3 --> sc upgrade f ../tools/simmodule/SIM011.BIN You get the following output, this is a successful execution. diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index ab45a2681..267e6811b 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -195,47 +195,6 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_ return true; } -int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) { - /** - Todo, rewrite the logger to use the generic functionality instead. It should be noted, however, - that this logger takes number of bits as argument, not number of bytes. - **/ - - if (!tracing) return false; - - uint8_t *trace = BigBuf_get_addr(); - uint32_t iLen = nbytes(iBits); - // Return when trace is full - if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; - - //Hitag traces appear to use this traceformat: - // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag) - // 32 bits parity - // 8 bits size (number of bits in the trace entry, not number of bytes) - // y Bytes data - - rsamples += iSamples; - trace[traceLen++] = ((rsamples >> 0) & 0xff); - trace[traceLen++] = ((rsamples >> 8) & 0xff); - trace[traceLen++] = ((rsamples >> 16) & 0xff); - trace[traceLen++] = ((rsamples >> 24) & 0xff); - - if (!readerToTag) { - trace[traceLen - 1] |= 0x80; - } - - trace[traceLen++] = ((dwParity >> 0) & 0xff); - trace[traceLen++] = ((dwParity >> 8) & 0xff); - trace[traceLen++] = ((dwParity >> 16) & 0xff); - trace[traceLen++] = ((dwParity >> 24) & 0xff); - trace[traceLen++] = iBits; - - memcpy(trace + traceLen, btBytes, iLen); - traceLen += iLen; - - return true; -} - // Emulator memory uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { uint8_t *mem = BigBuf_get_EM_addr(); diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 995451b9b..bdd2003be 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -42,6 +42,5 @@ extern void set_tracing(bool enable); extern void set_tracelen(uint32_t value); extern bool get_tracing(void); extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); -extern int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); #endif /* __BIGBUF_H */ diff --git a/armsrc/Makefile b/armsrc/Makefile index 382407e1d..707325d41 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -38,7 +38,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ -DWITH_ISO14443a \ -DWITH_ICLASS \ -DWITH_FELICA \ - -DWITH_HFSNOOP \ + -DWITH_HFSNIFF \ -DWITH_LF_SAMYRUN \ -fno-strict-aliasing -ffunction-sections -fdata-sections @@ -60,7 +60,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c +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 diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index bf4b71d61..8cac76c35 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -433,4 +433,4 @@ void RunMod() { } } } -} \ No newline at end of file +} diff --git a/armsrc/Standalone/hf_mattyrun.h b/armsrc/Standalone/hf_mattyrun.h index 8b33e67c5..6602eba54 100644 --- a/armsrc/Standalone/hf_mattyrun.h +++ b/armsrc/Standalone/hf_mattyrun.h @@ -20,4 +20,4 @@ #define OPTS 2 -#endif /* __HF_MATTYRUN_H */ \ No newline at end of file +#endif /* __HF_MATTYRUN_H */ diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 99af4ef1e..4b7a87e99 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -259,4 +259,4 @@ void RunMod() { LED(selected + 1, 0); } } -} \ No newline at end of file +} diff --git a/armsrc/Standalone/hf_young.h b/armsrc/Standalone/hf_young.h index 46c0d1361..dcd8b13e7 100644 --- a/armsrc/Standalone/hf_young.h +++ b/armsrc/Standalone/hf_young.h @@ -19,4 +19,4 @@ #define OPTS 2 -#endif /* __HF_YOUNG_H */ \ No newline at end of file +#endif /* __HF_YOUNG_H */ diff --git a/armsrc/Standalone/lf_hidbrute.h b/armsrc/Standalone/lf_hidbrute.h index bc1cf2e31..49b0af6c6 100644 --- a/armsrc/Standalone/lf_hidbrute.h +++ b/armsrc/Standalone/lf_hidbrute.h @@ -21,4 +21,4 @@ void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc); -#endif /* __LF_HIDBRUTE_H */ \ No newline at end of file +#endif /* __LF_HIDBRUTE_H */ diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index ea1bd1f6f..178ce98fb 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -164,4 +164,4 @@ void RunMod() { out: DbpString("[=] exiting"); LEDsoff(); -} \ No newline at end of file +} diff --git a/armsrc/Standalone/lf_proxbrute.h b/armsrc/Standalone/lf_proxbrute.h index 3911fee35..3a9e1ce29 100644 --- a/armsrc/Standalone/lf_proxbrute.h +++ b/armsrc/Standalone/lf_proxbrute.h @@ -18,4 +18,4 @@ #define OPTS 2 -#endif /* __LF_PROXBRUTE_H */ \ No newline at end of file +#endif /* __LF_PROXBRUTE_H */ diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index ec0e4d19e..b4530fa2f 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -138,4 +138,4 @@ void RunMod() { out: DbpString("[=] exiting"); LEDsoff(); -} \ No newline at end of file +} diff --git a/armsrc/Standalone/lf_samyrun.h b/armsrc/Standalone/lf_samyrun.h index cf21e1261..52c0bb942 100644 --- a/armsrc/Standalone/lf_samyrun.h +++ b/armsrc/Standalone/lf_samyrun.h @@ -19,4 +19,4 @@ #define OPTS 2 -#endif /* __LF_SAMYRUN_H */ \ No newline at end of file +#endif /* __LF_SAMYRUN_H */ diff --git a/armsrc/Standalone/standalone.h b/armsrc/Standalone/standalone.h index 53d5ff13d..980bcbf46 100644 --- a/armsrc/Standalone/standalone.h +++ b/armsrc/Standalone/standalone.h @@ -16,4 +16,4 @@ extern void RunMod(); -#endif /* __STANDALONE_H */ \ No newline at end of file +#endif /* __STANDALONE_H */ diff --git a/armsrc/aes.c b/armsrc/aes.c index 61a8da76b..f8a36f28c 100644 --- a/armsrc/aes.c +++ b/armsrc/aes.c @@ -1167,4 +1167,4 @@ int main() { return 0; } -#endif \ No newline at end of file +#endif diff --git a/armsrc/aes.h b/armsrc/aes.h index afe7e5e4e..aa9f0c582 100644 --- a/armsrc/aes.h +++ b/armsrc/aes.h @@ -31,4 +31,4 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen); int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen); -#endif \ No newline at end of file +#endif diff --git a/armsrc/appmain.c b/armsrc/appmain.c index dbe20b2b7..aecfee076 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -650,8 +650,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; - case CMD_LF_SNOOP_RAW_ADC_SAMPLES: { - uint32_t bits = SnoopLF(); + case CMD_LF_SNIFF_RAW_ADC_SAMPLES: { + uint32_t bits = SniffLF(); cmd_send(CMD_ACK, bits, 0, 0, 0, 0); break; } @@ -664,13 +664,13 @@ void UsbPacketReceived(uint8_t *packet, int len) { CmdHIDsimTAG(c->arg[0], c->arg[1], 1); break; case CMD_FSK_SIM_TAG: - CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); break; case CMD_ASK_SIM_TAG: - CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); break; case CMD_PSK_SIM_TAG: - CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); break; case CMD_HID_CLONE_TAG: CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); @@ -765,8 +765,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif #ifdef WITH_HITAG - case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type - SnoopHitag(c->arg[0]); + case CMD_SNIFF_HITAG: // Eavesdrop Hitag tag, args = type + SniffHitag(c->arg[0]); break; case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content SimulateHitagTag((bool)c->arg[0], (byte_t *)c->d.asBytes); @@ -786,7 +786,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge if ((hitag_function)c->arg[0] < 10) { WritePageHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); - } else if ((hitag_function)c->arg[0] >= 10) { + } else { WriterHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); } break; @@ -843,7 +843,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_READ_SRI_TAG: ReadSTMemoryIso14443b(c->arg[0]); break; - case CMD_SNOOP_ISO_14443B: + case CMD_SNIFF_ISO_14443B: SniffIso14443b(); break; case CMD_SIMULATE_TAG_ISO_14443B: @@ -862,7 +862,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_FELICA_LITE_SIM: felica_sim_lite(c->arg[0]); break; - case CMD_FELICA_SNOOP: + case CMD_FELICA_SNIFF: felica_sniff(c->arg[0], c->arg[1]); break; case CMD_FELICA_LITE_DUMP: @@ -871,7 +871,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif #ifdef WITH_ISO14443a - case CMD_SNOOP_ISO_14443a: + case CMD_SNIFF_ISO_14443a: SniffIso14443a(c->arg[0]); break; case CMD_READER_ISO_14443a: @@ -1003,7 +1003,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { #ifdef WITH_ICLASS // Makes use of ISO14443a FPGA Firmware - case CMD_SNOOP_ICLASS: + case CMD_SNIFF_ICLASS: SniffIClass(); break; case CMD_SIMULATE_TAG_ICLASS: @@ -1043,9 +1043,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; #endif -#ifdef WITH_HFSNOOP +#ifdef WITH_HFSNIFF case CMD_HF_SNIFFER: - HfSnoop(c->arg[0], c->arg[1]); + HfSniff(c->arg[0], c->arg[1]); break; #endif @@ -1322,10 +1322,12 @@ void UsbPacketReceived(uint8_t *packet, int len) { // first mem page res = Flash_WriteDataCont(startidx, data, first_len); + isok = (res == first_len) ? 1 : 0; + // second mem page res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); - isok = (res == (len - first_len)) ? 1 : 0; + isok &= (res == (len - first_len)) ? 1 : 0; } else { res = Flash_WriteDataCont(startidx, data, len); @@ -1389,6 +1391,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { FlashStop(); cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + BigBuf_free(); LED_B_OFF(); break; } diff --git a/armsrc/apps.h b/armsrc/apps.h index 36c865900..62fce3931 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -85,9 +85,9 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol); void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles); void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol); -void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); -void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); -void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); +void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); +void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); +void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); @@ -222,24 +222,12 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); -// hitag2.h -void SnoopHitag(uint32_t type); -void SimulateHitagTag(bool tag_mem_supplied, byte_t *data); -void ReaderHitag(hitag_function htf, hitag_data *htd); -void WriterHitag(hitag_function htf, hitag_data *htd, int page); - -//hitagS.h -void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data); -void ReadHitagS(hitag_function htf, hitag_data *htd); -void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); -void check_challenges(bool file_given, byte_t *data); - // cmd.h uint8_t cmd_receive(UsbCommand *cmd); uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); // util.h -void HfSnoop(int, int); +void HfSniff(int, int); //felica.c extern void felica_sendraw(UsbCommand *c); diff --git a/armsrc/buzzer.c b/armsrc/buzzer.c index 27d0cd12a..708b7d3f7 100644 --- a/armsrc/buzzer.c +++ b/armsrc/buzzer.c @@ -83,4 +83,4 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_1,2*count); LED_B_ON(); */ -} \ No newline at end of file +} diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index 0a23305fd..fd3f30d0d 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -630,4 +630,4 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); offset += block_size; } -} \ No newline at end of file +} diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index a723a203e..e1f880c8b 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -152,4 +152,4 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire Desfire_aes_key_new(buffer, key); break; } -} \ No newline at end of file +} diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h index adbda9c42..4fc02854e 100644 --- a/armsrc/desfire_key.h +++ b/armsrc/desfire_key.h @@ -17,4 +17,4 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, uint8_t Desfire_key_get_version(desfirekey_t key); void Desfire_key_set_version(desfirekey_t key, uint8_t version); void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); -#endif \ No newline at end of file +#endif diff --git a/armsrc/epa.c b/armsrc/epa.c index 95de11550..521bb3f69 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -305,6 +305,11 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) { // initiate the PACE protocol // use the CAN for the password since that doesn't change func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); + // check if the command succeeded + if (func_return != 0) { + EPA_PACE_Collect_Nonce_Abort(4, func_return); + return; + } // now get the nonce uint8_t nonce[256] = {0}; @@ -312,7 +317,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) { func_return = EPA_PACE_Get_Nonce(requested_size, nonce); // check if the command succeeded if (func_return < 0) { - EPA_PACE_Collect_Nonce_Abort(4, func_return); + EPA_PACE_Collect_Nonce_Abort(5, func_return); return; } diff --git a/armsrc/felica.c b/armsrc/felica.c index 3aa3c282d..190960bd4 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -544,7 +544,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { int remFrames = (samplesToSkip) ? samplesToSkip : 0; - Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); + Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 4af499d3a..f4258a11b 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -151,4 +151,4 @@ void Flashmem_print_status(void); -#endif \ No newline at end of file +#endif diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 4ec60d175..11ceff3d9 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -4,9 +4,9 @@ #include "util.h" #include "usb_cdc.h" // for usb_poll_validate_length -static void RAMFUNC optimizedSnoop(void); +static void RAMFUNC optimizedSniff(void); -static void RAMFUNC optimizedSnoop(void) { +static void RAMFUNC optimizedSniff(void) { int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory uint16_t *dest = (uint16_t *)BigBuf_get_addr(); @@ -23,7 +23,7 @@ static void RAMFUNC optimizedSnoop(void) { set_tracelen(BigBuf_max_traceLen()); } -void HfSnoop(int samplesToSkip, int triggersToSkip) { +void HfSniff(int samplesToSkip, int triggersToSkip) { BigBuf_free(); BigBuf_Clear(); @@ -66,14 +66,14 @@ void HfSnoop(int samplesToSkip, int triggersToSkip) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) waitcount--; } - optimizedSnoop(); + optimizedSniff(); Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); } //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - DbpString("HF Snoop end"); + DbpString("HF Sniffing end"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index f328ccb0d..57200c701 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -3,46 +3,35 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Hitag2 emulation (preliminary test version) +// Hitag2 emulation // // (c) 2009 Henryk Plötz //----------------------------------------------------------------------------- // Hitag2 complete rewrite of the code // - Fixed modulation/encoding issues // - Rewrote code for transponder emulation -// - Added snooping of transponder communication +// - Added sniffing of transponder communication // - Added reader functionality // // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- +// Piwi, 2019 +// Iceman, 2019 +#include "hitag2.h" +#include "hitag2_crypto.h" +#include "hitag.h" #include "proxmark3.h" #include "apps.h" #include "util.h" -#include "hitag2.h" #include "string.h" #include "BigBuf.h" -static bool bQuiet; static bool bCrypto; static bool bAuthenticating; static bool bPwd; static bool bSuccessful; -struct hitag2_tag { - uint32_t uid; - enum { - TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr - TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password - TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands - TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written - } state; - unsigned int active_sector; - uint8_t crypto_active; - uint64_t cs; - uint8_t sectors[12][4]; -}; - static struct hitag2_tag tag = { .state = TAG_STATE_RESET, .sectors = { // Password mode: | Crypto mode: @@ -81,87 +70,6 @@ static uint8_t key[8]; static uint8_t writedata[4]; static uint64_t cipher_state; -/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ -// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. -// For educational purposes only. -// No warranties or guarantees of any kind. -// This code is released into the public domain by its author. - -// Basic macros: - -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) - -// Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) - -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 - -static u32 _f20(const u64 x) { - u32 i5; - - i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 - + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 - + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 - + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 - + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; - - return (ht2_f5c >> i5) & 1; -} - -static u64 _hitag2_init(const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; - - for (i = 0; i < 32; i++) { - x >>= 1; - x += (u64)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; - } - return x; -} - -static u64 _hitag2_round(u64 *state) { - u64 x = *state; - - x = (x >> 1) + - ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) - ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) - ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) - ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); - - *state = x; - return _f20(x); -} - -// "MIKRON" = O N M I K R -// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key -// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear -// Random = 65 6E 45 72 - Random IV, transmitted in clear -//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream - -// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". -// The inverse of the first 4 bytes is sent to the tag to authenticate. -// The rest is encrypted by XORing it with the subsequent keystream. - -static u32 _hitag2_byte(u64 *x) { - u32 i, c; - for (i = 0, c = 0; i < 8; i++) { - c += (u32) _hitag2_round(x) << (i ^ 7); - } - return c; -} - static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; @@ -173,48 +81,13 @@ static int hitag2_init(void) { return 0; } -static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) { - uint64_t key = ((uint64_t)tag->sectors[2][2]) | - ((uint64_t)tag->sectors[2][3] << 8) | - ((uint64_t)tag->sectors[1][0] << 16) | - ((uint64_t)tag->sectors[1][1] << 24) | - ((uint64_t)tag->sectors[1][2] << 32) | - ((uint64_t)tag->sectors[1][3] << 40); - uint32_t uid = ((uint32_t)tag->sectors[0][0]) | - ((uint32_t)tag->sectors[0][1] << 8) | - ((uint32_t)tag->sectors[0][2] << 16) | - ((uint32_t)tag->sectors[0][3] << 24); - uint32_t iv_ = (((uint32_t)(iv[0]))) | - (((uint32_t)(iv[1])) << 8) | - (((uint32_t)(iv[2])) << 16) | - (((uint32_t)(iv[3])) << 24); - tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_)); -} - -static int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) { - uint8_t authenticator_should[4]; - authenticator_should[0] = ~_hitag2_byte(cs); - authenticator_should[1] = ~_hitag2_byte(cs); - authenticator_should[2] = ~_hitag2_byte(cs); - authenticator_should[3] = ~_hitag2_byte(cs); - return (memcmp(authenticator_should, authenticator_is, 4) == 0); -} - -static int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, unsigned int bytes, unsigned int bits) { - int i; - for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs); - for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i); - return 0; -} - // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 +#ifndef T0 #define T0 192 - -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#endif #define HITAG_FRAME_LEN 20 #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ @@ -241,7 +114,6 @@ static int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, unsigned int by #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 - static void hitag_send_bit(int bit) { LED_A_ON(); // Reset clock for the next bit @@ -279,7 +151,6 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { LOW(GPIO_SSC_DOUT); } - static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { uint8_t rx_air[HITAG_FRAME_LEN]; @@ -398,8 +269,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ break; } -// LogTraceHitag(rx,rxlen,0,0,false); -// LogTraceHitag(tx,*txlen,0,0,true); +// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); +// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); if (tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); @@ -419,7 +290,6 @@ static void hitag_reader_send_bit(int bit) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6); - // SpinDelayUs(8*8); // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); @@ -435,7 +305,6 @@ static void hitag_reader_send_bit(int bit) { LED_A_OFF(); } - static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { @@ -605,8 +474,8 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t * if (!bCrypto) { uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40; uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24; - Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((rev64(ui64key)) >> 32), (uint32_t)((rev64(ui64key)) & 0xffffffff), rev32(ui32uid)); - cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0); + Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid)); + cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0); memset(tx, 0x00, 4); memset(tx + 4, 0xff, 4); hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0); @@ -801,7 +670,10 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t return true; } -void SnoopHitag(uint32_t type) { +void SniffHitag(uint32_t type) { + + StopTicks(); + int frame_count; int response; int overflow; @@ -814,12 +686,8 @@ void SnoopHitag(uint32_t type) { size_t rxlen = 0; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); - - // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); @@ -829,19 +697,18 @@ void SnoopHitag(uint32_t type) { auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - DbpString("Starting Hitag2 snoop"); + DbpString("Starting Hitag2 sniffing"); LED_D_ON(); // Set up eavesdropping mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; // Disable modulation, we are going to eavesdrop, not modulate ;) LOW(GPIO_SSC_DOUT); @@ -853,14 +720,16 @@ void SnoopHitag(uint32_t type) { // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. - uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; - AT91C_BASE_TC1->TC_CMR = t1_channel_mode; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // synchronized startup procedure + while (AT91C_BASE_TC1->TC_CV > 0) {}; // wait until TC0 returned to zero + // Reset the received frame, frame count and timing info memset(rx, 0x00, sizeof(rx)); frame_count = 0; @@ -971,10 +840,7 @@ void SnoopHitag(uint32_t type) { // Check if frame was captured if (rxlen > 0) { frame_count++; - if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) { - DbpString("Trace full"); - break; - } + LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); // Check if we recognize a valid authentication attempt if (nbytes(rxlen) == 8) { @@ -1005,49 +871,46 @@ void SnoopHitag(uint32_t type) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); - set_tracing(false); -// Dbprintf("frame received: %d",frame_count); -// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); -// DbpString("All done"); + + // release allocated memory from BigBuff. + BigBuf_free(); + StartTicks(); + + DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations"); } void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { - int frame_count; - int response; - int overflow; + + StopTicks(); + + int frame_count = 0, response = 0, overflow = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t tx[HITAG_FRAME_LEN]; size_t txlen = 0; - bool bQuitTraceFull = false; - bQuiet = false; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); - - // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); auth_table_len = 0; auth_table_pos = 0; - uint8_t *auth_table; - - auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); + uint8_t *auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + DbpString("Starting Hitag2 simulation"); + LED_D_ON(); hitag2_init(); @@ -1068,41 +931,41 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(50); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; // Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; - // Enable and reset counter + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // synchronized startup procedure + while (AT91C_BASE_TC1->TC_CV > 0); // wait until TC0 returned to zero + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); @@ -1144,16 +1007,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Check if frame was captured if (rxlen > 4) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, true)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(rx, nbytes(rxlen), response, response, NULL, true); // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1170,19 +1024,8 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Send and store the tag answer (if there is any) if (txlen) { - // Transmit the tag frame hitag_send_frame(tx, txlen); - // Store the frame in the trace - if (!bQuiet) { - if (!LogTraceHitag(tx, txlen, 0, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); } // Reset the received frame and response timing info @@ -1200,17 +1043,25 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + // release allocated memory from BigBuff. + BigBuf_free(); + + StartTicks(); DbpString("Sim Stopped"); - set_tracing(false); } void ReaderHitag(hitag_function htf, hitag_data *htd) { + + StopTicks(); + int frame_count = 0; int response = 0; uint8_t rx[HITAG_FRAME_LEN]; @@ -1233,7 +1084,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { Dbprintf("List identifier in password mode"); memcpy(password, htd->pwd.password, 4); blocknr = 0; - bQuiet = false; bPwd = false; break; } @@ -1241,7 +1091,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr, htd->auth.NrAr, 8); Dbhexdump(8, NrAr, false); - bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1251,7 +1100,6 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. Dbhexdump(6, key, false); blocknr = 0; - bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1260,13 +1108,11 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { Dbprintf("Testing %d authentication attempts", (auth_table_len / 8)); auth_table_pos = 0; memcpy(NrAr, auth_table, 8); - bQuiet = false; bCrypto = false; break; } case RHT2F_UID_ONLY: { blocknr = 0; - bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1274,45 +1120,48 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { default: { Dbprintf("Error, unknown function: %d", htf); set_tracing(false); + StartTicks(); return; } } FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - BigBuf_free(); + BigBuf_free(); clear_trace(); set_tracing(true); LED_D_ON(); hitag2_init(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); -// RELAY_OFF(); + + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + // PIO_A - BSR AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; @@ -1320,36 +1169,36 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero + // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings reset_sof = 4; t_wait = HITAG_T_WAIT_2; - // DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); - goto out; + goto out; } uint8_t attempt_count = 0; - - while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length() ) { + + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTraceHitag(rx, rxlen, response, 0, false); + LogTrace(rx, nbytes(rxlen), response, response, NULL, false); } // By default reset the transmission buffer @@ -1376,7 +1225,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { attempt_count++; //attempt 3 times to get uid then quit if (!bStop && attempt_count == 3) bStop = true; - + break; } default: { @@ -1405,7 +1254,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); } // Reset values for receiving frames @@ -1474,14 +1323,19 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } } - -out: + +out: LEDsoff(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + + // release allocated memory from BigBuff. + BigBuf_free(); + StartTicks(); + if (bSuccessful) cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); else @@ -1489,8 +1343,10 @@ out: } void WriterHitag(hitag_function htf, hitag_data *htd, int page) { - int frame_count; - int response; + + StopTicks(); + + int frame_count = 0, response = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; @@ -1502,17 +1358,13 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; - bool bQuitTraceFull = false; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; - - // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); - // DbpString("Starting Hitag reader family"); + // Reset the return status + bSuccessful = false; // Check configuration switch (htf) { @@ -1522,15 +1374,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { memcpy(writedata, htd->crypto.data, 4); Dbhexdump(6, key, false); blocknr = page; - bQuiet = false; bCrypto = false; bAuthenticating = false; - bQuitTraceFull = true; writestate = WRITE_STATE_START; } break; default: { Dbprintf("Error, unknown function: %d", htf); + StartTicks(); return; } break; @@ -1540,44 +1391,45 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { hitag2_init(); // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - - // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG + | AT91C_TC_LDRA_FALLING; // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0) {}; + // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; lastbit = 1; bStop = false; @@ -1586,38 +1438,27 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // hitagS settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings reset_sof = 4; t_wait = HITAG_T_WAIT_2; - // DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); return; } - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(rx, nbytes(rxlen), response, response, NULL, false); } // By default reset the transmission buffer @@ -1643,9 +1484,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); - - // Dbprintf("DEBUG: Sending reader frame"); + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1656,16 +1495,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); } // Reset values for receiving frames @@ -1675,7 +1505,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { bSkip = true; tag_sof = reset_sof; response = 0; - // Dbprintf("DEBUG: Waiting to receive frame"); uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods @@ -1748,6 +1577,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } // if we saw over 100 wierd values break it probably isn't hitag... if (errorCount > 100) break; + // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) break; @@ -1760,14 +1590,15 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); } } - // Dbprintf("DEBUG: Done waiting for frame"); - LED_B_OFF(); - LED_D_OFF(); + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // Dbprintf("frame received: %d",frame_count); - // DbpString("All done"); + + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); } diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h new file mode 100644 index 000000000..2260e5f8d --- /dev/null +++ b/armsrc/hitag2.h @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// (c) 2012 Roel Verdult +// +// 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. +//----------------------------------------------------------------------------- +// Hitag2 type prototyping +//----------------------------------------------------------------------------- + +#ifndef _HITAG2_H_ +#define _HITAG2_H_ + +#include +#include +#include "hitag.h" + +void SniffHitag(uint32_t type); +void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); +void ReaderHitag(hitag_function htf, hitag_data *htd); +void WriterHitag(hitag_function htf, hitag_data *htd, int page); + +#endif diff --git a/armsrc/hitag2_crypto.c b/armsrc/hitag2_crypto.c new file mode 100644 index 000000000..7d1e10d87 --- /dev/null +++ b/armsrc/hitag2_crypto.c @@ -0,0 +1,116 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// Hitag2 Crypto +// +// (c) 2009 Henryk Plötz +// (c) 2012 Roel Verdult +// (c) 2019 Iceman +//----------------------------------------------------------------------------- +#include "hitag2_crypto.h" + +/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ +// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. +// For educational purposes only. +// No warranties or guarantees of any kind. +// This code is released into the public domain by its author. + +// Single bit Hitag2 functions: +#ifndef i4 +#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +#endif + +static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + +uint32_t _f20(const uint64_t x) { + uint32_t i5; + + i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 + + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 + + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 + + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 + + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; + + return (ht2_f5c >> i5) & 1; +} + +uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) { + uint32_t i; + uint64_t x = ((key & 0xFFFF) << 32) + serial; + + for (i = 0; i < 32; i++) { + x >>= 1; + x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; + } + return x; +} + +uint64_t _hitag2_round(uint64_t *state) { + uint64_t x = *state; + + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) + ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) + ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) + ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); + + *state = x; + return _f20(x); +} + +// "MIKRON" = O N M I K R +// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key +// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear +// Random = 65 6E 45 72 - Random IV, transmitted in clear +//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + +// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". +// The inverse of the first 4 bytes is sent to the tag to authenticate. +// The rest is encrypted by XORing it with the subsequent keystream. + +uint32_t _hitag2_byte(uint64_t *x) { + uint32_t i, c; + for (i = 0, c = 0; i < 8; i++) { + c += (uint32_t) _hitag2_round(x) << (i ^ 7); + } + return c; +} + +void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) { + uint64_t key = ((uint64_t)tag->sectors[2][2]) | + ((uint64_t)tag->sectors[2][3] << 8) | + ((uint64_t)tag->sectors[1][0] << 16) | + ((uint64_t)tag->sectors[1][1] << 24) | + ((uint64_t)tag->sectors[1][2] << 32) | + ((uint64_t)tag->sectors[1][3] << 40); + uint32_t uid = ((uint32_t)tag->sectors[0][0]) | + ((uint32_t)tag->sectors[0][1] << 8) | + ((uint32_t)tag->sectors[0][2] << 16) | + ((uint32_t)tag->sectors[0][3] << 24); + uint32_t iv_ = (((uint32_t)(iv[0]))) | + (((uint32_t)(iv[1])) << 8) | + (((uint32_t)(iv[2])) << 16) | + (((uint32_t)(iv[3])) << 24); + tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_)); +} + +int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) { + uint8_t authenticator_should[4]; + authenticator_should[0] = ~_hitag2_byte(cs); + authenticator_should[1] = ~_hitag2_byte(cs); + authenticator_should[2] = ~_hitag2_byte(cs); + authenticator_should[3] = ~_hitag2_byte(cs); + return (memcmp(authenticator_should, authenticator_is, 4) == 0); +} + +int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) { + int i; + for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs); + for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i); + return 0; +} + diff --git a/armsrc/hitag2_crypto.h b/armsrc/hitag2_crypto.h new file mode 100644 index 000000000..8af1af412 --- /dev/null +++ b/armsrc/hitag2_crypto.h @@ -0,0 +1,36 @@ +#ifndef __HITAG2_CRYPTO_H +#define __HITAG2_CRYPTO_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include "string.h" +#include "util.h" + +struct hitag2_tag { + uint32_t uid; + enum { + TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr + TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password + TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands + TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written + } state; + uint16_t active_sector; + uint8_t crypto_active; + uint64_t cs; + uint8_t sectors[12][4]; +}; + +extern uint32_t _f20(const uint64_t x); +extern uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV); +extern uint64_t _hitag2_round(uint64_t *state); +extern uint32_t _hitag2_byte(uint64_t *x); +extern void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv); +extern int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is); +extern int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ; +#ifdef __cplusplus +} +#endif + +#endif diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index b53112081..5fece9d26 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -10,109 +10,46 @@ //----------------------------------------------------------------------------- // Some code was copied from Hitag2.c //----------------------------------------------------------------------------- -#include -#include "proxmark3.h" -#include "apps.h" -#include "util.h" + #include "hitagS.h" -#include "hitag2.h" -#include "string.h" -#include "BigBuf.h" #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) - static bool bQuiet; static bool bSuccessful; static struct hitagS_tag tag; static byte_t page_to_be_written = 0; static int block_data_left = 0; + typedef enum modulation { AC2K = 0, AC4K, MC4K, MC8K } MOD; -static MOD m = AC2K; //used modulation + +static MOD m = AC2K; // used modulation static uint32_t temp_uid; static int temp2 = 0; -static int sof_bits; //number of start-of-frame bits -static byte_t pwdh0, pwdl0, pwdl1; //password bytes -static uint32_t rnd = 0x74124485; //randomnumber +static int sof_bits; // number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; // password bytes +static uint32_t rnd = 0x74124485; // randomnumber static int test = 0; size_t blocknr; bool end = false; -// Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 #define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) #define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) #define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) -#define uf20bs u32 - -static u32 f20(const u64 x) { - u32 i5; - - i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 - + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 - + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 - + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 - + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; - - return (ht2_f5c >> i5) & 1; -} -static u64 hitag2_round(u64 *state) { - u64 x = *state; - - x = (x >> 1) - + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) - ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) - ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) - & 1) << 47); - - *state = x; - return f20(x); -} -static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; - for (i = 0; i < 32; i++) { - x >>= 1; - x += (u64)(f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; - } - return x; -} -static u32 hitag2_byte(u64 *x) { - u32 i, c; - - for (i = 0, c = 0; i < 8; i++) - c += (u32) hitag2_round(x) << (i ^ 7); - return c; -} // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 +#ifndef T0 #define T0 192 - -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#endif #define HITAG_FRAME_LEN 20 #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ @@ -258,100 +195,85 @@ static void hitag_send_bit(int bit) { } } -static void hitag_send_frame(const byte_t *frame, size_t frame_len) { -// Send start of frame - +static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { + // SOF - send start of frame for (size_t i = 0; i < sof_bits; i++) { hitag_send_bit(1); } -// Send the content of the frame + // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } -// Drop the modulation + LOW(GPIO_SSC_DOUT); } static void hitag_reader_send_bit(int bit) { -//Dbprintf("BIT: %d",bit); + LED_A_ON(); -// Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; -// Binary puls length modulation (BPLM) is used to encode the data stream -// This means that a transmission of a one takes longer than that of a zero + // Binary puls length modulation (BPLM) is used to encode the data stream + // This means that a transmission of a one takes longer than that of a zero -// Enable modulation, which means, drop the the field HIGH(GPIO_SSC_DOUT); + if (test == 1) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); - - // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; - - // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; - - // SpinDelayUs(22*8); } } else { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); - - // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - - // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; - - // SpinDelayUs(22*8); } } LED_A_OFF(); } -static void hitag_reader_send_frame(const byte_t *frame, size_t frame_len) { -// Send the content of the frame +static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { + // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { - if (frame[0] == 0xf8) { - //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); - } +// if (frame[0] == 0xf8) { + //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); +// } hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } -// Send EOF + // send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; -// Enable modulation, which means, drop the the field + HIGH(GPIO_SSC_DOUT); -// Wait for 4-10 times the carrier period + + // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; -// Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); } /* * to check if the right uid was selected */ -static int check_select(byte_t *rx, uint32_t uid) { +static int check_select(uint8_t *rx, uint32_t uid) { unsigned char resp[48]; int i; uint32_t ans = 0x0; @@ -359,31 +281,32 @@ static int check_select(byte_t *rx, uint32_t uid) { resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; for (i = 0; i < 32; i++) ans += resp[5 + i] << (31 - i); - /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 - && rx[4] == 0x65 && rx[5] == 0x38) - Dbprintf("got uid %X", ans);*/ + temp_uid = ans; if (ans == tag.uid) return 1; + return 0; } /* * handles all commands from a reader */ -static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, - byte_t *tx, size_t *txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; - byte_t page; +static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, + uint8_t *tx, size_t *txlen) { + uint8_t rx_air[HITAG_FRAME_LEN]; + uint8_t page; int i; - u64 state; + uint64_t state; unsigned char crc; -// Copy the (original) received frame how it is send over the air + // Copy the (original) received frame how it is send over the air memcpy(rx_air, rx, nbytes(rxlen)); -// Reset the transmission frame length + + // Reset the transmission frame length *txlen = 0; -// Try to find out which command was send by selecting on length (in bits) + + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { case 5: { //UID request with a selected response protocol mode @@ -452,11 +375,13 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, Dbprintf("Challenge for UID: %X", temp_uid); temp2++; *txlen = 32; - state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), - rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); - Dbprintf( - ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", - rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + state = _hitag2_init(REV64(tag.key), + REV32(tag.pages[0][0]), + REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])) + ); + Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", + rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + switch (tag.mode) { case HT_STANDARD: sof_bits = 1; @@ -475,12 +400,13 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, } for (i = 0; i < 4; i++) - hitag2_byte(&state); - //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response - tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); - tx[1] = hitag2_byte(&state) ^ tag.pwdh0; - tx[2] = hitag2_byte(&state) ^ tag.pwdl0; - tx[3] = hitag2_byte(&state) ^ tag.pwdl1; + _hitag2_byte(&state); + + //send con2, pwdh0, pwdl0, pwdl1 encrypted as a response + tx[0] = _hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); + tx[1] = _hitag2_byte(&state) ^ tag.pwdh0; + tx[2] = _hitag2_byte(&state) ^ tag.pwdl0; + tx[3] = _hitag2_byte(&state) ^ tag.pwdl1; if (tag.mode != HT_STANDARD) { //add crc8 *txlen = 40; @@ -489,14 +415,12 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, calc_crc(&crc, tag.pwdh0, 8); calc_crc(&crc, tag.pwdl0, 8); calc_crc(&crc, tag.pwdl1, 8); - tx[4] = (crc ^ hitag2_byte(&state)); + tx[4] = (crc ^ _hitag2_byte(&state)); } /* * some readers do not allow to authenticate multiple times in a row with the same tag. * use this to change the uid between authentications. - */ - /* if (temp2 % 2 == 0) { tag.uid = 0x11223344; tag.pages[0][0] = 0x44332211; @@ -720,18 +644,17 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, /* * to autenticate to a tag with the given key or challenge */ -static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, byte_t *rx, const size_t rxlen, byte_t *tx, - size_t *txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; +static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { + uint8_t rx_air[HITAG_FRAME_LEN]; int response_bit[200]; int i, j, z, k; unsigned char mask = 1; unsigned char uid[32]; - byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; + uint8_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; unsigned char crc; - u64 state; - byte_t auth_ks[4]; - byte_t conf_pages[3]; + uint64_t state; + uint8_t auth_ks[4]; + uint8_t conf_pages[3]; memcpy(rx_air, rx, nbytes(rxlen)); *txlen = 0; @@ -757,16 +680,45 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA if (k > 31) break; } - uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) - | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; - uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) - | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; - uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) - | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; - uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) - | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; + uid1 = (uid[0] << 7) + | (uid[1] << 6) + | (uid[2] << 5) + | (uid[3] << 4) + | (uid[4] << 3) + | (uid[5] << 2) + | (uid[6] << 1) + | uid[7]; + + uid2 = (uid[8] << 7) + | (uid[9] << 6) + | (uid[10] << 5) + | (uid[11] << 4) + | (uid[12] << 3) + | (uid[13] << 2) + | (uid[14] << 1) + | uid[15]; + + uid3 = (uid[16] << 7) + | (uid[17] << 6) + | (uid[18] << 5) + | (uid[19] << 4) + | (uid[20] << 3) + | (uid[21] << 2) + | (uid[22] << 1) + | uid[23]; + + uid4 = (uid[24] << 7) + | (uid[25] << 6) + | (uid[26] << 5) + | (uid[27] << 4) + | (uid[28] << 3) + | (uid[29] << 2) + | (uid[30] << 1) + | uid[31]; + if (DEBUG) Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); + tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); //select uid @@ -777,29 +729,40 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA calc_crc(&crc, uid2, 8); calc_crc(&crc, uid3, 8); calc_crc(&crc, uid4, 8); + for (i = 0; i < 100; i++) { response_bit[i] = 0; } + for (i = 0; i < 5; i++) { response_bit[i] = 0; } + for (i = 5; i < 37; i++) { response_bit[i] = uid[i - 5]; } + for (j = 0; j < 8; j++) { response_bit[i] = 0; if ((crc & ((mask << 7) >> j)) != 0) response_bit[i] = 1; i++; } + k = 0; for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) | response_bit[k + 7]; + tx[i] = (response_bit[k] << 7) + | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) + | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) + | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) + | response_bit[k + 7]; + k += 8; } + tag.pstate = HT_INIT; } else if (tag.pstate == HT_INIT && rxlen == 44) { // received configuration after select command @@ -847,18 +810,17 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA tag.LCK0 = response_bit[27]; if (DEBUG) - Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], - conf_pages[1], conf_pages[2]); + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); + if (tag.auth == 1) { //if the tag is in authentication mode try the key or challenge *txlen = 64; if (end != true) { if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY - state = hitag2_init(rev64(key), rev32(tag.uid), - rev32(rnd)); + state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); for (i = 0; i < 4; i++) { - auth_ks[i] = hitag2_byte(&state) ^ 0xff; + auth_ks[i] = _hitag2_byte(&state) ^ 0xff; } *txlen = 64; tx[0] = rnd & 0xff; @@ -906,21 +868,18 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA pwdl1 = 0; if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY { - state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); + state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); for (i = 0; i < 5; i++) - hitag2_byte(&state); - pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) - ^ hitag2_byte(&state); + _hitag2_byte(&state); + + pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) ^ _hitag2_byte(&state); + pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) ^ _hitag2_byte(&state); + pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state); } if (DEBUG) Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); - //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); //rnd += 1; } @@ -933,18 +892,22 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA /* * Emulates a Hitag S Tag with the given data from the .hts file */ -void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { - int frame_count; - int response; - int overflow; +void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { + + StopTicks(); + + int frame_count = 0, response = 0, overflow = 0; int i, j; - byte_t rx[HITAG_FRAME_LEN]; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - //bool bQuitTraceFull = false; bQuiet = false; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; + + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); @@ -958,16 +921,18 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { tag.pstate = HT_READY; tag.tstate = HT_NO_OP; + for (i = 0; i < 16; i++) for (j = 0; j < 4; j++) tag.pages[i][j] = 0x0; - //read tag data into memory + + // read tag data into memory if (tag_mem_supplied) { DbpString("Loading hitagS memory..."); - memcpy((byte_t *)tag.pages, data, 4 * 64); + memcpy((uint8_t *)tag.pages, data, 4 * 64); } + tag.uid = (uint32_t)tag.pages[0]; - Dbprintf("Hitag S simulation started"); tag.key = (intptr_t)tag.pages[3]; tag.key <<= 16; tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1]; @@ -1017,48 +982,48 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { if ((tag.pages[1][1] & 0x1) == 0x01) tag.LCK0 = 1; -// Set up simulator mode, frequency divisor which will drive the FPGA -// and analog mux selection. + // Set up simulator mode, frequency divisor which will drive the FPGA + // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(20); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Configure output pin that is connected to the FPGA (for modulating) + // Configure output pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Disable modulation at default, which means release resistance + // Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); -// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on rising edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; -// Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; - -// Enable and reset counter + // Enable and reset counter + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (!BUTTON_PRESS()) { - // Watchdog hit + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero + + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Receive frame, watch for at most T0*EOF periods @@ -1098,12 +1063,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // Check if frame was captured if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, true)) { - DbpString("Trace full"); - clear_trace(); - } - } + LogTrace(rx, nbytes(rxlen), response, 0, NULL, true); // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1116,20 +1076,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) // periods. The gap time T_Low varies (4..10). All timer values are in // terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) {}; // Send and store the tag answer (if there is any) if (txlen > 0) { // Transmit the tag frame hitag_send_frame(tx, txlen); - // Store the frame in the trace - if (!bQuiet) { - if (!LogTraceHitag(tx, txlen, 0, 0, false)) { - DbpString("Trace full"); - clear_trace(); - } - } + LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); } // Reset the received frame and response timing info @@ -1147,11 +1100,19 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + // release allocated memory from BigBuff. + BigBuf_free(); + + StartTicks(); + + DbpString("Sim Stopped"); } /* @@ -1160,22 +1121,23 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { * Reads every page of a hitag S transpoder. */ void ReadHitagS(hitag_function htf, hitag_data *htd) { + + StopTicks(); + int i, j, z, k; - int frame_count; + int frame_count = 0, response = 0; int response_bit[200]; - int response; - byte_t rx[HITAG_FRAME_LEN]; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; - int lastbit; + int lastbit = 1; bool bSkip; - int reset_sof; + int reset_sof = 1; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; - bool bQuitTraceFull = false; int sendNum = 0; unsigned char mask = 1; unsigned char crc; @@ -1183,31 +1145,31 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { page_to_be_written = 0; //read given key/challenge - byte_t NrAr_[8]; + uint8_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - byte_t key_[6]; + uint8_t key_[6]; + switch (htf) { - case 01: { //RHTS_CHALLENGE + case RHTSF_CHALLENGE: { DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + break; } - break; - case 02: { //RHTS_KEY + case RHTSF_KEY: { DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + break; } - break; default: { Dbprintf("Error , unknown function: %d", htf); return; } - break; } FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1219,40 +1181,36 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { clear_trace(); bQuiet = false; - bQuitTraceFull = true; LED_D_ON(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - - // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | @@ -1264,32 +1222,20 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - reset_sof = 1; + // Reset the received frame, frame count and timing info t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); } // By default reset the transmission buffer @@ -1299,13 +1245,14 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { if (rxlen == 0) { //start authentication txlen = 5; - memcpy(tx, "\xc0", nbytes(txlen)); + memcpy(tx, "\xC0", nbytes(txlen)); tag.pstate = HT_READY; tag.tstate = HT_NO_OP; } else if (tag.pstate != HT_SELECTED) { if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1) bStop = !false; } + if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { //send read request tag.tstate = HT_READING_PAGE; @@ -1316,7 +1263,8 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE + } else if (tag.pstate == HT_SELECTED + && tag.tstate == HT_READING_PAGE && rxlen > 0) { //save received data z = 0; @@ -1361,15 +1309,19 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { sendNum++; //display key and password if possible if (sendNum == 2 && tag.auth == 1 && tag.LKP) { - if (htf == 02) { //RHTS_KEY + if (htf == RHTSF_KEY) { Dbprintf("Page[ 2]: %02X %02X %02X %02X", - (byte_t)(key >> 8) & 0xff, - (byte_t) key & 0xff, pwdl1, pwdl0); + (uint8_t)(key >> 8) & 0xff, + (uint8_t) key & 0xff, + pwdl1, + pwdl0 + ); Dbprintf("Page[ 3]: %02X %02X %02X %02X", - (byte_t)(key >> 40) & 0xff, - (byte_t)(key >> 32) & 0xff, - (byte_t)(key >> 24) & 0xff, - (byte_t)(key >> 16) & 0xff); + (uint8_t)(key >> 40) & 0xff, + (uint8_t)(key >> 32) & 0xff, + (uint8_t)(key >> 24) & 0xff, + (uint8_t)(key >> 16) & 0xff + ); } else { //if the authentication is done with a challenge the key and password are unknown Dbprintf("Page[ 2]: __ __ __ __"); @@ -1410,17 +1362,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } // Reset values for receiving frames @@ -1491,12 +1433,17 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } } end = false; - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1505,12 +1452,14 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { * Writes the given 32Bit data into page_ */ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; + + StopTicks(); + + int frame_count = 0, response = 0; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1518,124 +1467,106 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; - bool bQuitTraceFull = false; int page = page_; unsigned char crc; - byte_t data[4] = {0, 0, 0, 0}; + uint8_t data[4] = {0, 0, 0, 0}; + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + bSuccessful = false; + + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); //read given key/challenge, the page and the data - byte_t NrAr_[8]; + uint8_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - byte_t key_[6]; + uint8_t key_[6]; switch (htf) { - case 03: { //WHTS_CHALLENGE + case WHTSF_CHALLENGE: { memcpy(data, htd->auth.data, 4); DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + break; } - break; - case 04: { //WHTS_KEY + + case WHTSF_KEY: { memcpy(data, htd->crypto.data, 4); DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + break; } - break; default: { Dbprintf("Error , unknown function: %d", htf); return; } - break; } Dbprintf("Page: %d", page_); Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status - bSuccessful = false; tag.pstate = HT_READY; tag.tstate = HT_NO_OP; -// Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); - - bQuiet = false; - bQuitTraceFull = true; - LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - -// Set Frequency divisor which will drive the FPGA and analog mux selection + // Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - -// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; -// Enable and reset counters + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; -// Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; + while (AT91C_BASE_TC0->TC_CV > 0); + + // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); } //check for valid input @@ -1711,9 +1642,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1724,17 +1653,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } // Reset values for receiving frames @@ -1744,6 +1663,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { bSkip = true; tag_sof = reset_sof; response = 0; + uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { @@ -1794,9 +1714,13 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } else { // Ignore wierd value, is to small to mean anything + errorCount++; } } + // if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount > 100) break; + // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) @@ -1805,11 +1729,15 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } end = false; - LED_B_OFF(); - LED_D_OFF(); + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1820,17 +1748,16 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { * is not received correctly due to Antenna problems. This function * detects these challenges. */ -void check_challenges(bool file_given, byte_t *data) { +void check_challenges(bool file_given, uint8_t *data) { int i, j, z, k; - byte_t uid_byte[4]; - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; - byte_t unlocker[60][8]; + uint8_t uid_byte[4]; + int frame_count = 0, response = 0; + uint8_t rx[HITAG_FRAME_LEN]; + uint8_t unlocker[60][8]; int u1 = 0; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1839,76 +1766,71 @@ void check_challenges(bool file_given, byte_t *data) { int t_wait = HITAG_T_WAIT_MAX; int STATE = 0; bool bStop; - bool bQuitTraceFull = false; int response_bit[200]; unsigned char mask = 1; unsigned char uid[32]; unsigned char crc; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status + // Reset the return status bSuccessful = false; -// Clean up trace and prepare it for storing frames + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); bQuiet = false; - bQuitTraceFull = true; LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - SpinDelay(50); - -// Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - -// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG + | AT91C_TC_LDRA_FALLING; - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - -// Enable and reset counters + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; -// Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; + while (AT91C_BASE_TC0->TC_CV > 0) {}; + + // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; if (file_given) { DbpString("Loading challenges..."); - memcpy((byte_t *)unlocker, data, 60 * 8); + memcpy((uint8_t *)unlocker, data, 60 * 8); } while (file_given && !bStop && !BUTTON_PRESS()) { @@ -1918,16 +1840,7 @@ void check_challenges(bool file_given, byte_t *data) { // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); } tx = txbuf; @@ -1943,7 +1856,7 @@ void check_challenges(bool file_given, byte_t *data) { STATE = 0; txlen = 5; //start new authentication - memcpy(tx, "\xc0", nbytes(txlen)); + memcpy(tx, "\xC0", nbytes(txlen)); } else if (rxlen >= 67 && STATE == 0) { //received uid z = 0; @@ -2043,9 +1956,7 @@ void check_challenges(bool file_given, byte_t *data) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -2056,17 +1967,7 @@ void check_challenges(bool file_given, byte_t *data) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); } // Reset values for receiving frames @@ -2136,11 +2037,16 @@ void check_challenges(bool file_given, byte_t *data) { } } } - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h new file mode 100644 index 000000000..49a885c4c --- /dev/null +++ b/armsrc/hitagS.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// HitagS emulation (preliminary test version) +// +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + +#ifndef _HITAGS_H_ +#define _HITAGS_H_ + +#include +#include +#include +#include "hitag2_crypto.h" +#include "hitag.h" +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" +#include "BigBuf.h" + +void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data); +void ReadHitagS(hitag_function htf, hitag_data *htd); +void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); +void check_challenges(bool file_given, uint8_t *data); + +#endif diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 7bd725eab..1326306b1 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -18,7 +18,7 @@ // // FIX: // ==== -// We still have sometimes a demodulation error when snooping iClass communication. +// We still have sometimes a demodulation error when sniffing iClass communication. // The resulting trace of a read-block-03 command may look something like this: // // + 22279: : 0c 03 e8 01 @@ -2456,4 +2456,4 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); switch_off(); -} \ No newline at end of file +} diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a22a79390..023eb02f9 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2747,7 +2747,7 @@ void DetectNACKbug() { bool received_nack; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). - uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; + int32_t sync_cycles = PRNG_SEQUENCE_LENGTH; BigBuf_free(); BigBuf_Clear_ext(false); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 5b6a85477..5d988459b 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1413,7 +1413,7 @@ static void iso1444b_setup_sniff(void) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace();//setup snoop + clear_trace(); set_tracing(true); // Initialize Demod and Uart structs @@ -1570,6 +1570,7 @@ void iso14b_set_trigger(bool enable) { void SendRawCommand14443B_Ex(UsbCommand *c) { iso14b_command_t param = c->arg[0]; size_t len = c->arg[1] & 0xffff; + uint32_t timeout = c->arg[2]; uint8_t *cmd = c->d.asBytes; uint8_t status = 0; uint32_t sendlen = sizeof(iso14b_card_select_t); @@ -1586,6 +1587,9 @@ void SendRawCommand14443B_Ex(UsbCommand *c) { clear_trace(); } + if ((param & ISO14B_SET_TIMEOUT)) + iso14b_set_timeout(timeout); + set_tracing(true); if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { @@ -1634,4 +1638,4 @@ out: switch_off(); // disconnect raw SpinDelay(20); } -} \ No newline at end of file +} diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index b6d53ccea..12e9cc815 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -621,8 +621,8 @@ void Iso15693InitReader(void) { // Encode (into the ToSend buffers) an identify request, which is the first // thing that you must send to a tag to get a response. +// It expects "out" to be at least CMD_ID_RESP large static void BuildIdentifyRequest(uint8_t *out) { - uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; // flags cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; @@ -665,6 +665,7 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb */ // Now the VICC>VCD responses when we are simulating a tag +// It expects "out" to be at least CMD_INV_RESP large static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -686,7 +687,7 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { // CRC AddCrc(cmd, 10); CodeIso15693AsReader(cmd, CMD_INV_RESP); - memcpy(out, cmd, CMD_ID_RESP); + memcpy(out, cmd, CMD_INV_RESP); } // Universal Method for sending to and recv bytes from a tag @@ -739,50 +740,50 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { if (len > 3) { if (d[0] & (1 << 3)) - strncat(status, "ProtExt ", DBD15STATLEN); + strncat(status, "ProtExt ", DBD15STATLEN - strlen(status)); if (d[0] & 1) { // error - strncat(status, "Error ", DBD15STATLEN); + strncat(status, "Error ", DBD15STATLEN - strlen(status)); switch (d[1]) { case 0x01: - strncat(status, "01: not supported", DBD15STATLEN); + strncat(status, "01: not supported", DBD15STATLEN - strlen(status)); break; case 0x02: - strncat(status, "02: not recognized", DBD15STATLEN); + strncat(status, "02: not recognized", DBD15STATLEN - strlen(status)); break; case 0x03: - strncat(status, "03: opt not supported", DBD15STATLEN); + strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status)); break; case 0x0f: - strncat(status, "0F: no info", DBD15STATLEN); + strncat(status, "0F: no info", DBD15STATLEN - strlen(status)); break; case 0x10: - strncat(status, "10: dont exist", DBD15STATLEN); + strncat(status, "10: dont exist", DBD15STATLEN - strlen(status)); break; case 0x11: - strncat(status, "11: lock again", DBD15STATLEN); + strncat(status, "11: lock again", DBD15STATLEN - strlen(status)); break; case 0x12: - strncat(status, "12: locked", DBD15STATLEN); + strncat(status, "12: locked", DBD15STATLEN - strlen(status)); break; case 0x13: - strncat(status, "13: program error", DBD15STATLEN); + strncat(status, "13: program error", DBD15STATLEN - strlen(status)); break; case 0x14: - strncat(status, "14: lock error", DBD15STATLEN); + strncat(status, "14: lock error", DBD15STATLEN - strlen(status)); break; default: - strncat(status, "unknown error", DBD15STATLEN); + strncat(status, "unknown error", DBD15STATLEN - strlen(status)); } - strncat(status, " ", DBD15STATLEN); + strncat(status, " ", DBD15STATLEN - strlen(status)); } else { - strncat(status, "No error ", DBD15STATLEN); + strncat(status, "No error ", DBD15STATLEN - strlen(status)); } if (CheckCrc(d, len)) - strncat(status, "[+] crc OK", DBD15STATLEN); + strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status)); else - strncat(status, "[!] crc fail", DBD15STATLEN); + strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status)); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); } @@ -999,4 +1000,4 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint } else { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); } -} \ No newline at end of file +} diff --git a/armsrc/lfops.c b/armsrc/lfops.c index ac9f08ed3..a40e5e977 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -21,13 +21,6 @@ #include "common.h" #include "flashmem.h" // persistence on mem -#ifndef SHORT_COIL -# define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#endif -#ifndef OPEN_COIL -# define OPEN_COIL() HIGH(GPIO_SSC_DOUT) -#endif - //#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) //#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) //#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) @@ -317,7 +310,7 @@ void ReadTItag(void) { // expected for either the low or high frequency if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) { // low frequency represents a 1 - shift3 |= (1 << 31); + shift3 |= (1u << 31); } else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) { // high frequency represents a 0 } else { @@ -481,7 +474,7 @@ void AcquireTiType(void) { // unpack buffer for (i = TIBUFLEN - 1; i >= 0; i--) { for (j = 0; j < 32; j++) { - if (buf[i] & (1 << j)) { + if (buf[i] & (1u << j)) { dest[--n] = 1; } else { dest[--n] = -1; @@ -730,8 +723,6 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { uint8_t halfFC = fc >> 1; uint8_t wavesPerClock = clock / fc; uint8_t mod = clock % fc; //modifier - uint8_t modAdj = fc / mod; //how often to apply modifier - bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; // loop through clock - step field clock for (uint8_t idx = 0; idx < wavesPerClock; idx++) { @@ -740,19 +731,23 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { memset(dest + (*n) + (fc - halfFC), 1, halfFC); *n += fc; } - if (mod > 0)(*modCnt)++; + if (mod > 0) { + uint8_t modAdj = fc / mod; //how often to apply modifier + bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; + (*modCnt)++; - if ((mod > 0) && modAdjOk) { //fsk2 - if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave - memset(dest + (*n), 0, fc - halfFC); - memset(dest + (*n) + (fc - halfFC), 1, halfFC); - *n += fc; + if (modAdjOk) { //fsk2 + if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave + memset(dest + (*n), 0, fc - halfFC); + memset(dest + (*n) + (fc - halfFC), 1, halfFC); + *n += fc; + } + } + if (!modAdjOk) { //fsk1 + memset(dest + (*n), 0, mod - (mod >> 1)); + memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); + *n += mod; } - } - if (mod > 0 && !modAdjOk) { //fsk1 - memset(dest + (*n), 0, mod - (mod >> 1)); - memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); - *n += mod; } } @@ -829,7 +824,7 @@ void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol) { // prepare a waveform pattern in the buffer based on the ID given then // simulate a FSK tag until the button is pressed // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock -void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { +void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // free eventually allocated BigBuf memory @@ -838,7 +833,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { clear_trace(); set_tracing(false); - int ledcontrol = 1, n = 0, i = 0; + int n = 0, i = 0; uint8_t fcHigh = arg1 >> 8; uint8_t fcLow = arg1 & 0xFF; uint16_t modCnt = 0; @@ -906,11 +901,11 @@ static void stAskSimBit(int *n, uint8_t clock) { } // args clock, ask/man or askraw, invert, transmission separator -void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { +void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - int ledcontrol = 1, n = 0, i = 0; + int n = 0, i = 0; uint8_t clk = (arg1 >> 8) & 0xFF; uint8_t encoding = arg1 & 0xFF; uint8_t separator = arg2 & 1; @@ -973,11 +968,11 @@ static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, b } // args clock, carrier, invert, -void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { +void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - int ledcontrol = 1, n = 0, i = 0; + int n = 0, i = 0; uint8_t clk = arg1 >> 8; uint8_t carrier = arg1 & 0xFF; uint8_t invert = arg2 & 0xFF; @@ -1066,12 +1061,8 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) } } else { //if bit 38 is not set then 37 bit format is used bitlen = 37; - fc = 0; - cardnum = 0; - if (bitlen == 37) { - cardnum = (lo >> 1) & 0x7FFFF; - fc = ((hi & 0xF) << 12) | (lo >> 20); - } + cardnum = (lo >> 1) & 0x7FFFF; + fc = ((hi & 0xF) << 12) | (lo >> 20); } Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", hi, @@ -1382,8 +1373,6 @@ void T55xxResetRead(void) { //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); - StartTicks(); - // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... @@ -1416,8 +1405,6 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) bool testMode = arg & 0x4; uint32_t i = 0; - StartTicks(); - // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1491,7 +1478,7 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { // Read one card block in page [page] void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { LED_A_ON(); - bool PwdMode = arg0 & 0x1; + bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; bool brute_mem = arg0 & 0x4; @@ -1513,8 +1500,6 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { //make sure block is at max 7 Block &= 0x7; - StartTicks(); - // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... @@ -1591,26 +1576,23 @@ void T55xx_ChkPwds() { uint32_t candidate = 0; #ifdef WITH_FLASH - bool use_flashmem = true; - if (use_flashmem) { - BigBuf_Clear_EM(); - uint16_t isok = 0; - uint8_t counter[2] = {0x00, 0x00}; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter)); - if (isok != sizeof(counter)) - goto OUT; + BigBuf_Clear_EM(); + uint16_t isok = 0; + uint8_t counter[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter)); + if (isok != sizeof(counter)) + goto OUT; - pwdCount = counter[1] << 8 | counter[0]; + pwdCount = counter[1] << 8 | counter[0]; - if (pwdCount == 0 && pwdCount == 0xFFFF) - goto OUT; + if (pwdCount == 0 || pwdCount == 0xFFFF) + goto OUT; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4); - if (isok != pwdCount * 4) - goto OUT; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4); + if (isok != pwdCount * 4) + goto OUT; - Dbprintf("[=] Password dictionary count %d ", pwdCount); - } + Dbprintf("[=] Password dictionary count %d ", pwdCount); #endif uint32_t pwd = 0, curr = 0, prev = 0; @@ -1661,8 +1643,6 @@ void T55xxWakeUp(uint32_t Pwd) { LED_B_ON(); uint32_t i = 0; - StartTicks(); - // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 53b8e75b3..7018fbae2 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -29,7 +29,7 @@ void printConfig() { /** * Called from the USB-handler to set the sampling configuration - * The sampling config is used for std reading and snooping. + * The sampling config is used for std reading and sniffing. * * Other functions may read samples and ignore the sampling config, * such as functions to read the UID from a prox tag or similar. @@ -239,9 +239,9 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { if (!silent) printConfig(); LFSetupFPGAForADC(config.divisor, activeField); - uint32_t ret = DoAcquisition_config(silent, sample_size); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + uint32_t ret = DoAcquisition_config(silent, sample_size); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** @@ -250,15 +250,15 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { **/ uint32_t SampleLF(bool printCfg, int sample_size) { BigBuf_Clear_ext(false); - return ReadLF(true, printCfg, sample_size); + return ReadLF(true, printCfg, sample_size); } /** -* Initializes the FPGA for snoop-mode (field off), and acquires the samples. +* Initializes the FPGA for sniffer-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SnoopLF() { +uint32_t SniffLF() { BigBuf_Clear_ext(false); - return ReadLF(false, true, 0); + return ReadLF(false, true, 0); } /** @@ -427,12 +427,10 @@ uint32_t doCotagAcquisitionManchester() { if (sample > COTAG_ONE_THRESHOLD) { prev = curr; curr = 1; - } - else if ( sample < COTAG_ZERO_THRESHOLD) { + } else if (sample < COTAG_ZERO_THRESHOLD) { prev = curr; curr = 0; - } - else { + } else { curr = prev; } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 94c370ed9..8556cd327 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -30,10 +30,10 @@ void doT55x7Acquisition(size_t sample_size); uint32_t SampleLF(bool silent, int sample_size); /** -* Initializes the FPGA for snoop-mode (field off), and acquires the samples. +* Initializes the FPGA for sniff-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SnoopLF(); +uint32_t SniffLF(); // adds sample size to default options uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after); @@ -67,7 +67,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field); /** * Called from the USB-handler to set the sampling configuration - * The sampling config is used for std reading and snooping. + * The sampling config is used for std reading and sniffing. * * Other functions may read samples and ignore the sampling config, * such as functions to read the UID from a prox tag or similar. diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 1f1932e27..9e771679b 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1247,7 +1247,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da keyCount = size[1] << 8 | size[0]; - if (keyCount == 0 && keyCount == 0xFFFF) + if (keyCount == 0 || keyCount == 0xFFFF) goto OUT; datain = BigBuf_malloc(keyCount * 6); @@ -2098,4 +2098,4 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(false); -} \ No newline at end of file +} diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 595d46395..51ed76ca5 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -25,4 +25,4 @@ #include "crc.h" #include "protocols.h" #include "parity.h" -#endif \ No newline at end of file +#endif diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 8f391207e..0e75aac35 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -322,4 +322,4 @@ void RAMFUNC MfSniffSend() { LED_B_ON(); cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. LED_B_OFF(); -} \ No newline at end of file +} diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index debfd5a09..9b5cb8609 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -39,4 +39,4 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui void RAMFUNC MfSniffSend(void); void MfSniffEnd(void); -#endif \ No newline at end of file +#endif diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index ef371b233..90a6f5d64 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -518,4 +518,4 @@ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) { tab[u + 2] = c + tab[u + 1]; return 0; -} \ No newline at end of file +} diff --git a/armsrc/pcf7931.h b/armsrc/pcf7931.h index bed33dadc..b8121c29f 100644 --- a/armsrc/pcf7931.h +++ b/armsrc/pcf7931.h @@ -17,4 +17,4 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p); bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab); void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data); -#endif \ No newline at end of file +#endif diff --git a/armsrc/start.c b/armsrc/start.c index a6503f1ea..b5947bdf3 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -77,4 +77,4 @@ void __attribute__((section(".startos"))) Vector(void) { AppMain(); } -#endif \ No newline at end of file +#endif diff --git a/armsrc/string.h b/armsrc/string.h index de8f3ac20..f6f094c48 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -24,4 +24,4 @@ char *strcat(char *dest, const char *src); void strreverse(char s[]); void itoa(int n, char s[]); -#endif /* __STRING_H */ \ No newline at end of file +#endif /* __STRING_H */ diff --git a/armsrc/ticks.h b/armsrc/ticks.h index 6e5e334f0..d24d2aac5 100644 --- a/armsrc/ticks.h +++ b/armsrc/ticks.h @@ -44,4 +44,4 @@ extern void WaitUS(uint16_t us); extern void WaitMS(uint16_t ms); extern void StopTicks(void); -#endif \ No newline at end of file +#endif diff --git a/armsrc/util.h b/armsrc/util.h index 19b104f51..15f93d1f9 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -17,7 +17,18 @@ #include "BigBuf.h" #include "ticks.h" +// Basic macros +#ifndef SHORT_COIL +#define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#endif + +#ifndef OPEN_COIL +#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#endif + +#ifndef BYTEx #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) +#endif #define LED_RED 1 #define LED_ORANGE 2 @@ -43,6 +54,34 @@ # define NTIME(n) for (int _index = 0; _index < n; _index++) #endif +#ifndef REV8 +#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#endif + +#ifndef REV16 +#define REV16(x) (REV8(x) + (REV8 (x >> 8) << 8)) +#endif + +#ifndef REV32 +#define REV32(x) (REV16(x) + (REV16(x >> 16) << 16)) +#endif + +#ifndef REV64 +#define REV64(x) (REV32(x) + (REV32(x >> 32) << 32)) +#endif + +#ifndef BIT32 +#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#endif + +#ifndef INV32 +#define INV32(x,i,n) ((x)[(i)>>5]^=((uint32_t)(n))<<((i)&31)) +#endif + +#ifndef ROTL64 +#define ROTL64(x, n) ((((uint64_t)(x))<<((n)&63))+(((uint64_t)(x))>>((0-(n))&63))) +#endif + size_t nbytes(size_t nbits); extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index a687cb0b1..78c8f4d1e 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -8,7 +8,7 @@ #include #include #include -#include "../loclass/fileutil.h" +#include "../loclass/fileutils.h" #define NTAG215_SIZE 540 diff --git a/client/cli.c b/client/cli.c index 19e472586..270689732 100644 --- a/client/cli.c +++ b/client/cli.c @@ -21,7 +21,7 @@ int main(int argc, char **argv) { if (argc != 3 && argc != 4) { printf("\n\tusage: cli [logfile (default cli.log)]\n"); printf("\n"); - printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); + printf("\texample: cli hf 14a sniff hf 14a list h14a.log\n"); printf("\n"); return -1; } diff --git a/client/cmdcrc.c b/client/cmdcrc.c index 1a17d1428..be74fc39a 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -483,4 +483,4 @@ int CmdrevengSearch(const char *Cmd) { if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); return 1; -} \ No newline at end of file +} diff --git a/client/cmddata.c b/client/cmddata.c index 5aeaca388..aa44611ed 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -417,18 +417,16 @@ int CmdPrintDemodBuff(const char *Cmd) { return 0; } length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length; - int numBits = (length) & 0x00FFC; //make sure we don't exceed our string if (hexMode) { char *buf = (char *)(DemodBuffer + offset); - numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; - numBits = binarraytohex(hex, buf, numBits); + int numBits = binarraytohex(hex, sizeof(hex), buf, length); if (numBits == 0) { return 0; } PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); } else { - PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, numBits, 16)); + PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 16)); } return 1; } @@ -475,14 +473,15 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, size_t BitLen = getFromGraphBuf(bits); - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %d", BitLen); if (BitLen < 255) return 0; if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; int foundclk = 0; - //amp before ST check + + //amplify signal before ST check if (amp == 'a') askAmp(bits, BitLen); @@ -496,8 +495,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, clk = (clk == 0) ? foundclk : clk; CursorCPos = ststart; CursorDPos = stend; - if (verbose || g_debugMode) - PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); + if (verbose) + PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers"); } int startIdx = 0; @@ -513,19 +512,19 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, return 0; } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); + if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); //output setDemodBuf(bits, BitLen, 0); setClockGrid(clk, startIdx); - if (verbose || g_debugMode) { + if (verbose) { if (errCnt > 0) - PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); + PrintAndLogEx(DEBUG, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); if (askType) - PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); + PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); else - PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); + PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(); } @@ -624,7 +623,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); if (DemodBufferLen == 0) { - PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); + PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first"); return 0; } @@ -643,7 +642,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { } if (errCnt > 0) - PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d", errCnt); + PrintAndLogEx(WARNING, "# Errors found during Demod (shown as " _YELLOW_("7")" in bit stream): %d", errCnt); PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); @@ -716,7 +715,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph // sanity check if (window > len) window = len; - if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); + if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%d")" correlations", GraphTraceLen - window); //test double autocv = 0.0; // Autocovariance value @@ -769,10 +768,11 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } int foo = ABS(hi - hi_1); - int bar = (int)((int)((hi + hi_1) / 2) * 0.03); + int bar = (int)((int)((hi + hi_1) / 2) * 0.04); + if (verbose && foo < bar) { distance = idx_1 - idx; - PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); + PrintAndLogEx(SUCCESS, "possible 4% visible correlation %4d samples", distance); } else if (verbose && (correlation > 1)) { PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); } else { @@ -1069,7 +1069,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) { } return 1; } else { - if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); + PrintAndLogEx(DEBUG, "no FSK data found"); } return 0; } @@ -1128,7 +1128,7 @@ int PSKDemod(const char *Cmd, bool verbose) { return 1; } -int CmdPSKIdteck(const char *Cmd) { +int CmdIdteckDemod(const char *Cmd) { if (!PSKDemod("", false)) { PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); diff --git a/client/cmddata.h b/client/cmddata.h index 86f19d81d..1091c48c2 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -54,7 +54,7 @@ int CmdDetectClockRate(const char *Cmd); int CmdFSKrawdemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd); -int CmdPSKIdteck(const char *Cmd); +int CmdIdteckDemod(const char *Cmd); int CmdGrid(const char *Cmd); int CmdGetBitStream(const char *Cmd); int CmdHexsamples(const char *Cmd); diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 0701f1d2d..c75fadb3c 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -245,7 +245,7 @@ int CmdFlashMemLoad(const char *Cmd) { break; default: - res = loadFile(filename, "bin", data, &datalen); + res = loadFile(filename, "bin", data, FLASH_MEM_MAX_SIZE, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if (res) { free(data); diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 0a56ebed4..099a4e3b1 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -42,4 +42,4 @@ extern int CmdFlashMemWipe(const char *Cmd); extern int CmdFlashMemInfo(const char *Cmd); #endif -#endif \ No newline at end of file +#endif diff --git a/client/cmdhf.c b/client/cmdhf.c index 237149348..8368160f8 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -21,7 +21,7 @@ int usage_hf_search() { return 0; } int usage_hf_sniff() { - PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for sniffed data"); + PrintAndLogEx(NORMAL, "The high frequence sniffer will assign all available memory on device for sniffed data"); PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it"); PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n"); PrintAndLogEx(NORMAL, "Usage: hf sniff "); @@ -42,7 +42,7 @@ int CmdHFSearch(const char *Cmd) { if (cmdp == 'h') return usage_hf_search(); PrintAndLogEx(INFO, "Checking for known tags...\n"); - + int ans = CmdHF14AInfo("s"); if (ans > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 6d4b39e4e..6dd7149f2 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -803,7 +803,7 @@ int CmdHF14ASniff(const char *Cmd) { if (ctmp == 'c') param |= 0x01; if (ctmp == 'r') param |= 0x02; } - UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; + UsbCommand c = {CMD_SNIFF_ISO_14443a, {param, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 564b18012..9d542f228 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -33,7 +33,7 @@ int usage_hf_14b_reader(void) { return 0; } int usage_hf_14b_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s / -ss] [-t] <0A 0B 0C ... hex>"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -r do not read response"); @@ -41,6 +41,7 @@ int usage_hf_14b_raw(void) { PrintAndLogEx(NORMAL, " -p leave the field on after receive"); PrintAndLogEx(NORMAL, " -s active signal field ON with select"); PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); + PrintAndLogEx(NORMAL, " -t timeout in ms"); PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); return 0; @@ -145,20 +146,20 @@ int CmdHF14BSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_sniff(); - UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; + UsbCommand c = {CMD_SNIFF_ISO_14443B, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } int CmdHF14BCmdRaw(const char *Cmd) { - bool reply = true, power = false, select = false; + bool reply = true, power = false, select = false, hasTimeout = false; char buf[5] = ""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; uint16_t datalen = 0; uint32_t flags = ISO14B_CONNECT; - uint32_t temp = 0; + uint32_t temp = 0, user_timeout = 0, time_wait = 0; if (strlen(Cmd) < 3) return usage_hf_14b_raw(); @@ -189,6 +190,13 @@ int CmdHF14BCmdRaw(const char *Cmd) { flags |= ISO14B_SELECT_STD; } break; + case 't': + hasTimeout = true; + sscanf(Cmd + i + 2, "%d", &user_timeout); + i += 3; + while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } + i -= 2; + break; default: return usage_hf_14b_raw(); } @@ -214,7 +222,17 @@ int CmdHF14BCmdRaw(const char *Cmd) { return 0; } - if (!power) + if (hasTimeout) { +#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s + flags |= ISO14B_SET_TIMEOUT; + if (user_timeout > MAX_TIMEOUT) { + user_timeout = MAX_TIMEOUT; + PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); + } + time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + } + + if (power == 0) flags |= ISO14B_DISCONNECT; if (datalen > 0) @@ -223,7 +241,7 @@ int CmdHF14BCmdRaw(const char *Cmd) { // Max buffer is USB_CMD_DATA_SIZE datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, time_wait}}; memcpy(c.d.asBytes, data, datalen); clearCommandBuffer(); SendCommand(&c); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 2e784962c..23a756062 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -684,15 +684,15 @@ int CmdHF15Dump(const char *Cmd) { //Validations if (errors) return usage_15_dump(); + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } + if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } - fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr, uid, "-dump", sizeof(uid)); } @@ -796,7 +796,7 @@ int CmdHF15Restore(const char *Cmd) { case '2': case 'o': strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1); - strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - 1); + strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - strlen(newCmdPrefix) - 1); break; default: PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); @@ -1315,4 +1315,4 @@ int CmdHF15(const char *Cmd) { int CmdHF15Help(const char *Cmd) { CmdsHelp(CommandTable15); return 0; -} \ No newline at end of file +} diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index fce18f11b..0386155c1 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -176,4 +176,4 @@ int CmdHFEPA(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; -} \ No newline at end of file +} diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 59ddc5d65..33d506a58 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -218,7 +218,7 @@ int CmdHFFelicaSniff(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_hf_felica_sniff(); - UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; + UsbCommand c = {CMD_FELICA_SNIFF, {samples2skip, triggers2skip, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -609,4 +609,4 @@ int CmdHFFelica(const char *Cmd) { int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} \ No newline at end of file +} diff --git a/client/cmdhffido.h b/client/cmdhffido.h index 2460a170f..96f9153ed 100644 --- a/client/cmdhffido.h +++ b/client/cmdhffido.h @@ -24,4 +24,4 @@ extern int CmdHFFido(const char *Cmd); -#endif \ No newline at end of file +#endif diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index b71f2fd03..ad0f510a7 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -279,7 +279,7 @@ int CmdHFiClassList(const char *Cmd) { int CmdHFiClassSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_iclass_sniff(); - UsbCommand c = {CMD_SNOOP_ICLASS}; + UsbCommand c = {CMD_SNIFF_ICLASS}; SendCommand(&c); return 0; } @@ -1375,11 +1375,14 @@ int CmdHFiClassCloneTag(const char *Cmd) { return 2; } + fclose(f); + uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) + if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { return 0; + } UsbCommand w = {CMD_ICLASS_CLONE, {startblock, endblock}}; uint8_t *ptr; @@ -1401,6 +1404,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]); } + UsbCommand resp; clearCommandBuffer(); SendCommand(&w); diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index a509873da..db65447ac 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1317,4 +1317,4 @@ int CmdHFLegic(const char *Cmd) { int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} \ No newline at end of file +} diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 6bcfe0b20..3c1fb83bd 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1251,4 +1251,4 @@ uint64_t GetCrypto1ProbableKey(TAuthData *ad) { crypto1_get_lfsr(revstate, &key); crypto1_destroy(revstate); return key; -} \ No newline at end of file +} diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e3b8cb957..44722a7bb 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2541,7 +2541,7 @@ int CmdHF14AMfELoad(const char *Cmd) { uint8_t *data = calloc(4096, sizeof(uint8_t)); size_t datalen = 0; - //int res = loadFile(filename, "bin", data, &datalen); + //int res = loadFile(filename, "bin", data, maxdatalen, &datalen); int res = loadFileEML(filename, "eml", data, &datalen); if (res) { free(data); @@ -2827,7 +2827,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { size_t datalen = 0; int res = 0; if (fillFromBin) { - res = loadFile(fileName, "bin", data, &datalen); + res = loadFile(fileName, "bin", data, maxdatalen, &datalen); } else { if (fillFromJson) { res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); @@ -3506,7 +3506,7 @@ static command_t CommandTable[] = { {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, {"chk", CmdHF14AMfChk, 0, "Check keys"}, {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, - {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, + {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"}, {"-----------", CmdHelp, 1, ""}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, diff --git a/client/cmdhfmfdesfire.h b/client/cmdhfmfdesfire.h index c29fd262a..cc5481b0e 100644 --- a/client/cmdhfmfdesfire.h +++ b/client/cmdhfmfdesfire.h @@ -2,4 +2,4 @@ static int CmdHelp(const char *Cmd); int CmdHF14AMfDESAuth(const char *Cmd); int CmdHFMFDesfire(const char *Cmd); -int CmdHelp(const char *Cmd); \ No newline at end of file +int CmdHelp(const char *Cmd); diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index a5cacb518..ed9d36b79 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -15,4 +15,4 @@ extern int CmdHFMFP(const char *Cmd); -#endif \ No newline at end of file +#endif diff --git a/client/cmdlf.c b/client/cmdlf.c index b6da222c6..948cf2235 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -70,8 +70,8 @@ int usage_lf_config(void) { PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample."); PrintAndLogEx(NORMAL, " lf read"); PrintAndLogEx(NORMAL, " Performs a read (active field)"); - PrintAndLogEx(NORMAL, " lf snoop"); - PrintAndLogEx(NORMAL, " Performs a snoop (no active field)"); + PrintAndLogEx(NORMAL, " lf sniff"); + PrintAndLogEx(NORMAL, " Performs a sniff (no active field)"); return 0; } int usage_lf_simfsk(void) { @@ -216,7 +216,7 @@ int CmdFlexdemod(const char *Cmd) { } if (start == size - LONG_WAIT) { - PrintAndLogEx(WARNING, "nothing to wait for"); + PrintAndLogEx(WARNING, "nothing to wait for"); return 0; } @@ -389,7 +389,7 @@ int CmdLFSniff(const char *Cmd) { uint8_t cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_lf_sniff(); - UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES, {0, 0, 0}}; + UsbCommand c = {CMD_LF_SNIFF_RAW_ADC_SAMPLES, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK, NULL); @@ -839,12 +839,12 @@ bool CheckChipType(bool getDeviceData) { //check for t55xx chip... if (tryDetectP1(true)) { - PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found"); + PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found"); PrintAndLogEx(SUCCESS, "Try " _YELLOW_("`lf t55xx`")" commands"); retval = true; goto out; } - + out: save_restoreGB(GRAPH_RESTORE); save_restoreDB(GRAPH_RESTORE); @@ -896,12 +896,15 @@ int CmdLFfind(const char *Cmd) { } if (EM4x50Read("", false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return 1;} + + if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} if (CmdAWIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;} + if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} + if (CmdEM410xDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;} if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;} if (CmdGuardDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; } - if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} - if (CmdPSKIdteck("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} + if (CmdIdteckDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} if (CmdIndalaDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;} if (CmdIOProxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} if (CmdJablotronDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;} @@ -910,7 +913,7 @@ int CmdLFfind(const char *Cmd) { if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;} if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;} if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;} - if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} + if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;} if (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;} if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;} @@ -945,19 +948,19 @@ int CmdLFfind(const char *Cmd) { bool st = true; if (ASKDemod_ext("0 0 0", true, false, 1, &st)) { PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag found!"); - PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'") ); + PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'")); goto out; } if (CmdPSK1rawDemod("")) { PrintAndLogEx(NORMAL, "Possible unknown PSK1 Modulated Tag found above!"); - PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'") ); + PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'")); PrintAndLogEx(NORMAL, " Could also be PSK3 - [currently not supported]"); - PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr") ); + PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr")); goto out; } - PrintAndLogEx(FAILED, _RED_("\nNo data found!") ); + PrintAndLogEx(FAILED, _RED_("\nNo data found!")); } out: // identify chipset diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 719c01a96..5a7d58307 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -17,23 +17,68 @@ #include "common.h" #include "util.h" #include "parity.h" -#include "hitag2.h" -#include "hitagS.h" +#include "hitag.h" #include "util_posix.h" #include "comms.h" #include "cmddata.h" +#include "loclass/fileutils.h" // savefile static int CmdHelp(const char *Cmd); size_t nbytes(size_t nbits) { return (nbits / 8) + ((nbits % 8) > 0); } - -int usage_hitag_reader(void) -{ - PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] "); +int usage_hitag_sniff(void) { + PrintAndLogEx(NORMAL, "Sniff traffic between Hitag reader and tag. Use " _YELLOW_("`lf hitag list`")" to view collected data."); + PrintAndLogEx(NORMAL, "Usage: lf hitag sniff [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); +// PrintAndLogEx(NORMAL, " p Password"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf hitag sniff"); + return 0; +} +int usage_hitag_sim(void) { + PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); + PrintAndLogEx(NORMAL, "Usage: lf hitag sim [h] [2|s] e|j|b "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " [2|s] 2 = hitag2, s = hitagS"); + PrintAndLogEx(NORMAL, " e Load data from EML file"); + PrintAndLogEx(NORMAL, " j Load data from JSON file"); + PrintAndLogEx(NORMAL, " b Load data from BIN file"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); + return 0; +} +int usage_hitag_info(void) { + PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " p password"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf hitag info"); + return 0; +} +int usage_hitag_dump(void) { + PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); +// PrintAndLogEx(NORMAL, " p password"); +// PrintAndLogEx(NORMAL, " f data filename, if no given, UID will be used as filename"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); + PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); + return 0; +} +int usage_hitag_reader(void) { + PrintAndLogEx(NORMAL, "Hitag reader functions"); + PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " HitagS (0*)"); PrintAndLogEx(NORMAL, " 01 Challenge, read all pages from a Hitag S tag"); PrintAndLogEx(NORMAL, " 02 Set to 0 if no authentication is needed. Read all pages from a Hitag S tag"); @@ -43,11 +88,41 @@ int usage_hitag_reader(void) PrintAndLogEx(NORMAL, " 22 Authentication"); PrintAndLogEx(NORMAL, " 23 Authentication, key is in format: ISK high + ISK low"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); - PrintAndLogEx(NORMAL, " 26 Just read UID"); + PrintAndLogEx(NORMAL, " 26 Just read UID"); + return 0; +} +int usage_hitag_writer(void) { + PrintAndLogEx(NORMAL, "Hitag writer functions"); + PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " HitagS (0*)"); + PrintAndLogEx(NORMAL, " 03 (Challenge) write page on a Hitag S tag"); + PrintAndLogEx(NORMAL, " 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); + PrintAndLogEx(NORMAL, " Hitag1 (1*)"); + PrintAndLogEx(NORMAL, " Hitag2 (2*)"); + PrintAndLogEx(NORMAL, " 24 (set to 0 if no authentication is needed) write page on a Hitag2 tag"); + return 0; +} +int usage_hitag_checkchallenges(void) { + PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); + PrintAndLogEx(NORMAL, "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`")); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf hitag cc [h] f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " f Load data from BIN file"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); return 0; } int CmdLFHitagList(const char *Cmd) { + CmdTraceList("hitag"); + return 0; + + /* uint8_t *got = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if (!got) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); @@ -172,10 +247,15 @@ int CmdLFHitagList(const char *Cmd) { free(got); return 0; + */ } -int CmdLFHitagSnoop(const char *Cmd) { - UsbCommand c = {CMD_SNOOP_HITAG}; +int CmdLFHitagSniff(const char *Cmd) { + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_hitag_sniff(); + + UsbCommand c = {CMD_SNIFF_HITAG, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -183,40 +263,249 @@ int CmdLFHitagSnoop(const char *Cmd) { int CmdLFHitagSim(const char *Cmd) { - UsbCommand c = {CMD_SIMULATE_HITAG}; + bool errors = false; + bool tag_mem_supplied = false; + uint8_t cmdp = 0; + size_t maxdatalen = 48; + uint8_t *data = calloc(4 * 64, sizeof(uint8_t)); + size_t datalen = 0; + int res = 0; char filename[FILE_PATH_SIZE] = { 0x00 }; - FILE *f; - bool tag_mem_supplied; - int len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); + UsbCommand c = {CMD_SIMULATE_HITAG, {0, 0, 0}}; - if (strlen(filename) > 0) { - f = fopen(filename, "rb+"); - if (!f) { - PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); - return 1; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + free(data); + return usage_hitag_sim(); + case '2': + maxdatalen = 48; + cmdp++; + break; + case 's': + c.cmd = CMD_SIMULATE_HITAG_S; + maxdatalen = 4 * 64; + cmdp++; + break; + case 'e': + param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); + res = loadFileEML(filename, "eml", data, &datalen); + if (res > 0 || datalen != maxdatalen) { + PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); + errors = true; + break; + } + tag_mem_supplied = true; + cmdp += 2; + break; + case 'j': + param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); + res = loadFileJSON(filename, "json", data, maxdatalen, &datalen); + if (res > 0) { + errors = true; + break; + } + tag_mem_supplied = true; + cmdp += 2; + break; + case 'b': + param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); + res = loadFile(filename, "bin", data, maxdatalen, &datalen); + if (res > 0) { + errors = true; + break; + } + tag_mem_supplied = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; } - tag_mem_supplied = true; - size_t bytes_read = fread(c.d.asBytes, 1, 48, f); - if (bytes_read == 48) { - PrintAndLogEx(WARNING, "Error: File reading error"); - fclose(f); - return 1; - } - fclose(f); - } else { - tag_mem_supplied = false; } - // Does the tag comes with memory + //Validations + if (errors || cmdp == 0) { + free(data); + return usage_hitag_sim(); + } + c.arg[0] = (uint32_t)tag_mem_supplied; + if (tag_mem_supplied) { + memcpy(c.d.asBytes, data, datalen); + } clearCommandBuffer(); SendCommand(&c); + + free(data); return 0; } +static void printHitagConfiguration(uint8_t config) { + + char msg[100]; + memset(msg, 0, sizeof(msg)); + + char bits[9]; + char *bs = bits; + for (uint8_t i = 0 ; i < 8 ; i++) { + snprintf(bs, sizeof(bits), "%d", (config >> (7 - i)) & 1); + bs++; + } + + PrintAndLogEx(INFO, "\n\nHitag2 tag information "); + PrintAndLogEx(INFO, "------------------------------------"); + + //configuration byte + PrintAndLogEx(SUCCESS, "Config byte : %02X - %s", config, bits); + + // encoding + strcat(msg, "Encoding : "); + if (config & 0x1) { + strcat(msg + strlen(msg), _YELLOW_("Biphase")); + } else { + strcat(msg + strlen(msg), _YELLOW_("Manchester")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + memset(msg, 0, sizeof(msg)); + + // version + strcat(msg, "Coding in HITAG 2 operation: %s"); + uint8_t foo = (config & 0x6) >> 1; + switch (foo) { + case 0: + PrintAndLogEx(SUCCESS, "Version : public mode B, Coding: biphase"); + PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); + break; + case 1: + PrintAndLogEx(SUCCESS, "Version : public mode A, Coding: manchester"); + PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); + break; + case 2: + PrintAndLogEx(SUCCESS, "Version : public mode C, Coding: biphase"); + PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); + break; + case 3: + PrintAndLogEx(SUCCESS, "Version : Hitag2"); + PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); + break; + } + memset(msg, 0, sizeof(msg)); + + // mode + strcat(msg, "Tag is in : "); + if (config & 0x8) { + strcat(msg + strlen(msg), _YELLOW_("Crypto mode")); + } else { + strcat(msg + strlen(msg), _YELLOW_("Password mode")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + memset(msg, 0, sizeof(msg)); + + // page access + strcat(msg, "Page 6,7 : "); + if (config & 0x10) { + strcat(msg + strlen(msg), "read only"); + } else { + strcat(msg + strlen(msg), _GREEN_("read write")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + memset(msg, 0, sizeof(msg)); + + // page access + strcat(msg, "Page 4,5 : "); + if (config & 0x20) { + strcat(msg + strlen(msg), "read only"); + } else { + strcat(msg + strlen(msg), _GREEN_("read write")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + memset(msg, 0, sizeof(msg)); + + // OTP + strcat(msg, "Page 3 : "); + if (config & 0x40) { + strcat(msg + strlen(msg), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE")); + } else { + strcat(msg + strlen(msg), _GREEN_("read write")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + memset(msg, 0, sizeof(msg)); + + // OTP + if (config & 0x80) { + strcat(msg, "Page 1 : " _RED_("locked") "\n"); + + strcat(msg + strlen(msg), "Page 2 : "); + if (config & 0x8) { + strcat(msg + strlen(msg), _RED_("locked")); + } else { + strcat(msg + strlen(msg), "read only"); + } + } else { + strcat(msg, "Page 1,2 : " _GREEN_("read write")); + } + PrintAndLogEx(SUCCESS, "%s", msg); + PrintAndLogEx(INFO, "------------------------------------"); +} + +static bool getHitagUid(uint32_t *uid) { + + UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY, 0, 0} }; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return false; + } + + if (resp.arg[0] == false) { + PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID"); + return false; + } + + if ( uid ) + *uid = bytes_to_num(resp.d.asBytes, 4); + + return true; +} + +int CmdLFHitagInfo(const char *Cmd) { + PrintAndLogEx(INFO, "Hitag2 tag information "); + PrintAndLogEx(INFO, "To be done!"); + PrintAndLogEx(INFO, "------------------------------------"); + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_hitag_info(); + + // pwd or key + + // read UID + uint32_t uid = 0; + if ( getHitagUid( &uid ) == false ) + return 1; + + PrintAndLogEx(SUCCESS, "UID: %08X", uid); + + // how to detemine Hitag types? + + // read block3, get configuration byte. + + // common configurations. + printHitagConfiguration(0x06); + //printHitagConfiguration( 0x0E ); + //printHitagConfiguration( 0x02 ); + //printHitagConfiguration( 0x00 ); + //printHitagConfiguration( 0x04 ); + return 0; +} + +// TODO: iceman +// Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !? +// int CmdLFHitagReader(const char *Cmd) { UsbCommand c = {CMD_READER_HITAG, {0, 0, 0} }; @@ -228,25 +517,25 @@ int CmdLFHitagReader(const char *Cmd) { c.cmd = CMD_READ_HITAG_S; num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4); - break; + break; } case RHTSF_KEY: { c.cmd = CMD_READ_HITAG_S; num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); - break; + break; } case RHT2F_PASSWORD: { num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password); - break; + break; } case RHT2F_AUTHENTICATE: { num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4); - break; + break; } case RHT2F_CRYPTO: { num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); - break; + break; } case RHT2F_TEST_AUTH_ATTEMPTS: { // No additional parameters needed @@ -257,7 +546,6 @@ int CmdLFHitagReader(const char *Cmd) { break; } default: { - PrintAndLogEx(NORMAL, "\nError: unkown reader function %d", htf); return usage_hitag_reader(); } } @@ -278,150 +566,136 @@ int CmdLFHitagReader(const char *Cmd) { uint32_t id = bytes_to_num(resp.d.asBytes, 4); - if (htf == RHT2F_UID_ONLY) { - PrintAndLogEx(NORMAL, "Valid Hitag2 tag found - UID: %08x", id); - } else { + PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id); + if (htf != RHT2F_UID_ONLY) { + + PrintAndLogEx(SUCCESS, "Dumping tag memory..." ); + uint8_t *data = resp.d.asBytes; + char filename[FILE_PATH_SIZE]; - FILE *f = NULL; - sprintf(filename, "%08x_%04x.ht2", id, (rand() & 0xffff)); - f = fopen(filename, "wb"); - if (!f) { - PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); - return 1; - } + char *fnameptr = filename; + fnameptr += sprintf(fnameptr, "lf-hitag-"); + FillFileNameByUID(fnameptr, data, "-dump", 4); - // Write the 48 tag memory bytes to file and finalize - fwrite(resp.d.asBytes, 1, 48, f); - fclose(f); - PrintAndLogEx(NORMAL, "Succesfully saved tag memory to [%s]", filename); + saveFile(filename, "bin", data, 48); + saveFileEML(filename, "eml", data, 48, 4); + saveFileJSON(filename, "json", jsfHitag, data, 48); + + // block3, 1 byte + printHitagConfiguration(data[4*3] ); } return 0; } -int CmdLFHitagSimS(const char *Cmd) { - UsbCommand c = { CMD_SIMULATE_HITAG_S }; - char filename[FILE_PATH_SIZE] = { 0x00 }; - FILE *f; - bool tag_mem_supplied; - int len = strlen(Cmd); - if (len > FILE_PATH_SIZE) - len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - - if (strlen(filename) > 0) { - f = fopen(filename, "rb+"); - if (!f) { - PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); - return 1; - } - tag_mem_supplied = true; - size_t bytes_read = fread(c.d.asBytes, 1, 4 * 64, f); - if (bytes_read == 4 * 64) { - PrintAndLogEx(WARNING, "Error: File reading error"); - fclose(f); - return 1; - } - fclose(f); - } else { - tag_mem_supplied = false; - } - - // Does the tag comes with memory - c.arg[0] = (uint32_t) tag_mem_supplied; - clearCommandBuffer(); - SendCommand(&c); - return 0; -} - int CmdLFHitagCheckChallenges(const char *Cmd) { - UsbCommand c = { CMD_TEST_HITAGS_TRACES }; - char filename[FILE_PATH_SIZE] = { 0x00 }; - FILE *f; - bool file_given; - int len = strlen(Cmd); - if (len > FILE_PATH_SIZE) - len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - if (strlen(filename) > 0) { - f = fopen(filename, "rb+"); - if (!f) { - PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); - return 1; + UsbCommand c = { CMD_TEST_HITAGS_TRACES, {0, 0, 0}}; + char filename[FILE_PATH_SIZE] = { 0x00 }; + size_t datalen = 0; + int res = 0; + bool file_given = false; + bool errors = false; + uint8_t cmdp = 0; + uint8_t *data = calloc(8 * 60, sizeof(uint8_t)); + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + free(data); + return usage_hitag_checkchallenges(); + case 'f': + param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); + res = loadFile(filename, "cc", data, 8 * 60, &datalen); + if (res > 0) { + errors = true; + break; + } + + memcpy(c.d.asBytes, data, datalen); + file_given = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; } - file_given = true; - size_t bytes_read = fread(c.d.asBytes, 1, 8 * 60, f); - if (bytes_read == 8 * 60) { - PrintAndLogEx(WARNING, "Error: File reading error"); - fclose(f); - return 1; - } - fclose(f); - } else { - file_given = false; + } + + //Validations + if (errors) { + free(data); + return usage_hitag_checkchallenges(); } //file with all the challenges to try c.arg[0] = (uint32_t)file_given; clearCommandBuffer(); SendCommand(&c); + + free(data); return 0; } -int CmdLFHitagWP(const char *Cmd) { - UsbCommand c = { CMD_WR_HITAG_S }; +int CmdLFHitagWriter(const char *Cmd) { + UsbCommand c = { CMD_WR_HITAG_S, {0, 0, 0}}; hitag_data *htd = (hitag_data *)c.d.asBytes; hitag_function htf = param_get32ex(Cmd, 0, 0, 10); + switch (htf) { - case 03: { //WHTSF_CHALLENGE + case WHTSF_CHALLENGE: { num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd->auth.NrAr); c.arg[2] = param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->auth.data); + break; } - break; - case 04: - case 24: { - //WHTSF_KEY + case WHTSF_KEY: + case WHT2F_CRYPTO: { num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); c.arg[2] = param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data); - + break; } - break; default: { - PrintAndLogEx(WARNING, "Error: unkown writer function %d", htf); - PrintAndLogEx(NORMAL, "Hitag writer functions"); - PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 03 (Challenge) write page on a Hitag S tag"); - PrintAndLogEx(NORMAL, " 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); - PrintAndLogEx(NORMAL, " Hitag1 (1*)"); - PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - return 1; + return usage_hitag_writer(); } - break; } - // Copy the hitag function into the first argument + c.arg[0] = htf; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - WaitForResponse(CMD_ACK, &resp); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return 1; + } - // Check the return status, stored in the first argument - if (resp.arg[0] == false) return 1; + if (resp.arg[0] == false) { + PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed"); + return 1; + } + return 0; +} + +int CmdLFHitagDump(const char *Cmd) { + PrintAndLogEx(INFO, "Dumping of tag memory"); + PrintAndLogEx(INFO, "To be done!"); + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_hitag_dump(); return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdLFHitagList, 1, " List Hitag trace history"}, - {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, - {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, - {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, - {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, - {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, - {"check_challenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, + {"help", CmdHelp, 1, "This help" }, + {"list", CmdLFHitagList, 0, "List Hitag trace history" }, + {"info", CmdLFHitagInfo, 1, "Tag information" }, + {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader" }, + {"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder" }, + {"sniff", CmdLFHitagSniff, 1, "Eavesdrop Hitag communication" }, + {"writer", CmdLFHitagWriter, 1, "Act like a Hitag Writer" }, + {"cc", CmdLFHitagCheckChallenges, 1, "Test all challenges" }, { NULL, NULL, 0, NULL } }; diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index e43ed58ff..eb5bb2dd0 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -14,11 +14,12 @@ extern int CmdLFHitag(const char *Cmd); extern int CmdLFHitagList(const char *Cmd); -extern int CmdLFHitagReader(const char *Cmd); +extern int CmdLFHitagSniff(const char *Cmd); extern int CmdLFHitagSim(const char *Cmd); -extern int CmdLFHitagSimS(const char *Cmd); -extern int CmdLFHitagSnoop(const char *Cmd); -extern int CmdLFHitagWP(const char *Cmd); +extern int CmdLFHitagInfo(const char *Cmd); +extern int CmdLFHitagReader(const char *Cmd); extern int CmdLFHitagCheckChallenges(const char *Cmd); +extern int CmdLFHitagWriter(const char *Cmd); +extern int CmdLFHitagDump(const char *cmd); #endif diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 91f4a456f..41512c6b9 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1882,7 +1882,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { // first try fliping each bit in the expected password while (bit < 32) { - curr_password = orig_password ^ (1 << bit); + curr_password = orig_password ^ (1u << bit); found = tryOnePassword(curr_password); if (found == -1) return 0; bit++; @@ -1897,7 +1897,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { // from low bit to high bit bit = 0; while (bit < 32) { - mask += (1 << bit); + mask += (1u << bit); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again if (prev_password == curr_password) { @@ -1916,7 +1916,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { bit = 0; mask = 0xffffffff; while (bit < 32) { - mask -= (1 << bit); + mask -= (1u << bit); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again if (prev_password == curr_password) { diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 6abb9b5de..5d3c2e399 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -191,7 +191,7 @@ int CmdTIDemod(const char *Cmd) { bits[i] = '1'; maxPos += highLen; // bitstream arrives lsb first so shift right - shift3 |= (1 << 31); + shift3 |= (1u << 31); } else { bits[i] = '.'; maxPos += lowLen; diff --git a/client/cmdmain.c b/client/cmdmain.c index 608a0e668..5bbd689e1 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -74,4 +74,4 @@ int CmdRev(const char *Cmd) { //----------------------------------------------------------------------------- int CommandReceived(char *Cmd) { return CmdsParse(CommandTable, Cmd); -} \ No newline at end of file +} diff --git a/client/cmdscript.c b/client/cmdscript.c index 2e2ec5f53..e1a21ffc4 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -193,4 +193,4 @@ int CmdScript(const char *Cmd) { int CmdHelp(const char *Cmd) { PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place lua-scripts within the scripts/-folder. "); return 0; -} \ No newline at end of file +} diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 27b2afc39..8d00fa128 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -49,13 +49,13 @@ int usage_sm_info(void) { return 0; } int usage_sm_upgrade(void) { - PrintAndLogEx(NORMAL, "Upgrade firmware"); + PrintAndLogEx(NORMAL, "Upgrade RDV4.0 Sim module firmware"); PrintAndLogEx(NORMAL, "Usage: sc upgrade f "); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " f : firmware file name"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc upgrade f myfile"); + PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/SIM011.BIN"); return 0; } int usage_sm_setclock(void) { @@ -116,7 +116,7 @@ uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) { return atr[2]; } - return 0x11; // default value is ‘0x11’, corresponding to fmax=5 MHz, Fi=372, Di=1. + return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1. } int DiArray[] = { @@ -196,6 +196,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { uint8_t T0 = atr[1]; uint8_t K = T0 & 0x0F; uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; + bool protocol_T0_present = true; + bool protocol_T15_present = false; if (T0 & 0x10) { PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); @@ -215,6 +217,14 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (T0 & 0x80) { TD1 = atr[2 + T1len]; PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); + protocol_T0_present = false; + if ((TD1 & 0x0f) == 0) { + protocol_T0_present = true; + } + if ((TD1 & 0x0f) == 15) { + protocol_T15_present = true; + } + T1len++; if (TD1 & 0x10) { @@ -232,6 +242,12 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (TD1 & 0x80) { uint8_t TDi = atr[2 + T1len + TD1len]; PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); + if ((TDi & 0x0f) == 0) { + protocol_T0_present = true; + } + if ((TDi & 0x0f) == 15) { + protocol_T15_present = true; + } TD1len++; bool nextCycle = true; @@ -262,19 +278,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { } } - uint8_t vxor = 0; - for (int i = 1; i < atrlen; i++) - vxor ^= atr[i]; + if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK + uint8_t vxor = 0; + for (int i = 1; i < atrlen; i++) + vxor ^= atr[i]; - if (vxor) - PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); - else - PrintAndLogEx(INFO, "Check summ OK."); + if (vxor) + PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor); + else + PrintAndLogEx(INFO, "Check sum OK."); + } if (atr[0] != 0x3b) PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); - uint8_t calen = 2 + T1len + TD1len + TDilen + K; if (atrlen != calen && atrlen != calen + 1) // may be CRC @@ -561,8 +578,9 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave int CmdSmartUpgrade(const char *Cmd) { - PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); - PrintAndLogEx(WARNING, "A dangerous command, do wrong and you will brick the smart card socket"); + PrintAndLogEx(WARNING, "WARNING - Sim module firmware upgrade."); + PrintAndLogEx(WARNING, "A dangerous command, do wrong and you could brick the sim module"); + PrintAndLogEx(NORMAL, ""); FILE *f; char filename[FILE_PATH_SIZE] = {0}; @@ -592,10 +610,33 @@ int CmdSmartUpgrade(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_sm_upgrade(); - // load file + + char sha512filename[FILE_PATH_SIZE] = {'\0'}; + char *bin_extension = filename; + char *dot_position = NULL; + while ((dot_position = strchr(bin_extension, '.')) != NULL) { + bin_extension = dot_position + 1; + } + + if (!strcmp(bin_extension, "BIN") +#ifdef _WIN32 + || !strcmp(bin_extension, "bin") +#endif + ) { + memcpy(sha512filename, filename, strlen(filename) - strlen("bin")); + strcat(sha512filename, "sha512.txt"); + } else { + PrintAndLogEx(FAILED, "Filename extension of firmware upgrade file must be .BIN"); + return 1; + } + + PrintAndLogEx(INFO, "firmware file : " _YELLOW_("%s"), filename); + PrintAndLogEx(INFO, "Checking integrity : " _YELLOW_("%s"), sha512filename); + + // load firmware file f = fopen(filename, "rb"); if (!f) { - PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); + PrintAndLogEx(FAILED, "Firmware file " _YELLOW_("%s") " not found or locked.", filename); return 1; } @@ -605,27 +646,77 @@ int CmdSmartUpgrade(const char *Cmd) { fseek(f, 0, SEEK_SET); if (fsize < 0) { - PrintAndLogDevice(WARNING, "error, when getting filesize"); + PrintAndLogEx(WARNING, "error, when getting filesize"); fclose(f); return 1; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { - PrintAndLogDevice(WARNING, "error, cannot allocate memory "); + PrintAndLogEx(WARNING, "error, cannot allocate memory "); fclose(f); return 1; } - size_t bytes_read = fread(dump, 1, fsize, f); + size_t firmware_size = fread(dump, 1, fsize, f); + if (f) { + fclose(f); + } + + // load sha512 file + f = fopen(sha512filename, "rb"); + if (!f) { + PrintAndLogEx(FAILED, "SHA-512 file not found or locked."); + return 1; + } + + // get filesize in order to malloc memory + fseek(f, 0, SEEK_END); + fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + if (fsize < 0) { + PrintAndLogEx(FAILED, "Could not determine size of SHA-512 file"); + fclose(f); + return 1; + } + + if (fsize < 128) { + PrintAndLogEx(FAILED, "SHA-512 file too short"); + fclose(f); + return 1; + } + + char hashstring[129]; + size_t bytes_read = fread(hashstring, 1, 128, f); + hashstring[128] = '\0'; + if (f) fclose(f); - PrintAndLogEx(SUCCESS, "Smartcard socket firmware uploading to PM3"); + uint8_t hash1[64]; + if (bytes_read != 128 || param_gethex(hashstring, 0, hash1, 128)) { + PrintAndLogEx(FAILED, "Couldn't read SHA-512 file"); + return 1; + } + + uint8_t hash2[64]; + if (sha512hash(dump, firmware_size, hash2)) { + PrintAndLogEx(FAILED, "Couldn't calculate SHA-512 of firmware"); + return 1; + } + + if (memcmp(hash1, hash2, 64)) { + PrintAndLogEx(FAILED, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)")); + return 1; + } + + PrintAndLogEx(SUCCESS, "Sim module firmware uploading to PM3"); + //Send to device uint32_t index = 0; uint32_t bytes_sent = 0; - uint32_t bytes_remaining = bytes_read; + uint32_t bytes_remaining = firmware_size; while (bytes_remaining > 0) { uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining); @@ -649,10 +740,10 @@ int CmdSmartUpgrade(const char *Cmd) { } free(dump); printf("\n"); - PrintAndLogEx(SUCCESS, "Smartcard socket firmware updating, don\'t turn off your PM3!"); + PrintAndLogEx(SUCCESS, "Sim module firmware updating, don\'t turn off your PM3!"); // trigger the firmware upgrade - UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}}; + UsbCommand c = {CMD_SMART_UPGRADE, {firmware_size, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -660,10 +751,12 @@ int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; } - if ((resp.arg[0] & 0xFF)) - PrintAndLogEx(SUCCESS, "Smartcard socket firmware upgraded successful"); - else - PrintAndLogEx(FAILED, "Smartcard socket firmware updating failed"); + if ((resp.arg[0] & 0xFF)) { + PrintAndLogEx(SUCCESS, "Sim module firmware upgrade " _GREEN_("successful")); + PrintAndLogEx(SUCCESS, "\n run " _YELLOW_("`hw status`") " to validate the fw version "); + } else { + PrintAndLogEx(FAILED, "Sim module firmware upgrade " _RED_("failed")); + } return 0; } @@ -874,11 +967,11 @@ static void smart_brute_prim() { if (len > 2) { - //if ( decodeTLV ) { - //if (!TLVPrintFromBuffer(buf, len-2)) { + // if ( decodeTLV ) { + // if (!TLVPrintFromBuffer(buf, len-2)) { PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); - //} - //} + // } + // } } len = 0; } @@ -1124,14 +1217,14 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdSmartList, 0, "List ISO 7816 history"}, - {"info", CmdSmartInfo, 1, "Tag information"}, - {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, - {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, - {"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdSmartList, 0, "List ISO 7816 history"}, + {"info", CmdSmartInfo, 1, "Tag information"}, + {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, + {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, + {"upgrade", CmdSmartUpgrade, 1, "Upgrade sim module firmware"}, {"setclock", CmdSmartSetClock, 1, "Set clock speed"}, - {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, + {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 14e79cd4e..251859761 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -25,6 +25,7 @@ #include "emv/emvcore.h" // decodeTVL #include "emv/apduinfo.h" // APDUcode description #include "emv/dump.h" // dump_buffer +#include "crypto/libpcrypto.h" // sha512hash extern int CmdSmartcard(const char *Cmd); @@ -40,4 +41,4 @@ extern int usage_sm_raw(void); extern int usage_sm_reader(void); extern int usage_sm_info(void); extern int usage_sm_upgrade(void); -#endif \ No newline at end of file +#endif diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 77f85ce5c..05a85a050 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -36,6 +36,7 @@ int usage_trace_list() { PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); + PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace list 14a f"); @@ -175,6 +176,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso15693_CRC_check(frame, data_len); break; case ISO_7816_4: + case PROTO_HITAG: default: break; } @@ -189,11 +191,12 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui for (int j = 0; j < data_len && j / 18 < 18; j++) { uint8_t parityBits = parityBytes[j >> 3]; - if (protocol != LEGIC && - protocol != ISO_14443B && - protocol != ISO_7816_4 && - (isResponse || protocol == ISO_14443A) && - (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { + if (protocol != LEGIC + && protocol != ISO_14443B + && protocol != ISO_7816_4 + && protocol != PROTO_HITAG + && (isResponse || protocol == ISO_14443A) + && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]); } else { @@ -556,16 +559,17 @@ int CmdTraceList(const char *Cmd) { // validate type of output if (strcmp(type, "iclass") == 0) protocol = ICLASS; - else if (strcmp(type, "14a") == 0) protocol = ISO_14443A; - else if (strcmp(type, "14b") == 0) protocol = ISO_14443B; - else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; - else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4; - else if (strcmp(type, "des") == 0) protocol = MFDES; - else if (strcmp(type, "legic") == 0) protocol = LEGIC; - else if (strcmp(type, "15") == 0) protocol = ISO_15693; - else if (strcmp(type, "felica") == 0) protocol = FELICA; - else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; - else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations + else if (strcmp(type, "14a") == 0) protocol = ISO_14443A; + else if (strcmp(type, "14b") == 0) protocol = ISO_14443B; + else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; + else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4; + else if (strcmp(type, "des") == 0) protocol = MFDES; + else if (strcmp(type, "legic") == 0) protocol = LEGIC; + else if (strcmp(type, "15") == 0) protocol = ISO_15693; + else if (strcmp(type, "felica") == 0) protocol = FELICA; + else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; + else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; + else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else errors = true; cmdp++; @@ -625,6 +629,8 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if (protocol == ISO_7816_4) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); + if (protocol == PROTO_HITAG) + PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); @@ -642,8 +648,8 @@ int CmdTraceLoad(const char *Cmd) { FILE *f = NULL; char filename[FILE_PATH_SIZE]; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_load(); param_getstr(Cmd, 0, filename, sizeof(filename)); @@ -688,13 +694,13 @@ int CmdTraceLoad(const char *Cmd) { int CmdTraceSave(const char *Cmd) { if (traceLen == 0) { - PrintAndLogEx(WARNING, "trace is empty, exiting..."); + PrintAndLogEx(WARNING, "trace is empty, nothing to save"); return 0; } char filename[FILE_PATH_SIZE]; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_save(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save(); param_getstr(Cmd, 0, filename, sizeof(filename)); saveFile(filename, "bin", trace, traceLen); diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 883de0dbb..095d16af3 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -106,6 +107,20 @@ int sha256hash(uint8_t *input, int length, uint8_t *hash) { return 0; } +int sha512hash(uint8_t *input, int length, uint8_t *hash) { + if (!hash || !input) + return 1; + + mbedtls_sha512_context sctx; + mbedtls_sha512_init(&sctx); + mbedtls_sha512_starts(&sctx, 0); //SHA-512, not 384 + mbedtls_sha512_update(&sctx, input, length); + mbedtls_sha512_finish(&sctx, hash); + mbedtls_sha512_free(&sctx); + + return 0; +} + int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char *key_d, char *key_x, char *key_y) { if (!ctx) return 1; diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h index 5f3592b7a..2cb4644a8 100644 --- a/client/crypto/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -22,6 +22,7 @@ extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); extern int sha256hash(uint8_t *input, int length, uint8_t *hash); +extern int sha512hash(uint8_t *input, int length, uint8_t *hash); extern int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy); extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 31886cf75..b5edfa81c 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -288,6 +288,7 @@ int CmdEMVGPO(const char *cmd) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); + free(pdol_data_tlv); return 4; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1577,6 +1578,7 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); + free(pdol_data_tlv); DropFieldEx(channel); return 6; } diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index d47109f7c..18326083f 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -38,4 +38,4 @@ extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbu extern bool ParamLoadFromJson(struct tlvdb *tlv); -#endif \ No newline at end of file +#endif diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 36e5872e0..7c5a4a883 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -322,42 +322,42 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len } if (!memcmp("fpga_lf", basename(infile_name), 7)) - strncat(dst, "LF", len - 1); + strncat(dst, "LF", len - strlen(dst) - 1); else if (!memcmp("fpga_hf", basename(infile_name), 7)) - strncat(dst, "HF", len - 1); + strncat(dst, "HF", len - strlen(dst) - 1); - strncat(dst, " image built", len - 1); + strncat(dst, " image built", len - strlen(dst) - 1); if (bitparse_find_section(infile, 'b', &fpga_info_len)) { - strncat(dst, " for ", len - 1); + strncat(dst, " for ", len - strlen(dst) - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - 1); + strncat(dst, tempstr, len - strlen(dst) - 1); } if (bitparse_find_section(infile, 'c', &fpga_info_len)) { - strncat(dst, " on ", len - 1); + strncat(dst, " on ", len - strlen(dst) - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - 1); + strncat(dst, tempstr, len - strlen(dst) - 1); } if (bitparse_find_section(infile, 'd', &fpga_info_len)) { - strncat(dst, " at ", len - 1); + strncat(dst, " at ", len - strlen(dst) - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - 1); + strncat(dst, tempstr, len - strlen(dst) - 1); } return 0; } diff --git a/client/hardnested/hardnested_tables.c b/client/hardnested/hardnested_tables.c index bc92e5f10..09de7f5d7 100644 --- a/client/hardnested/hardnested_tables.c +++ b/client/hardnested/hardnested_tables.c @@ -577,4 +577,4 @@ int main(int argc, char *argv[]) { free_part_sum_bitarrays(); return 0; -} \ No newline at end of file +} diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 5e562c10b..ac563bd26 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -96,7 +96,7 @@ typedef struct { #define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_CLONE_TAG 0x021B #define CMD_EM410X_DEMOD 0x021c -// Sampling configuration for LF reader/snooper +// Sampling configuration for LF reader/sniffer #define CMD_SET_LF_SAMPLING_CONFIG 0x021d #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F @@ -119,10 +119,10 @@ typedef struct { #define CMD_ISO_15693_COMMAND 0x0313 #define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 +#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 // For Hitag2 transponders -#define CMD_SNOOP_HITAG 0x0370 +#define CMD_SNIFF_HITAG 0x0370 #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 @@ -135,8 +135,8 @@ typedef struct { #define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNOOP_ISO_14443B 0x0382 -#define CMD_SNOOP_ISO_14443a 0x0383 +#define CMD_SNIFF_ISO_14443B 0x0382 +#define CMD_SNIFF_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 @@ -151,7 +151,7 @@ typedef struct { #define CMD_LEGIC_ESET 0x03BD #define CMD_LEGIC_EGET 0x03BE -#define CMD_SNOOP_ICLASS 0x0392 +#define CMD_SNIFF_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS_REPLAY 0x0395 diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 41be3d39c..038d8e475 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -692,4 +692,4 @@ int testElite() { errors += _test_iclass_key_permutation(); errors += _testBruteforce(); return errors; -} \ No newline at end of file +} diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 4d58c7084..0c345ca14 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -155,11 +155,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty json_t *root = json_object(); JsonSaveStr(root, "Created", "proxmark3"); switch (ftype) { - case jsfRaw: + case jsfRaw: { JsonSaveStr(root, "FileType", "raw"); JsonSaveBufAsHexCompact(root, "raw", data, datalen); break; - case jsfCardMemory: + } + case jsfCardMemory: { JsonSaveStr(root, "FileType", "mfcard"); for (int i = 0; i < (datalen / 16); i++) { char path[PATH_MAX_LENGTH] = {0}; @@ -208,7 +209,8 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty } } break; - case jsfMfuMemory: + } + case jsfMfuMemory: { JsonSaveStr(root, "FileType", "mfu"); mfu_dump_t *tmp = (mfu_dump_t *)data; @@ -230,12 +232,26 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4; for (int i = 0; i < len; i++) { - char path[PATH_MAX_LENGTH] = {0}; sprintf(path, "$.blocks.%d", i); JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); } break; + } + case jsfHitag: { + JsonSaveStr(root, "FileType", "hitag"); + uint8_t uid[4] = {0}; + memcpy(uid, data, 4); + + JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid)); + + for (int i = 0; i < (datalen / 4); i++) { + char path[PATH_MAX_LENGTH] = {0}; + sprintf(path, "$.blocks.%d", i); + JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4); + } + break; + } } int res = json_dump_file(root, fileName, JSON_INDENT(2)); @@ -253,7 +269,7 @@ out: return retval; } -int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen) { +int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) { if (preferredName == NULL) return 1; if (suffix == NULL) return 1; @@ -298,6 +314,11 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t * goto out; } + if (bytes_read != maxdatalen) { + PrintAndLogDevice(WARNING, "Warning, bytes read exeed calling array limit. Max bytes is %d bytes", maxdatalen); + bytes_read = maxdatalen; + } + memcpy((data), dump, bytes_read); free(dump); @@ -447,8 +468,29 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size *datalen = sptr; } + if (!strcmp(ctype, "hitag")) { + size_t sptr = 0; + for (int i = 0; i < (maxdatalen / 4); i++) { + if (sptr + 4 > maxdatalen) { + retval = 5; + goto out; + } - PrintAndLog("loaded from JSON file " _YELLOW_("%s"), fileName); + char path[30] = {0}; + sprintf(path, "$.blocks.%d", i); + + size_t len = 0; + JsonLoadBufAsHex(root, path, &udata[sptr], 4, &len); + if (!len) + break; + + sptr += len; + } + + *datalen = sptr; + } + + PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); out: json_decref(root); free(fileName); diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index c2888c196..7b358331a 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -55,6 +55,11 @@ typedef enum { jsfRaw, jsfCardMemory, jsfMfuMemory, + jsfHitag, +// jsf14b, +// jsf15, +// jsfLegic, +// jsfT55xx, } JSONFileType; int fileExists(const char *filename); @@ -107,10 +112,11 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT * @param preferredName * @param suffix the file suffix. Leave out the ".". * @param data The data array to store the loaded bytes from file + * @param maxdatalen the number of bytes that your data array has * @param datalen the number of bytes loaded from file * @return 0 for ok, 1 for failz */ -extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen); +extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); /** * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. diff --git a/client/lualibs/7816_error.lua b/client/lualibs/7816_error.lua index 038f668fb..15f4ef471 100644 --- a/client/lualibs/7816_error.lua +++ b/client/lualibs/7816_error.lua @@ -75,4 +75,4 @@ _errorcodes.tostring = function(command) end return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) end -return _errorcodes \ No newline at end of file +return _errorcodes diff --git a/client/lualibs/hf_reader.lua b/client/lualibs/hf_reader.lua index d0550a335..b99b521da 100644 --- a/client/lualibs/hf_reader.lua +++ b/client/lualibs/hf_reader.lua @@ -32,4 +32,4 @@ end return { waitForTag = waitForTag, -} \ No newline at end of file +} diff --git a/client/lualibs/precalc.lua b/client/lualibs/precalc.lua index 71d91c05a..7da08f006 100644 --- a/client/lualibs/precalc.lua +++ b/client/lualibs/precalc.lua @@ -91,4 +91,4 @@ local PreCalc = return list end, } -return PreCalc \ No newline at end of file +return PreCalc diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index 3711c02a3..2ee86c378 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -155,4 +155,4 @@ local library = { ISO14B_COMMAND = ISO14B_COMMAND, } -return library \ No newline at end of file +return library diff --git a/client/lualibs/taglib.lua b/client/lualibs/taglib.lua index 715a29487..0612ed2d3 100644 --- a/client/lualibs/taglib.lua +++ b/client/lualibs/taglib.lua @@ -121,4 +121,4 @@ return { return m[value] or "no tag-info available" end, -} \ No newline at end of file +} diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index 697e48b72..ed9874e40 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -427,4 +427,4 @@ local Utils = -- end } -return Utils \ No newline at end of file +return Utils diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 1d9f0c3ab..626d2cd07 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -100,4 +100,4 @@ extern int detect_classic_prng(void); extern int detect_classic_nackbug(bool verbose); extern void detect_classic_magic(void); extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); -#endif \ No newline at end of file +#endif diff --git a/client/pm3_eml_mfd_test.py b/client/pm3_eml_mfd_test.py index 478a050df..171bad843 100644 --- a/client/pm3_eml_mfd_test.py +++ b/client/pm3_eml_mfd_test.py @@ -21,7 +21,7 @@ class TestEmlMfd(unittest.TestCase): ] def test_eml2mfd(self): self.three_argument_test(pm3_eml2mfd.main, self.EML2MFD_TESTCASES) - + def test_mfd2eml(self): self.three_argument_test(pm3_mfd2eml.main, imap(reversed, self.EML2MFD_TESTCASES), c14n=hex_c14n) diff --git a/client/reveng/preset.c b/client/reveng/preset.c index d5bdac2dd..2f305a285 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -939,4 +939,4 @@ static void munpack(model_t *dest, const struct mpreset *src) { dest->flags = src->flags; /* link to the name as it is static */ dest->name = (src->alias) ? src->alias->name : NULL; -} \ No newline at end of file +} diff --git a/client/scandir.h b/client/scandir.h index a41a13319..7155c5a79 100644 --- a/client/scandir.h +++ b/client/scandir.h @@ -19,4 +19,4 @@ extern int scandir(const char *dir, struct dirent ***namelist, int (*select)(con extern int alphasort(const struct dirent **a, const struct dirent **b); #endif // _WIN32 -#endif // SCANDIR_H__ \ No newline at end of file +#endif // SCANDIR_H__ diff --git a/client/scripting.c b/client/scripting.c index 14dc35774..719798177 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -776,4 +776,4 @@ int set_pm3_libraries(lua_State *L) { strcat(libraries_path, LUA_LIBRARIES_WILDCARD); setLuaPath(L, libraries_path); return 1; -} \ No newline at end of file +} diff --git a/client/scripts/Legic_clone.lua b/client/scripts/Legic_clone.lua index dcac7f323..21d756d0e 100644 --- a/client/scripts/Legic_clone.lua +++ b/client/scripts/Legic_clone.lua @@ -538,4 +538,4 @@ function main(args) end -- call main with arguments -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/brutesim.lua b/client/scripts/brutesim.lua index 9527d8970..a15cf6e60 100644 --- a/client/scripts/brutesim.lua +++ b/client/scripts/brutesim.lua @@ -297,4 +297,4 @@ local function main(args) core.console('hw ping') end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/calc_di.lua b/client/scripts/calc_di.lua index e0b587332..9a8c051a4 100644 --- a/client/scripts/calc_di.lua +++ b/client/scripts/calc_di.lua @@ -173,4 +173,4 @@ local function main(args) dumptofile( keys ) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/calc_ev1_it.lua b/client/scripts/calc_ev1_it.lua index c6070d20d..b4e995e96 100644 --- a/client/scripts/calc_ev1_it.lua +++ b/client/scripts/calc_ev1_it.lua @@ -175,4 +175,4 @@ local function main(args) print(string.format('PWD | %s', pwd)) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/calc_mizip.lua b/client/scripts/calc_mizip.lua index 42f13c578..8844f6d66 100644 --- a/client/scripts/calc_mizip.lua +++ b/client/scripts/calc_mizip.lua @@ -194,4 +194,4 @@ local function main(args) dumptofile( keys ) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/calypso.lua b/client/scripts/calypso.lua index 2b7252261..74de3cb9a 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/calypso.lua @@ -273,4 +273,4 @@ if "--test"==args then else -- Call the main main(args) -end \ No newline at end of file +end diff --git a/client/scripts/e.lua b/client/scripts/e.lua index 6b9d80364..1f9a14eb0 100644 --- a/client/scripts/e.lua +++ b/client/scripts/e.lua @@ -74,4 +74,4 @@ function main(args) end end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/emul2dump.lua b/client/scripts/emul2dump.lua index 04b9da12b..0cbc3a4c2 100644 --- a/client/scripts/emul2dump.lua +++ b/client/scripts/emul2dump.lua @@ -57,4 +57,4 @@ local function main(args) ExitMsg(("Wrote a BIN dump to the file %s"):format(filename)) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/emul2html.lua b/client/scripts/emul2html.lua index db76ec9c0..36230f8af 100644 --- a/client/scripts/emul2html.lua +++ b/client/scripts/emul2html.lua @@ -64,4 +64,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua index 90801b2a2..fe9cf32e5 100644 --- a/client/scripts/formatMifare.lua +++ b/client/scripts/formatMifare.lua @@ -213,4 +213,4 @@ local function main(args) end end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/hf_read.lua b/client/scripts/hf_read.lua index 7653e6e75..00238a67c 100644 --- a/client/scripts/hf_read.lua +++ b/client/scripts/hf_read.lua @@ -15,4 +15,4 @@ local function main(args) end return end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/htmldump.lua b/client/scripts/htmldump.lua index 40f3028b4..afd76abee 100644 --- a/client/scripts/htmldump.lua +++ b/client/scripts/htmldump.lua @@ -62,4 +62,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/lf_bulk.lua b/client/scripts/lf_bulk.lua index b4604bebb..dc59572f3 100644 --- a/client/scripts/lf_bulk.lua +++ b/client/scripts/lf_bulk.lua @@ -190,4 +190,4 @@ local function main(args) end end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 18078b822..ff739683d 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -272,4 +272,4 @@ local function main(args) print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec') end -main( args) \ No newline at end of file +main( args) diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index 4a740d7e6..0bb597a52 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -244,4 +244,4 @@ local function main( args) prlog(string.format("Dumped data into %s", filename)) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/ntag_3d.lua b/client/scripts/ntag_3d.lua index 890f29d94..2f08aac85 100644 --- a/client/scripts/ntag_3d.lua +++ b/client/scripts/ntag_3d.lua @@ -380,4 +380,4 @@ local function main(args) write_tag(uid, t) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/parameters.lua b/client/scripts/parameters.lua index f51266f7f..4eb86446d 100644 --- a/client/scripts/parameters.lua +++ b/client/scripts/parameters.lua @@ -42,4 +42,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/test_t55x7_ask.lua b/client/scripts/test_t55x7_ask.lua index 3f224b28a..0e0d3d9e3 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/scripts/test_t55x7_ask.lua @@ -137,4 +137,4 @@ local function main(args) test() print( string.rep('--',20) ) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/test_t55x7_fsk.lua b/client/scripts/test_t55x7_fsk.lua index 9dbb1b6bb..492f71681 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/scripts/test_t55x7_fsk.lua @@ -137,4 +137,4 @@ local function main(args) test(7) print( string.rep('--',20) ) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index 2a5545497..f48abff6c 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -282,4 +282,4 @@ local function main(args) core.clearCommandBuffer() end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/tracetest.lua b/client/scripts/tracetest.lua index 96d1f79c6..c3ddedf87 100644 --- a/client/scripts/tracetest.lua +++ b/client/scripts/tracetest.lua @@ -123,4 +123,4 @@ local function main(args) print( string.rep('--',20) ) end -main(args) \ No newline at end of file +main(args) diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua index 67949fd94..f91949166 100644 --- a/client/scripts/ufodump.lua +++ b/client/scripts/ufodump.lua @@ -173,4 +173,4 @@ if "--test"==args then else -- Call the main main(args) -end \ No newline at end of file +end diff --git a/client/snooper.c b/client/snooper.c index 88a30edaa..35267bc22 100644 --- a/client/snooper.c +++ b/client/snooper.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Snooper binary +// Sniff binary //----------------------------------------------------------------------------- #include "util_posix.h" @@ -19,7 +19,7 @@ int main() { usb_init(); - SetLogFilename("snooper.log"); + SetLogFilename("sniffer.log"); return_on_error = 1; @@ -27,7 +27,7 @@ int main() { while (!OpenProxmark()) { sleep(1); } while (1) { UsbCommand cmdbuf; - CommandReceived("hf 14a snoop"); + CommandReceived("hf 14a sniff"); HANDLE_ERROR; ReceiveCommand(&cmdbuf); HANDLE_ERROR; diff --git a/client/util.c b/client/util.c index 0b3211264..a3f275a0b 100644 --- a/client/util.c +++ b/client/util.c @@ -252,7 +252,10 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea // loop through the out_index to make sure we don't go too far for (out_index = 0; out_index < rowlen; out_index++) { // set character - sprintf(tmp++, "%u", data[in_index]); + if (data[in_index] == 7) // Manchester wrong bit marker + sprintf(tmp++, "."); + else + sprintf(tmp++, "%u", data[in_index]); // check if a line break is needed and we have room to print it in our array if ((breaks > 0) && !((in_index + 1) % breaks) && (out_index + 1 != rowlen)) { // increment and print line break @@ -683,24 +686,45 @@ int hextobinstring(char *target, char *source) { return length; } -// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source) +// convert binary array of 0x00/0x01 values to hex // return number of bits converted -int binarraytohex(char *target, char *source, int length) { - unsigned char i, x; - int j = length; - - if (j % 4) - return 0; - - while (j) { - for (i = x = 0 ; i < 4 ; ++i) - x += (source[i] << (3 - i)); - sprintf(target, "%X", x); - ++target; - source += 4; - j -= 4; +int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen) { + uint8_t i = 0, x = 0; + uint32_t t = 0; // written target chars + uint32_t r = 0; // consumed bits + uint8_t w = 0; // wrong bits separator printed + for (size_t s = 0 ; s < srclen; s++) { + if ((source[s] == 0) || (source[s] == 1)) { + w = 0; + x += (source[s] << (3 - i)); + i++; + if (i == 4) { + if (t >= targetlen - 2) return r; + sprintf(target + t, "%X", x); + t++; + r += 4; + x = 0; + i = 0; + } + } else { + if (i > 0) { + if (t >= targetlen - 5) return r; + w = 0; + sprintf(target + t, "%X[%i]", x, i); + t += 4; + r += i; + x = 0; + i = 0; + } + if (w == 0) { + if (t >= targetlen - 2) return r; + sprintf(target + t, " "); + t++; + } + r++; + } } - return length; + return r; } // convert binary array to human readable binary @@ -873,4 +897,4 @@ extern char *strmcopy(char *buf) { strcpy(str, buf); } return str; -} \ No newline at end of file +} diff --git a/client/util.h b/client/util.h index 9c68900e7..c754542ab 100644 --- a/client/util.h +++ b/client/util.h @@ -241,7 +241,7 @@ extern int param_getstr(const char *line, int paramnum, char *str, size_t buffer extern int hextobinarray(char *target, char *source); extern int hextobinstring(char *target, char *source); -extern int binarraytohex(char *target, char *source, int length); +extern int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen); extern void binarraytobinstring(char *target, char *source, int length); extern uint8_t GetParity(uint8_t *string, uint8_t type, int length); extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); @@ -263,4 +263,4 @@ extern bool str_startswith(const char *s, const char *pre); // check for prefi extern void strcleanrn(char *buf, size_t len); extern void strcreplace(char *buf, size_t len, char from, char to); extern char *strmcopy(char *buf); -#endif \ No newline at end of file +#endif diff --git a/client/util_darwin.h b/client/util_darwin.h index 15af75404..d89b681f2 100644 --- a/client/util_darwin.h +++ b/client/util_darwin.h @@ -16,4 +16,4 @@ void enableAppNap(); void makeUnfocusable(); void makeFocusable(); -#endif \ No newline at end of file +#endif diff --git a/common/bucketsort.h b/common/bucketsort.h index 1de175ae5..0a56509c1 100644 --- a/common/bucketsort.h +++ b/common/bucketsort.h @@ -21,4 +21,4 @@ typedef struct bucket_info { void bucket_sort_intersect(uint32_t *const estart, uint32_t *const estop, uint32_t *const ostart, uint32_t *const ostop, bucket_info_t *bucket_info, bucket_array_t bucket); -#endif \ No newline at end of file +#endif diff --git a/common/cmd.c b/common/cmd.c index 5f42c669a..3b45c08ad 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -61,4 +61,4 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void #endif return sendlen; -} \ No newline at end of file +} diff --git a/common/crc.c b/common/crc.c index 0846697de..2ad7609b1 100644 --- a/common/crc.c +++ b/common/crc.c @@ -123,4 +123,4 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) { for (int i = 0; i < size; ++i) crc_update2(&crc, buff[i], 8); return reflect8(crc_finish(&crc)); -} \ No newline at end of file +} diff --git a/common/crc16.h b/common/crc16.h index b88995a40..9a202f514 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -67,4 +67,4 @@ void reset_table(void); void generate_table(uint16_t polynomial, bool refin); uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bool refout); -#endif \ No newline at end of file +#endif diff --git a/common/crc32.c b/common/crc32.c index 3ee102ce5..440bed910 100644 --- a/common/crc32.c +++ b/common/crc32.c @@ -29,4 +29,4 @@ void crc32_ex(const uint8_t *data, const size_t len, uint8_t *crc) { void crc32_append(uint8_t *data, const size_t len) { crc32_ex(data, len, data + len); -} \ No newline at end of file +} diff --git a/common/crc64.c b/common/crc64.c index 7d582da02..23360f6bd 100644 --- a/common/crc64.c +++ b/common/crc64.c @@ -80,4 +80,4 @@ void crc64(const uint8_t *data, const size_t len, uint64_t *crc) { } } -//suint8_t x = (c & 0xFF00000000000000 ) >> 56; \ No newline at end of file +//suint8_t x = (c & 0xFF00000000000000 ) >> 56; diff --git a/common/i2c.h b/common/i2c.h index 4254a73c3..df7f6698c 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -48,4 +48,4 @@ void SmartCardUpgrade(uint64_t arg0); void SmartCardSetBaud(uint64_t arg0); void SmartCardSetClock(uint64_t arg0); void I2C_print_status(void); -#endif \ No newline at end of file +#endif diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 7b64c99d1..795d1be60 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -14,12 +14,13 @@ // return: ptr to string char *Iso15693sprintUID(char *target, uint8_t *uid) { - static char tempbuf[2 * 8 + 1] = {0}; + static char tempbuf[3 * 8 + 1] = {0}; if (target == NULL) target = tempbuf; + sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0] ); return target; -} \ No newline at end of file +} diff --git a/common/iso15693tools.h b/common/iso15693tools.h index d7a1b2bb5..26a7a87a7 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -123,4 +123,4 @@ static const int Iso15693FrameEOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -#endif \ No newline at end of file +#endif diff --git a/common/legic_prng.c b/common/legic_prng.c index fd5543cf7..5406161fc 100644 --- a/common/legic_prng.c +++ b/common/legic_prng.c @@ -62,4 +62,4 @@ uint32_t legic_prng_get_bits(uint8_t len) { legic_prng_forward(1); } return a; -} \ No newline at end of file +} diff --git a/common/lfdemod.c b/common/lfdemod.c index f356e7578..653c2a308 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1357,6 +1357,7 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { //by marshmellow //take 10 and 01 and manchester decode //run through 2 times and take least errCnt +// "7" indicates 00 or 11 wrong bit int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) { // sanity check @@ -1368,7 +1369,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) //find correct start position [alignment] for (k = 0; k < 2; ++k) { - for (i = k; i < *size - 3; i += 2) { + for (i = k; i < *size - 1; i += 2) { if (bits[i] == bits[i + 1]) errCnt++; } @@ -1380,7 +1381,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) } *alignPos = bestRun; //decode - for (i = bestRun; i < *size - 3; i += 2) { + for (i = bestRun; i < *size - 1; i += 2) { if (bits[i] == 1 && (bits[i + 1] == 0)) { bits[bitnum++] = invert; } else if ((bits[i] == 0) && bits[i + 1] == 1) { diff --git a/common/lfdemod.h b/common/lfdemod.h index 883393cc3..96a91363f 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -22,7 +22,7 @@ #include "util.h" // for ARRAYLEN //might not be high enough for noisy environments -#define NOISE_AMPLITUDE_THRESHOLD 10 +#define NOISE_AMPLITUDE_THRESHOLD 15 //ignore buffer with less than x samples #define SIGNAL_MIN_SAMPLES 100 //ignore first x samples of the buffer diff --git a/common/prng.h b/common/prng.h index f160d6b30..b9f49c6b6 100644 --- a/common/prng.h +++ b/common/prng.h @@ -21,4 +21,4 @@ void burtle_init_mod(prng_ctx *x, uint32_t seed); void burtle_init(prng_ctx *x, uint32_t seed); uint32_t GetSimplePrng(uint32_t seed); -#endif /* __PRNG_H */ \ No newline at end of file +#endif /* __PRNG_H */ diff --git a/common/protocols.h b/common/protocols.h index fde10f38a..f8ed2781e 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -276,6 +276,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO_15693 7 #define FELICA 8 #define PROTO_MIFARE 9 +#define PROTO_HITAG 10 //-- Picopass fuses #define FUSE_FPERS 0x80 diff --git a/common/radixsort.c b/common/radixsort.c index 67f2910c1..83b26d609 100644 --- a/common/radixsort.c +++ b/common/radixsort.c @@ -96,4 +96,4 @@ uint64_t *radixSort(uint64_t *array, uint32_t size) { } free(cpy); return array; -} \ No newline at end of file +} diff --git a/common/radixsort.h b/common/radixsort.h index 29faf9825..41a036461 100644 --- a/common/radixsort.h +++ b/common/radixsort.h @@ -20,4 +20,4 @@ typedef union { } rscounts_t; uint64_t *radixSort(uint64_t *array, uint32_t size); -#endif // RADIXSORT_H__ \ No newline at end of file +#endif // RADIXSORT_H__ diff --git a/common/random.h b/common/random.h index 315794f8d..85c90dd38 100644 --- a/common/random.h +++ b/common/random.h @@ -18,4 +18,4 @@ void fast_prand(); void fast_prandEx(uint32_t seed); uint32_t prand(); -#endif \ No newline at end of file +#endif diff --git a/common/tea.h b/common/tea.h index 3a12a769d..43ac93428 100644 --- a/common/tea.h +++ b/common/tea.h @@ -15,4 +15,4 @@ #include void tea_encrypt(uint8_t *v, uint8_t *key); void tea_decrypt(uint8_t *v, uint8_t *key); -#endif /* __TEA_H */ \ No newline at end of file +#endif /* __TEA_H */ diff --git a/common/usart.c b/common/usart.c index 46e8517fc..869179091 100644 --- a/common/usart.c +++ b/common/usart.c @@ -140,4 +140,4 @@ void usart_init(void) { // re-enable receiver / transmitter pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); -} \ No newline at end of file +} diff --git a/common/usb_cdc.c b/common/usb_cdc.c index d70c8ee04..c871de241 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -949,4 +949,4 @@ void AT91F_CDC_Enumerate() { AT91F_USB_SendStall(pUdp); break; } -} \ No newline at end of file +} diff --git a/common/wiegand.c b/common/wiegand.c index 2da88b085..e319e1a08 100644 --- a/common/wiegand.c +++ b/common/wiegand.c @@ -236,4 +236,4 @@ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, default: break; } -} \ No newline at end of file +} diff --git a/include/at91sam7s512.h b/include/at91sam7s512.h index f8fa2e8d4..f9f5f69b1 100644 --- a/include/at91sam7s512.h +++ b/include/at91sam7s512.h @@ -375,7 +375,7 @@ typedef struct _AT91S_DBGU { #define AT91C_US_TXBUFE (0x1 << 11) // (DBGU) TXBUFE Interrupt #define AT91C_US_RXBUFF (0x1 << 12) // (DBGU) RXBUFF Interrupt #define AT91C_US_COMM_TX (0x1 << 30) // (DBGU) COMM_TX Interrupt -#define AT91C_US_COMM_RX (0x1 << 31) // (DBGU) COMM_RX Interrupt +#define AT91C_US_COMM_RX (0x1u << 31) // (DBGU) COMM_RX Interrupt // -------- DBGU_IDR : (DBGU Offset: 0xc) Debug Unit Interrupt Disable Register -------- // -------- DBGU_IMR : (DBGU Offset: 0x10) Debug Unit Interrupt Mask Register -------- // -------- DBGU_CSR : (DBGU Offset: 0x14) Debug Unit Channel Status Register -------- diff --git a/include/common.h b/include/common.h index 2c3febc98..8bf8ab702 100644 --- a/include/common.h +++ b/include/common.h @@ -115,4 +115,4 @@ typedef struct { #ifdef __cplusplus } #endif -#endif \ No newline at end of file +#endif diff --git a/include/hitag.h b/include/hitag.h new file mode 100644 index 000000000..742d7ecd0 --- /dev/null +++ b/include/hitag.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// 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. +//----------------------------------------------------------------------------- +// Hitag2, HitagS +// +// (c) 2012 Roel Verdult +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + + +#ifndef HITAG_H__ +#define HITAG_H__ + +#ifdef _MSC_VER +#define PACKED +#else +#define PACKED __attribute__((packed)) +#endif + +typedef enum { + RHTSF_CHALLENGE = 01, + RHTSF_KEY = 02, + WHTSF_CHALLENGE = 03, + WHTSF_KEY = 04, + RHT2F_PASSWORD = 21, + RHT2F_AUTHENTICATE = 22, + RHT2F_CRYPTO = 23, + WHT2F_CRYPTO = 24, + RHT2F_TEST_AUTH_ATTEMPTS = 25, + RHT2F_UID_ONLY = 26, +} hitag_function; + +typedef struct { + uint8_t password[4]; +} PACKED rht2d_password; + +typedef struct { + uint8_t NrAr[8]; + uint8_t data[4]; +} PACKED rht2d_authenticate; + +typedef struct { + uint8_t key[6]; + uint8_t data[4]; +} PACKED rht2d_crypto; + +typedef union { + rht2d_password pwd; + rht2d_authenticate auth; + rht2d_crypto crypto; +} hitag_data; + + +//--------------------------------------------------------- +// Hitag S +//--------------------------------------------------------- +// protocol-state +typedef enum PROTO_STATE { + HT_READY = 0, + HT_INIT, + HT_AUTHENTICATE, + HT_SELECTED, + HT_QUIET, + HT_TTF, + HT_FAIL +} PSTATE; + +typedef enum TAG_STATE { + HT_NO_OP = 0, + HT_READING_PAGE, + HT_WRITING_PAGE_ACK, + HT_WRITING_PAGE_DATA, + HT_WRITING_BLOCK_DATA +} TSATE; + +//number of start-of-frame bits +typedef enum SOF_TYPE { + HT_STANDARD = 0, + HT_ADVANCED, + HT_FAST_ADVANCED, + HT_ONE, + HT_NO_BITS +} stype; + +struct hitagS_tag { + PSTATE pstate; //protocol-state + TSATE tstate; //tag-state + uint32_t uid; + uint8_t pages[64][4]; + uint64_t key; + uint8_t pwdl0, pwdl1, pwdh0; + //con0 + int max_page; + stype mode; + //con1 + bool auth; //0=Plain 1=Auth + bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase + int TTFDR; //data rate in TTF Mode + int TTFM; //the number of pages that are sent to the RWD + bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP + bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode + //con2 + //0=read write 1=read only + bool LCK7; //page4/5 + bool LCK6; //page6/7 + bool LCK5; //page8-11 + bool LCK4; //page12-15 + bool LCK3; //page16-23 + bool LCK2; //page24-31 + bool LCK1; //page32-47 + bool LCK0; //page48-63 +}; + +#endif diff --git a/include/mifare.h b/include/mifare.h index 104d5cf09..ae5500986 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -71,7 +71,8 @@ typedef enum ISO14B_COMMAND { ISO14B_REQUEST_TRIGGER = (1 << 4), ISO14B_APPEND_CRC = (1 << 5), ISO14B_SELECT_STD = (1 << 6), - ISO14B_SELECT_SR = (1 << 7) + ISO14B_SELECT_SR = (1 << 7), + ISO14B_SET_TIMEOUT = (1 << 8), } iso14b_command_t; typedef enum ISO15_COMMAND { diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 94ae66eaa..a15229969 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -129,7 +129,7 @@ typedef struct { #define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_CLONE_TAG 0x021B #define CMD_EM410X_DEMOD 0x021c -// Sampling configuration for LF reader/snooper +// Sampling configuration for LF reader/sniffer #define CMD_SET_LF_SAMPLING_CONFIG 0x021d #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F @@ -154,10 +154,10 @@ typedef struct { #define CMD_ISO_15693_COMMAND 0x0313 #define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 +#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 // For Hitag2 transponders -#define CMD_SNOOP_HITAG 0x0370 +#define CMD_SNIFF_HITAG 0x0370 #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 @@ -170,9 +170,9 @@ typedef struct { #define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNOOP_ISO_14443B 0x0382 +#define CMD_SNIFF_ISO_14443B 0x0382 -#define CMD_SNOOP_ISO_14443a 0x0383 +#define CMD_SNIFF_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 @@ -192,7 +192,7 @@ typedef struct { #define CMD_ICLASS_READCHECK 0x038F #define CMD_ICLASS_CLONE 0x0390 #define CMD_ICLASS_DUMP 0x0391 -#define CMD_SNOOP_ICLASS 0x0392 +#define CMD_SNIFF_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS_REPLAY 0x0395 @@ -204,7 +204,7 @@ typedef struct { // For ISO1092 / FeliCa #define CMD_FELICA_SIMULATE_TAG 0x03A0 -#define CMD_FELICA_SNOOP 0x03A1 +#define CMD_FELICA_SNIFF 0x03A1 #define CMD_FELICA_COMMAND 0x03A2 //temp #define CMD_FELICA_LITE_DUMP 0x03AA diff --git a/proxmark3.sh b/proxmark3.sh index 34691b95a..b109d82e6 100755 --- a/proxmark3.sh +++ b/proxmark3.sh @@ -2,7 +2,7 @@ function wait4proxmark_Linux { echo >&2 "Waiting for Proxmark to appear..." - while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do + while [ ! -c /dev/ttyACM? -a ! -c /dev/pm3-? ]; do sleep .1 done local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` diff --git a/tools/Makefile b/tools/Makefile index 51a76677b..3b1dc1b0f 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -16,4 +16,4 @@ get_xorsearch: # Mingw # unzzip-big XORSearch_V1_11_2.zip # linux -# gunzip XORSearch_V1_11_2.zip \ No newline at end of file +# gunzip XORSearch_V1_11_2.zip diff --git a/tools/findbits_test.py b/tools/findbits_test.py index 4415ce726..db8dda8fa 100644 --- a/tools/findbits_test.py +++ b/tools/findbits_test.py @@ -65,4 +65,4 @@ class OutputBuffer(object): if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 023c84c8b..ed5cea206 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -4,7 +4,7 @@ # Normally a couple of lines of bash would be enough (see openpcd project, original firmware by Harald Welte and Milosch Meriac) # but this will, at least in theory, also work on Windows with our current compile environment. # -- Henryk Plötz 2009-09-28 -# Modified april 2014 because of the move to github. +# Modified april 2014 because of the move to github. # --- Martin Holst Swende # Modified january 2016 to work with Travis-CI # --- iceman @@ -19,9 +19,9 @@ my $ctime; # GIT status 0 = dirty, 1 = clean , 2 = undecided my $clean = 2; -# Do we have acces to git command? +# Do we have acces to git command? ####### -# solves some bug on macos i.e: +# solves some bug on macos i.e: ## # perl ../tools/mkversion.pl .. > version.c || cp ../common/default_version.c version.c # /usr/bin/which: /usr/bin/which: cannot execute binary file diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 0717a24cb..6107a564e 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -174,4 +174,4 @@ bool uart_send(const serial_port sp, const uint8_t *p_tx, const size_t len) { return WriteFile(((serial_port_windows *)sp)->hPort, p_tx, len, &txlen, NULL); } -#endif \ No newline at end of file +#endif From cfe2b2797e5f6f920886a1ab7ee14571ad607b1e Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 21:45:00 +0100 Subject: [PATCH 04/19] Revert "Merge branch 'master' into hf_mf_sim" This reverts commit cbea5d9d022483fefb3e714bcd6c6e834b71447b, reversing changes made to b66152feb2da37fe87bffae9a37054935c8707e9. --- .gitignore | 1 - CHANGELOG.md | 29 - HACKING.txt | 195 ++++--- Makefile | 8 +- README.md | 4 +- armsrc/BigBuf.c | 41 ++ armsrc/BigBuf.h | 1 + armsrc/Makefile | 4 +- armsrc/Standalone/hf_mattyrun.c | 2 +- armsrc/Standalone/hf_mattyrun.h | 2 +- armsrc/Standalone/hf_young.c | 2 +- armsrc/Standalone/hf_young.h | 2 +- armsrc/Standalone/lf_hidbrute.h | 2 +- armsrc/Standalone/lf_proxbrute.c | 2 +- armsrc/Standalone/lf_proxbrute.h | 2 +- armsrc/Standalone/lf_samyrun.c | 2 +- armsrc/Standalone/lf_samyrun.h | 2 +- armsrc/Standalone/standalone.h | 2 +- armsrc/aes.c | 2 +- armsrc/aes.h | 2 +- armsrc/appmain.c | 33 +- armsrc/apps.h | 20 +- armsrc/buzzer.c | 2 +- armsrc/desfire_crypto.c | 2 +- armsrc/desfire_key.c | 2 +- armsrc/desfire_key.h | 2 +- armsrc/epa.c | 7 +- armsrc/felica.c | 2 +- armsrc/flashmem.h | 2 +- armsrc/hfsnoop.c | 10 +- armsrc/hitag2.c | 465 +++++++++++----- armsrc/hitag2.h | 23 - armsrc/hitag2_crypto.c | 116 ---- armsrc/hitag2_crypto.h | 36 -- armsrc/hitagS.c | 766 +++++++++++++++----------- armsrc/hitagS.h | 31 -- armsrc/iclass.c | 4 +- armsrc/iso14443a.c | 2 +- armsrc/iso14443b.c | 8 +- armsrc/iso15693.c | 39 +- armsrc/lfops.c | 98 ++-- armsrc/lfsampling.c | 22 +- armsrc/lfsampling.h | 6 +- armsrc/mifarecmd.c | 4 +- armsrc/mifarecmd.h | 2 +- armsrc/mifaresniff.c | 2 +- armsrc/mifaresniff.h | 2 +- armsrc/pcf7931.c | 2 +- armsrc/pcf7931.h | 2 +- armsrc/start.c | 2 +- armsrc/string.h | 2 +- armsrc/ticks.h | 2 +- armsrc/util.h | 39 -- client/amiitool/amiitool.c | 2 +- client/cli.c | 2 +- client/cmdcrc.c | 2 +- client/cmddata.c | 40 +- client/cmddata.h | 2 +- client/cmdflashmem.c | 2 +- client/cmdflashmem.h | 2 +- client/cmdhf.c | 4 +- client/cmdhf14a.c | 2 +- client/cmdhf14b.c | 30 +- client/cmdhf15.c | 14 +- client/cmdhfepa.c | 2 +- client/cmdhffelica.c | 4 +- client/cmdhffido.h | 2 +- client/cmdhficlass.c | 8 +- client/cmdhflegic.c | 2 +- client/cmdhflist.c | 2 +- client/cmdhfmf.c | 6 +- client/cmdhfmfdesfire.h | 2 +- client/cmdhfmfp.h | 2 +- client/cmdlf.c | 29 +- client/cmdlfhitag.c | 554 +++++-------------- client/cmdlfhitag.h | 9 +- client/cmdlft55xx.c | 6 +- client/cmdlfti.c | 2 +- client/cmdmain.c | 2 +- client/cmdscript.c | 2 +- client/cmdsmartcard.c | 167 ++---- client/cmdsmartcard.h | 3 +- client/cmdtrace.c | 46 +- client/crypto/libpcrypto.c | 15 - client/crypto/libpcrypto.h | 1 - client/emv/cmdemv.c | 2 - client/emv/emvjson.h | 2 +- client/fpga_compress.c | 18 +- client/hardnested/hardnested_tables.c | 2 +- client/hid-flasher/usb_cmd.h | 12 +- client/loclass/elite_crack.c | 2 +- client/loclass/fileutils.c | 54 +- client/loclass/fileutils.h | 8 +- client/lualibs/7816_error.lua | 2 +- client/lualibs/hf_reader.lua | 2 +- client/lualibs/precalc.lua | 2 +- client/lualibs/read14b.lua | 2 +- client/lualibs/taglib.lua | 2 +- client/lualibs/utils.lua | 2 +- client/mifare/mifarehost.h | 2 +- client/pm3_eml_mfd_test.py | 2 +- client/reveng/preset.c | 2 +- client/scandir.h | 2 +- client/scripting.c | 2 +- client/scripts/Legic_clone.lua | 2 +- client/scripts/brutesim.lua | 2 +- client/scripts/calc_di.lua | 2 +- client/scripts/calc_ev1_it.lua | 2 +- client/scripts/calc_mizip.lua | 2 +- client/scripts/calypso.lua | 2 +- client/scripts/e.lua | 2 +- client/scripts/emul2dump.lua | 2 +- client/scripts/emul2html.lua | 2 +- client/scripts/formatMifare.lua | 2 +- client/scripts/hf_read.lua | 2 +- client/scripts/htmldump.lua | 2 +- client/scripts/lf_bulk.lua | 2 +- client/scripts/mfkeys.lua | 2 +- client/scripts/ndef_dump.lua | 2 +- client/scripts/ntag_3d.lua | 2 +- client/scripts/parameters.lua | 2 +- client/scripts/test_t55x7_ask.lua | 2 +- client/scripts/test_t55x7_fsk.lua | 2 +- client/scripts/tnp3dump.lua | 2 +- client/scripts/tracetest.lua | 2 +- client/scripts/ufodump.lua | 2 +- client/snooper.c | 6 +- client/util.c | 60 +- client/util.h | 4 +- client/util_darwin.h | 2 +- common/bucketsort.h | 2 +- common/cmd.c | 2 +- common/crc.c | 2 +- common/crc16.h | 2 +- common/crc32.c | 2 +- common/crc64.c | 2 +- common/i2c.h | 2 +- common/iso15693tools.c | 5 +- common/iso15693tools.h | 2 +- common/legic_prng.c | 2 +- common/lfdemod.c | 5 +- common/lfdemod.h | 2 +- common/prng.h | 2 +- common/protocols.h | 1 - common/radixsort.c | 2 +- common/radixsort.h | 2 +- common/random.h | 2 +- common/tea.h | 2 +- common/usart.c | 2 +- common/usb_cdc.c | 2 +- common/wiegand.c | 2 +- include/at91sam7s512.h | 2 +- include/common.h | 2 +- include/hitag.h | 117 ---- include/mifare.h | 3 +- include/usb_cmd.h | 14 +- proxmark3.sh | 2 +- tools/Makefile | 2 +- tools/findbits_test.py | 2 +- tools/mkversion.pl | 6 +- uart/uart_win32.c | 2 +- 161 files changed, 1465 insertions(+), 2004 deletions(-) delete mode 100644 armsrc/hitag2.h delete mode 100644 armsrc/hitag2_crypto.c delete mode 100644 armsrc/hitag2_crypto.h delete mode 100644 armsrc/hitagS.h delete mode 100644 include/hitag.h diff --git a/.gitignore b/.gitignore index 9a12efbe5..785934f46 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ # don't push these files to the repository .history -.bash_history *.log *.eml *.o diff --git a/CHANGELOG.md b/CHANGELOG.md index 95c590a52..34bf817bd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,35 +3,6 @@ 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] - - Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox) - - Change - printing of fault bit markers (7) using a dot (@doegox) - - Change 'sc upgrade' - firmware file integrity check (@piwi) - - Fix 'data rawdemod am' - last bit was missing (@doegox) - - Fix 'hf 15 dump f' - also selects tag first (@iceman) - - Fix 'hf iclass clone' - missing fileclose (@iceman) - - Add 'trace list hitag' - old hitag annotations now use the new trace (@iceman) - - Change 'lf hitag sim' - loads bin/eml/json (@iceman) - - Change 'lf hitag reader 21' - saves in bin/eml/json (@iceman) - - Change 'lf hitag' - refactoring (@iceman) - - Change 'lf hitag' - refactoring (@piwi) - - Fix 'lf hitag' - generic fix for missing clock init (@piwi) - - Fix fsk sim operations on deviceside - avoid division by zero (@doegox) - - Fix 'hf mf fchk' - condition always false (@doegox) - - Fix 'lf t55xx recoverpw' - shift as u32 (@doegox) - - Fix 'lf ti demod' - shift as u32 (@doegox) - - Fix 'lf ti read' - shift as u32 (@doegox) - - Fix 'lf t55xx chk' - condition always false (@doegox) - - Change 'lf sim' - ledcontrol refactoring (@doegox) - - Fix 'hf mf nack' - signedness bug (@doegox) - - Fix 'hf epa cnonce' - check return value (@doegox) - - Fix 'lf hitag write' - condition always true (@doegox) - - Fix 'mem write' - added extra check (@doegox) - - Fix 'iso15693' - bad string cpy (@doegox) - - Fix 'make style' - EOF LF support (@doegox) - - Add 'hf 14b raw' - added -t for timeout (@iceman) - - Rename 'lf hitag snoop' - renamed to 'lf hitag sniff' (@iceman) - - Rename 'lf snoop' - renamed to 'lf sniff' (@iceman) - - Rename 'hf snoop' - renamed to 'hf sniff' (@iceman) - Fix 'hf mfp wrbl' - more blocks available (@merlokk) - Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox) - Change Makefiles optimizations when recompiling (@doegox) diff --git a/HACKING.txt b/HACKING.txt index 9d7bdaedc..fb68142e9 100644 --- a/HACKING.txt +++ b/HACKING.txt @@ -1,26 +1,38 @@ - "Coding styles are like assholes, everyone has one and no one likes anyone elses." - --Eric Warmenhoven + "Coding styles are like assholes, everyone has one and no one likes anyone elses." + --Eric Warmenhoven The Proxmark3 codebase is pretty messy and in the process of being cleaned up, so we don't have clear guidelines on how to place new code just yet. However, please don't make things worse. However, we have established a set of coding style guidelines in order to -clean up the code consistently and keep it consistent in the future. -Look around and respect the same style. -Helper script to get some uniformity in the style: - -$ make style - -It makes use of "astyle" so be sure to install it first. - +clean up the code consistently and keep it consistent in the future. Use common +sense and good taste. If breaking a rule leads to cleaner code, you can do so, +but laziness is not an excuse. === INDENTATION === -Don't use tabs, editors are messing them up too easily. -Increment unit is four spaces. +Use tabs for indentation, but use spaces for alignment: -If you use "make style", this will be done for you. + if (foo(this, that, there) + && bar == baz) + { + dostuff(); + } + +Notice it's like this (T___ for tab, S for space, for a 4-char tab setting): + +T___if (foo(this, that, there) +T___SSSS&& bar == baz) + +Another example: + +#define THIS 0x10 +#define THAT_THING 0x20 +#define SOMETHING_ELSE 0x80 + +These should look good no matter what your editor's tab setting is, so go nuts +and pick whatever you like best. === WIDTH === @@ -53,28 +65,24 @@ use microsoft-style DWORD and the like, we're getting rid of those. Avoid char for buffers, uint8_t is more obvious when you're not working with strings. Use 'const' where things are const. Try to use size_t for sizes. -Pointers and reference operators are attached to the variable name: - void *ptr; +Pointers are: + void *ptr; not: - void* ptr; + void* ptr; otherwise you're tempted to write: - void* in, out; + void* in, out; and you'll fail. -"make style" will take care of pointers & reference operators. - === EXPRESSIONS === In general, use whitespace around binary operators - no unspaced blobs of an -expression. "make style" will take care of whitespaces around operators. +expression. This rule may be broken if it makes things clearer. For example, -For example, - - if (5 * a < b && some_bool_var) + if (5*a < b && some_bool_var) but not - if (5*a 1 line, put braces +around them all. === FUNCTIONS === -Put the return type on the same line. -Put a space after a comma in argument lists. -Open the brace after the declaration (after a space). -"make style" will take care of all that. +Functions with no arguments are declared as f(void), not f(). Put the return +type on the same line. Use static for functions that aren't exported, and put +exported functions in a header file (one header file per source file with +exported functions usually, no huge headers with all functions). Put a space +after a comma in argument lists. -void foo(int a_thing, int something_else) { - ... +void foo(int a_thing, int something_else) +{ + ... } -Functions with no arguments are declared as f(void), not f(). -Use static for functions that aren't exported, and put exported functions -in a header file (one header file per source file with exported functions -usually, no huge headers with all functions). - -void baz(void) { - foo(bluh, blah); +void baz(void) +{ + foo(bluh, blah); } Function names should be separated_with_underscores(), except for standard functions (memcpy, etc.). It may make sense to break this rule for very common, generic functions that look like library functions (e.g. dprintf()). -Don't use single-character arguments. -Exception: very short functions with one argument that's really obvious: +Don't use single-character arguments. Exception: very short functions with one +argument that's really obvious: -static int ascii(char c) { - if (c < 0x20 || c >= 0x7f) - return '.'; - else - return c; +static int ascii(char c) +{ + if (c < 0x20 || c >= 0x7f) + return '.'; + else + return c; } vs. -static void hexdump(void *buf, size_t len) { - ... +static void hexdump(void *buf, size_t len) +{ + ... } As a general guideline, functions shouldn't usually be much more than 30-50 @@ -160,7 +188,7 @@ probably missing some factoring/restructuring opportunity. Use typedefs when defining structs. The type should be named something_t. typedef struct { - blah blah; + blah blah; } prox_cmd_t; You can use anonymous enums to replace lots of sequential or mostly-sequential @@ -171,18 +199,16 @@ You can use anonymous enums to replace lots of sequential or mostly-sequential Indent once for the case: labels, then again for the body. Like this: switch(bar) { - case OPTION_A: - do_stuff(); - break; - case OPTION_B: - do_other_stuff(); - break; + case OPTION_A: + do_stuff(); + break; + case OPTION_B: + do_other_stuff(); + break; } -"make style" will take care of the indentation. - -If you fall through into another case, add an explicit comment; -otherwise, it can look confusing. +If you fall through into another case, add an explicit comment; otherwise, it +can look confusing. If your switch() is too long or has too many cases, it should be cleaned up. Split off the cases into functions, break the switch() into parent and children @@ -192,12 +218,12 @@ the like. In other words, use common sense and your brain. If you need local scope variables for a case, you can add braces: switch(bar) { - case OPTION_A: { - int baz = 5 * bar; - do_stuff(baz); - break; - } - ... + case OPTION_A: { + int baz = 5*bar; + do_stuff(baz); + break; + } + ... But at that point you should probably consider using a separate function. @@ -240,7 +266,7 @@ License/description header first: //----------------------------------------------------------------------------- If you modify a file in any non-trivial way (add code, etc.), add your copyright -to the top with the current year. +to the top. === HEADER FILES === @@ -258,7 +284,8 @@ you shouldn't use it (same for _FOOBAR_H). === WHITESPACE === -Avoid trailing whitespace (no line should end in tab or space). -Keep a newline (blank line) at the end of each file. +Avoid trailing whitespace (no line should end in tab or space). People forget +this all the time if their editor doesn't handle it, but don't be surprised if +you see someone fixing it from time to time. -"make style" will take care of both. +Keep a newline (blank line) at the end of each file. diff --git a/Makefile b/Makefile index 6e7c9abd5..14bf98074 100644 --- a/Makefile +++ b/Makefile @@ -106,14 +106,8 @@ endif print-%: ; @echo $* = $($*) style: - # Make sure astyle is installed @which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 ) - # Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile - find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \ - -exec perl -pi -e 's/[ \t\r]+$$//' {} \; \ - -exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \ - -exec sh -c "echo >> {}" \; - # Apply astyle on *.c, *.h, *.cpp + find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "Makefile" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \ --indent=spaces=4 --indent-switches --indent-preprocessor \ --keep-one-line-blocks --max-instatement-indent=60 \ diff --git a/README.md b/README.md index cfdbacc61..c8c04f852 100644 --- a/README.md +++ b/README.md @@ -286,7 +286,7 @@ You will need to run these commands to make sure your rdv4 is prepared ### Verify sim module firmware version To make sure you got the latest sim module firmware. -_Lastest version is v3.11_ +_Lastest version is v3.10_ pm3 --> hw status @@ -298,7 +298,7 @@ Find version in the long output, look for these two lines This version is obselete. The following command upgrades your device sim module firmware. Don't not turn of your device during the execution of this command. - pm3 --> sc upgrade f ../tools/simmodule/SIM011.BIN + pm3 --> sc upgrade f ../tools/simmodule/SIM010.BIN You get the following output, this is a successful execution. diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 267e6811b..ab45a2681 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -195,6 +195,47 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_ return true; } +int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) { + /** + Todo, rewrite the logger to use the generic functionality instead. It should be noted, however, + that this logger takes number of bits as argument, not number of bytes. + **/ + + if (!tracing) return false; + + uint8_t *trace = BigBuf_get_addr(); + uint32_t iLen = nbytes(iBits); + // Return when trace is full + if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; + + //Hitag traces appear to use this traceformat: + // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag) + // 32 bits parity + // 8 bits size (number of bits in the trace entry, not number of bytes) + // y Bytes data + + rsamples += iSamples; + trace[traceLen++] = ((rsamples >> 0) & 0xff); + trace[traceLen++] = ((rsamples >> 8) & 0xff); + trace[traceLen++] = ((rsamples >> 16) & 0xff); + trace[traceLen++] = ((rsamples >> 24) & 0xff); + + if (!readerToTag) { + trace[traceLen - 1] |= 0x80; + } + + trace[traceLen++] = ((dwParity >> 0) & 0xff); + trace[traceLen++] = ((dwParity >> 8) & 0xff); + trace[traceLen++] = ((dwParity >> 16) & 0xff); + trace[traceLen++] = ((dwParity >> 24) & 0xff); + trace[traceLen++] = iBits; + + memcpy(trace + traceLen, btBytes, iLen); + traceLen += iLen; + + return true; +} + // Emulator memory uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { uint8_t *mem = BigBuf_get_EM_addr(); diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index bdd2003be..995451b9b 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -42,5 +42,6 @@ extern void set_tracing(bool enable); extern void set_tracelen(uint32_t value); extern bool get_tracing(void); extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +extern int LogTraceHitag(const uint8_t *btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); #endif /* __BIGBUF_H */ diff --git a/armsrc/Makefile b/armsrc/Makefile index cf63f6356..3c93c4af8 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -38,7 +38,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ -DWITH_ISO14443a \ -DWITH_ICLASS \ -DWITH_FELICA \ - -DWITH_HFSNIFF \ + -DWITH_HFSNOOP \ -DWITH_LF_SAMYRUN \ -fno-strict-aliasing -ffunction-sections -fdata-sections @@ -60,7 +60,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2_crypto.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c +SRC_LF = lfops.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_ISO14443b = iso14443b.c diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 8cac76c35..bf4b71d61 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -433,4 +433,4 @@ void RunMod() { } } } -} +} \ No newline at end of file diff --git a/armsrc/Standalone/hf_mattyrun.h b/armsrc/Standalone/hf_mattyrun.h index 6602eba54..8b33e67c5 100644 --- a/armsrc/Standalone/hf_mattyrun.h +++ b/armsrc/Standalone/hf_mattyrun.h @@ -20,4 +20,4 @@ #define OPTS 2 -#endif /* __HF_MATTYRUN_H */ +#endif /* __HF_MATTYRUN_H */ \ No newline at end of file diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 4b7a87e99..99af4ef1e 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -259,4 +259,4 @@ void RunMod() { LED(selected + 1, 0); } } -} +} \ No newline at end of file diff --git a/armsrc/Standalone/hf_young.h b/armsrc/Standalone/hf_young.h index dcd8b13e7..46c0d1361 100644 --- a/armsrc/Standalone/hf_young.h +++ b/armsrc/Standalone/hf_young.h @@ -19,4 +19,4 @@ #define OPTS 2 -#endif /* __HF_YOUNG_H */ +#endif /* __HF_YOUNG_H */ \ No newline at end of file diff --git a/armsrc/Standalone/lf_hidbrute.h b/armsrc/Standalone/lf_hidbrute.h index 49b0af6c6..bc1cf2e31 100644 --- a/armsrc/Standalone/lf_hidbrute.h +++ b/armsrc/Standalone/lf_hidbrute.h @@ -21,4 +21,4 @@ void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc); -#endif /* __LF_HIDBRUTE_H */ +#endif /* __LF_HIDBRUTE_H */ \ No newline at end of file diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index 178ce98fb..ea1bd1f6f 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -164,4 +164,4 @@ void RunMod() { out: DbpString("[=] exiting"); LEDsoff(); -} +} \ No newline at end of file diff --git a/armsrc/Standalone/lf_proxbrute.h b/armsrc/Standalone/lf_proxbrute.h index 3a9e1ce29..3911fee35 100644 --- a/armsrc/Standalone/lf_proxbrute.h +++ b/armsrc/Standalone/lf_proxbrute.h @@ -18,4 +18,4 @@ #define OPTS 2 -#endif /* __LF_PROXBRUTE_H */ +#endif /* __LF_PROXBRUTE_H */ \ No newline at end of file diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index b4530fa2f..ec0e4d19e 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -138,4 +138,4 @@ void RunMod() { out: DbpString("[=] exiting"); LEDsoff(); -} +} \ No newline at end of file diff --git a/armsrc/Standalone/lf_samyrun.h b/armsrc/Standalone/lf_samyrun.h index 52c0bb942..cf21e1261 100644 --- a/armsrc/Standalone/lf_samyrun.h +++ b/armsrc/Standalone/lf_samyrun.h @@ -19,4 +19,4 @@ #define OPTS 2 -#endif /* __LF_SAMYRUN_H */ +#endif /* __LF_SAMYRUN_H */ \ No newline at end of file diff --git a/armsrc/Standalone/standalone.h b/armsrc/Standalone/standalone.h index 980bcbf46..53d5ff13d 100644 --- a/armsrc/Standalone/standalone.h +++ b/armsrc/Standalone/standalone.h @@ -16,4 +16,4 @@ extern void RunMod(); -#endif /* __STANDALONE_H */ +#endif /* __STANDALONE_H */ \ No newline at end of file diff --git a/armsrc/aes.c b/armsrc/aes.c index f8a36f28c..61a8da76b 100644 --- a/armsrc/aes.c +++ b/armsrc/aes.c @@ -1167,4 +1167,4 @@ int main() { return 0; } -#endif +#endif \ No newline at end of file diff --git a/armsrc/aes.h b/armsrc/aes.h index aa9f0c582..afe7e5e4e 100644 --- a/armsrc/aes.h +++ b/armsrc/aes.h @@ -31,4 +31,4 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen); int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen); -#endif +#endif \ No newline at end of file diff --git a/armsrc/appmain.c b/armsrc/appmain.c index aecfee076..dbe20b2b7 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -650,8 +650,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; - case CMD_LF_SNIFF_RAW_ADC_SAMPLES: { - uint32_t bits = SniffLF(); + case CMD_LF_SNOOP_RAW_ADC_SAMPLES: { + uint32_t bits = SnoopLF(); cmd_send(CMD_ACK, bits, 0, 0, 0, 0); break; } @@ -664,13 +664,13 @@ void UsbPacketReceived(uint8_t *packet, int len) { CmdHIDsimTAG(c->arg[0], c->arg[1], 1); break; case CMD_FSK_SIM_TAG: - CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); + CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_ASK_SIM_TAG: - CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); + CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_PSK_SIM_TAG: - CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes, 1); + CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_HID_CLONE_TAG: CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); @@ -765,8 +765,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif #ifdef WITH_HITAG - case CMD_SNIFF_HITAG: // Eavesdrop Hitag tag, args = type - SniffHitag(c->arg[0]); + case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type + SnoopHitag(c->arg[0]); break; case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content SimulateHitagTag((bool)c->arg[0], (byte_t *)c->d.asBytes); @@ -786,7 +786,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge if ((hitag_function)c->arg[0] < 10) { WritePageHitagS((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); - } else { + } else if ((hitag_function)c->arg[0] >= 10) { WriterHitag((hitag_function)c->arg[0], (hitag_data *)c->d.asBytes, c->arg[2]); } break; @@ -843,7 +843,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_READ_SRI_TAG: ReadSTMemoryIso14443b(c->arg[0]); break; - case CMD_SNIFF_ISO_14443B: + case CMD_SNOOP_ISO_14443B: SniffIso14443b(); break; case CMD_SIMULATE_TAG_ISO_14443B: @@ -862,7 +862,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_FELICA_LITE_SIM: felica_sim_lite(c->arg[0]); break; - case CMD_FELICA_SNIFF: + case CMD_FELICA_SNOOP: felica_sniff(c->arg[0], c->arg[1]); break; case CMD_FELICA_LITE_DUMP: @@ -871,7 +871,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif #ifdef WITH_ISO14443a - case CMD_SNIFF_ISO_14443a: + case CMD_SNOOP_ISO_14443a: SniffIso14443a(c->arg[0]); break; case CMD_READER_ISO_14443a: @@ -1003,7 +1003,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { #ifdef WITH_ICLASS // Makes use of ISO14443a FPGA Firmware - case CMD_SNIFF_ICLASS: + case CMD_SNOOP_ICLASS: SniffIClass(); break; case CMD_SIMULATE_TAG_ICLASS: @@ -1043,9 +1043,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; #endif -#ifdef WITH_HFSNIFF +#ifdef WITH_HFSNOOP case CMD_HF_SNIFFER: - HfSniff(c->arg[0], c->arg[1]); + HfSnoop(c->arg[0], c->arg[1]); break; #endif @@ -1322,12 +1322,10 @@ void UsbPacketReceived(uint8_t *packet, int len) { // first mem page res = Flash_WriteDataCont(startidx, data, first_len); - isok = (res == first_len) ? 1 : 0; - // second mem page res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); - isok &= (res == (len - first_len)) ? 1 : 0; + isok = (res == (len - first_len)) ? 1 : 0; } else { res = Flash_WriteDataCont(startidx, data, len); @@ -1391,7 +1389,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { FlashStop(); cmd_send(CMD_ACK, 1, 0, 0, 0, 0); - BigBuf_free(); LED_B_OFF(); break; } diff --git a/armsrc/apps.h b/armsrc/apps.h index 57095a953..5bb92dc18 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -85,9 +85,9 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol); void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles); void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol); -void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); -void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); -void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol); +void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); +void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); +void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); @@ -222,12 +222,24 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); +// hitag2.h +void SnoopHitag(uint32_t type); +void SimulateHitagTag(bool tag_mem_supplied, byte_t *data); +void ReaderHitag(hitag_function htf, hitag_data *htd); +void WriterHitag(hitag_function htf, hitag_data *htd, int page); + +//hitagS.h +void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data); +void ReadHitagS(hitag_function htf, hitag_data *htd); +void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); +void check_challenges(bool file_given, byte_t *data); + // cmd.h uint8_t cmd_receive(UsbCommand *cmd); uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); // util.h -void HfSniff(int, int); +void HfSnoop(int, int); //felica.c extern void felica_sendraw(UsbCommand *c); diff --git a/armsrc/buzzer.c b/armsrc/buzzer.c index 708b7d3f7..27d0cd12a 100644 --- a/armsrc/buzzer.c +++ b/armsrc/buzzer.c @@ -83,4 +83,4 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_1,2*count); LED_B_ON(); */ -} +} \ No newline at end of file diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index fd3f30d0d..0a23305fd 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -630,4 +630,4 @@ void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *i mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size); offset += block_size; } -} +} \ No newline at end of file diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index e1f880c8b..a723a203e 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -152,4 +152,4 @@ void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfire Desfire_aes_key_new(buffer, key); break; } -} +} \ No newline at end of file diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h index 4fc02854e..adbda9c42 100644 --- a/armsrc/desfire_key.h +++ b/armsrc/desfire_key.h @@ -17,4 +17,4 @@ void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, uint8_t Desfire_key_get_version(desfirekey_t key); void Desfire_key_set_version(desfirekey_t key, uint8_t version); void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); -#endif +#endif \ No newline at end of file diff --git a/armsrc/epa.c b/armsrc/epa.c index 521bb3f69..95de11550 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -305,11 +305,6 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) { // initiate the PACE protocol // use the CAN for the password since that doesn't change func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); - // check if the command succeeded - if (func_return != 0) { - EPA_PACE_Collect_Nonce_Abort(4, func_return); - return; - } // now get the nonce uint8_t nonce[256] = {0}; @@ -317,7 +312,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) { func_return = EPA_PACE_Get_Nonce(requested_size, nonce); // check if the command succeeded if (func_return < 0) { - EPA_PACE_Collect_Nonce_Abort(5, func_return); + EPA_PACE_Collect_Nonce_Abort(4, func_return); return; } diff --git a/armsrc/felica.c b/armsrc/felica.c index 190960bd4..3aa3c282d 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -544,7 +544,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { int remFrames = (samplesToSkip) ? samplesToSkip : 0; - Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); + Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD); diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index f4258a11b..4af499d3a 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -151,4 +151,4 @@ void Flashmem_print_status(void); -#endif +#endif \ No newline at end of file diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 11ceff3d9..4ec60d175 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -4,9 +4,9 @@ #include "util.h" #include "usb_cdc.h" // for usb_poll_validate_length -static void RAMFUNC optimizedSniff(void); +static void RAMFUNC optimizedSnoop(void); -static void RAMFUNC optimizedSniff(void) { +static void RAMFUNC optimizedSnoop(void) { int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory uint16_t *dest = (uint16_t *)BigBuf_get_addr(); @@ -23,7 +23,7 @@ static void RAMFUNC optimizedSniff(void) { set_tracelen(BigBuf_max_traceLen()); } -void HfSniff(int samplesToSkip, int triggersToSkip) { +void HfSnoop(int samplesToSkip, int triggersToSkip) { BigBuf_free(); BigBuf_Clear(); @@ -66,14 +66,14 @@ void HfSniff(int samplesToSkip, int triggersToSkip) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) waitcount--; } - optimizedSniff(); + optimizedSnoop(); Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); } //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - DbpString("HF Sniffing end"); + DbpString("HF Snoop end"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 57200c701..f328ccb0d 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -3,35 +3,46 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Hitag2 emulation +// Hitag2 emulation (preliminary test version) // // (c) 2009 Henryk Plötz //----------------------------------------------------------------------------- // Hitag2 complete rewrite of the code // - Fixed modulation/encoding issues // - Rewrote code for transponder emulation -// - Added sniffing of transponder communication +// - Added snooping of transponder communication // - Added reader functionality // // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- -// Piwi, 2019 -// Iceman, 2019 -#include "hitag2.h" -#include "hitag2_crypto.h" -#include "hitag.h" #include "proxmark3.h" #include "apps.h" #include "util.h" +#include "hitag2.h" #include "string.h" #include "BigBuf.h" +static bool bQuiet; static bool bCrypto; static bool bAuthenticating; static bool bPwd; static bool bSuccessful; +struct hitag2_tag { + uint32_t uid; + enum { + TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr + TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password + TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands + TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written + } state; + unsigned int active_sector; + uint8_t crypto_active; + uint64_t cs; + uint8_t sectors[12][4]; +}; + static struct hitag2_tag tag = { .state = TAG_STATE_RESET, .sectors = { // Password mode: | Crypto mode: @@ -70,6 +81,87 @@ static uint8_t key[8]; static uint8_t writedata[4]; static uint64_t cipher_state; +/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ +// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. +// For educational purposes only. +// No warranties or guarantees of any kind. +// This code is released into the public domain by its author. + +// Basic macros: + +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) + +// Single bit Hitag2 functions: +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) + +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + +static u32 _f20(const u64 x) { + u32 i5; + + i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 + + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 + + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 + + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 + + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; + + return (ht2_f5c >> i5) & 1; +} + +static u64 _hitag2_init(const u64 key, const u32 serial, const u32 IV) { + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; + + for (i = 0; i < 32; i++) { + x >>= 1; + x += (u64)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; + } + return x; +} + +static u64 _hitag2_round(u64 *state) { + u64 x = *state; + + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) + ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) + ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) + ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); + + *state = x; + return _f20(x); +} + +// "MIKRON" = O N M I K R +// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key +// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear +// Random = 65 6E 45 72 - Random IV, transmitted in clear +//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + +// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". +// The inverse of the first 4 bytes is sent to the tag to authenticate. +// The rest is encrypted by XORing it with the subsequent keystream. + +static u32 _hitag2_byte(u64 *x) { + u32 i, c; + for (i = 0, c = 0; i < 8; i++) { + c += (u32) _hitag2_round(x) << (i ^ 7); + } + return c; +} + static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; @@ -81,13 +173,48 @@ static int hitag2_init(void) { return 0; } +static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) { + uint64_t key = ((uint64_t)tag->sectors[2][2]) | + ((uint64_t)tag->sectors[2][3] << 8) | + ((uint64_t)tag->sectors[1][0] << 16) | + ((uint64_t)tag->sectors[1][1] << 24) | + ((uint64_t)tag->sectors[1][2] << 32) | + ((uint64_t)tag->sectors[1][3] << 40); + uint32_t uid = ((uint32_t)tag->sectors[0][0]) | + ((uint32_t)tag->sectors[0][1] << 8) | + ((uint32_t)tag->sectors[0][2] << 16) | + ((uint32_t)tag->sectors[0][3] << 24); + uint32_t iv_ = (((uint32_t)(iv[0]))) | + (((uint32_t)(iv[1])) << 8) | + (((uint32_t)(iv[2])) << 16) | + (((uint32_t)(iv[3])) << 24); + tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_)); +} + +static int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) { + uint8_t authenticator_should[4]; + authenticator_should[0] = ~_hitag2_byte(cs); + authenticator_should[1] = ~_hitag2_byte(cs); + authenticator_should[2] = ~_hitag2_byte(cs); + authenticator_should[3] = ~_hitag2_byte(cs); + return (memcmp(authenticator_should, authenticator_is, 4) == 0); +} + +static int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, unsigned int bytes, unsigned int bits) { + int i; + for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs); + for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i); + return 0; +} + // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 -#ifndef T0 #define T0 192 -#endif + +#define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #define HITAG_FRAME_LEN 20 #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ @@ -114,6 +241,7 @@ static int hitag2_init(void) { #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 + static void hitag_send_bit(int bit) { LED_A_ON(); // Reset clock for the next bit @@ -151,6 +279,7 @@ static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { LOW(GPIO_SSC_DOUT); } + static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { uint8_t rx_air[HITAG_FRAME_LEN]; @@ -269,8 +398,8 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ break; } -// LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); -// LogTrace(tx, nbytes(txlen), 0, 0, NULL, true); +// LogTraceHitag(rx,rxlen,0,0,false); +// LogTraceHitag(tx,*txlen,0,0,true); if (tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen / 8, *txlen % 8); @@ -290,6 +419,7 @@ static void hitag_reader_send_bit(int bit) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6); + // SpinDelayUs(8*8); // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); @@ -305,6 +435,7 @@ static void hitag_reader_send_bit(int bit) { LED_A_OFF(); } + static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { @@ -474,8 +605,8 @@ static bool hitag2_crypto(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t * if (!bCrypto) { uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40; uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24; - Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((REV64(ui64key)) >> 32), (uint32_t)((REV64(ui64key)) & 0xffffffff), REV32(ui32uid)); - cipher_state = _hitag2_init(REV64(ui64key), REV32(ui32uid), 0); + Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t)((rev64(ui64key)) >> 32), (uint32_t)((rev64(ui64key)) & 0xffffffff), rev32(ui32uid)); + cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0); memset(tx, 0x00, 4); memset(tx + 4, 0xff, 4); hitag2_cipher_transcrypt(&cipher_state, tx + 4, 4, 0); @@ -670,10 +801,7 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t return true; } -void SniffHitag(uint32_t type) { - - StopTicks(); - +void SnoopHitag(uint32_t type) { int frame_count; int response; int overflow; @@ -686,8 +814,12 @@ void SniffHitag(uint32_t type) { size_t rxlen = 0; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); + + // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); @@ -697,18 +829,19 @@ void SniffHitag(uint32_t type) { auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - DbpString("Starting Hitag2 sniffing"); + DbpString("Starting Hitag2 snoop"); LED_D_ON(); // Set up eavesdropping mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Disable modulation, we are going to eavesdrop, not modulate ;) LOW(GPIO_SSC_DOUT); @@ -720,16 +853,14 @@ void SniffHitag(uint32_t type) { // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; + uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; + AT91C_BASE_TC1->TC_CMR = t1_channel_mode; // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // synchronized startup procedure - while (AT91C_BASE_TC1->TC_CV > 0) {}; // wait until TC0 returned to zero - // Reset the received frame, frame count and timing info memset(rx, 0x00, sizeof(rx)); frame_count = 0; @@ -840,7 +971,10 @@ void SniffHitag(uint32_t type) { // Check if frame was captured if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + if (!LogTraceHitag(rx, rxlen, response, 0, reader_frame)) { + DbpString("Trace full"); + break; + } // Check if we recognize a valid authentication attempt if (nbytes(rxlen) == 8) { @@ -871,46 +1005,49 @@ void SniffHitag(uint32_t type) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - // release allocated memory from BigBuff. - BigBuf_free(); - StartTicks(); - - DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_A_OFF(); + set_tracing(false); +// Dbprintf("frame received: %d",frame_count); +// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); +// DbpString("All done"); } void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { - - StopTicks(); - - int frame_count = 0, response = 0, overflow = 0; + int frame_count; + int response; + int overflow; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t tx[HITAG_FRAME_LEN]; size_t txlen = 0; + bool bQuitTraceFull = false; + bQuiet = false; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); + + // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); auth_table_len = 0; auth_table_pos = 0; - uint8_t *auth_table = BigBuf_malloc(AUTH_TABLE_LENGTH); + uint8_t *auth_table; + + auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - DbpString("Starting Hitag2 simulation"); - LED_D_ON(); hitag2_init(); @@ -931,40 +1068,40 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + SpinDelay(50); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - // Enable and reset counter - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; - // synchronized startup procedure - while (AT91C_BASE_TC1->TC_CV > 0); // wait until TC0 returned to zero + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; while (!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit @@ -1007,7 +1144,16 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Check if frame was captured if (rxlen > 4) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, true); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, true)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1024,8 +1170,19 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Send and store the tag answer (if there is any) if (txlen) { + // Transmit the tag frame hitag_send_frame(tx, txlen); - LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); + // Store the frame in the trace + if (!bQuiet) { + if (!LogTraceHitag(tx, txlen, 0, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } // Reset the received frame and response timing info @@ -1043,25 +1200,17 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - // release allocated memory from BigBuff. - BigBuf_free(); - - StartTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Sim Stopped"); + set_tracing(false); } void ReaderHitag(hitag_function htf, hitag_data *htd) { - - StopTicks(); - int frame_count = 0; int response = 0; uint8_t rx[HITAG_FRAME_LEN]; @@ -1084,6 +1233,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { Dbprintf("List identifier in password mode"); memcpy(password, htd->pwd.password, 4); blocknr = 0; + bQuiet = false; bPwd = false; break; } @@ -1091,6 +1241,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr, htd->auth.NrAr, 8); Dbhexdump(8, NrAr, false); + bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1100,6 +1251,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. Dbhexdump(6, key, false); blocknr = 0; + bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1108,11 +1260,13 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { Dbprintf("Testing %d authentication attempts", (auth_table_len / 8)); auth_table_pos = 0; memcpy(NrAr, auth_table, 8); + bQuiet = false; bCrypto = false; break; } case RHT2F_UID_ONLY: { blocknr = 0; + bQuiet = false; bCrypto = false; bAuthenticating = false; break; @@ -1120,48 +1274,45 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { default: { Dbprintf("Error, unknown function: %d", htf); set_tracing(false); - StartTicks(); return; } } FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - BigBuf_free(); + BigBuf_free(); clear_trace(); set_tracing(true); LED_D_ON(); hitag2_init(); + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; +// RELAY_OFF(); // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); - // PIO_A - BSR + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; @@ -1169,36 +1320,36 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero - // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings reset_sof = 1; t_wait = 200; + // DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings reset_sof = 1; t_wait = 200; + // DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings reset_sof = 4; t_wait = HITAG_T_WAIT_2; + // DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); - goto out; + goto out; } uint8_t attempt_count = 0; - - while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); + LogTraceHitag(rx, rxlen, response, 0, false); } // By default reset the transmission buffer @@ -1225,7 +1376,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { attempt_count++; //attempt 3 times to get uid then quit if (!bStop && attempt_count == 3) bStop = true; - + break; } default: { @@ -1254,7 +1405,7 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); } // Reset values for receiving frames @@ -1323,18 +1474,13 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } } - -out: + +out: LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - // release allocated memory from BigBuff. - BigBuf_free(); - StartTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); if (bSuccessful) cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); @@ -1343,10 +1489,8 @@ out: } void WriterHitag(hitag_function htf, hitag_data *htd, int page) { - - StopTicks(); - - int frame_count = 0, response = 0; + int frame_count; + int response; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; @@ -1358,13 +1502,17 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; + bool bQuitTraceFull = false; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + // Reset the return status + bSuccessful = false; + + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); - // Reset the return status - bSuccessful = false; + // DbpString("Starting Hitag reader family"); // Check configuration switch (htf) { @@ -1374,14 +1522,15 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { memcpy(writedata, htd->crypto.data, 4); Dbhexdump(6, key, false); blocknr = page; + bQuiet = false; bCrypto = false; bAuthenticating = false; + bQuitTraceFull = true; writestate = WRITE_STATE_START; } break; default: { Dbprintf("Error, unknown function: %d", htf); - StartTicks(); return; } break; @@ -1391,45 +1540,44 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { hitag2_init(); // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + + // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING - | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV > 0) {}; - // Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; lastbit = 1; bStop = false; @@ -1438,27 +1586,38 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // hitagS settings reset_sof = 1; t_wait = 200; + // DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings reset_sof = 1; t_wait = 200; + // DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings reset_sof = 4; t_wait = HITAG_T_WAIT_2; + // DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); return; } - - while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { - + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } // By default reset the transmission buffer @@ -1484,7 +1643,9 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); + + // Dbprintf("DEBUG: Sending reader frame"); // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1495,7 +1656,16 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } // Reset values for receiving frames @@ -1505,6 +1675,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { bSkip = true; tag_sof = reset_sof; response = 0; + // Dbprintf("DEBUG: Waiting to receive frame"); uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods @@ -1577,7 +1748,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } // if we saw over 100 wierd values break it probably isn't hitag... if (errorCount > 100) break; - // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) break; @@ -1590,15 +1760,14 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); } } + // Dbprintf("DEBUG: Done waiting for frame"); - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - StartTicks(); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // Dbprintf("frame received: %d",frame_count); + // DbpString("All done"); cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); } diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h deleted file mode 100644 index 2260e5f8d..000000000 --- a/armsrc/hitag2.h +++ /dev/null @@ -1,23 +0,0 @@ -//----------------------------------------------------------------------------- -// (c) 2012 Roel Verdult -// -// 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. -//----------------------------------------------------------------------------- -// Hitag2 type prototyping -//----------------------------------------------------------------------------- - -#ifndef _HITAG2_H_ -#define _HITAG2_H_ - -#include -#include -#include "hitag.h" - -void SniffHitag(uint32_t type); -void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); -void ReaderHitag(hitag_function htf, hitag_data *htd); -void WriterHitag(hitag_function htf, hitag_data *htd, int page); - -#endif diff --git a/armsrc/hitag2_crypto.c b/armsrc/hitag2_crypto.c deleted file mode 100644 index 7d1e10d87..000000000 --- a/armsrc/hitag2_crypto.c +++ /dev/null @@ -1,116 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- -// Hitag2 Crypto -// -// (c) 2009 Henryk Plötz -// (c) 2012 Roel Verdult -// (c) 2019 Iceman -//----------------------------------------------------------------------------- -#include "hitag2_crypto.h" - -/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ -// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. -// For educational purposes only. -// No warranties or guarantees of any kind. -// This code is released into the public domain by its author. - -// Single bit Hitag2 functions: -#ifndef i4 -#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -#endif - -static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 - -uint32_t _f20(const uint64_t x) { - uint32_t i5; - - i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 - + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 - + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 - + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 - + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; - - return (ht2_f5c >> i5) & 1; -} - -uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) { - uint32_t i; - uint64_t x = ((key & 0xFFFF) << 32) + serial; - - for (i = 0; i < 32; i++) { - x >>= 1; - x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; - } - return x; -} - -uint64_t _hitag2_round(uint64_t *state) { - uint64_t x = *state; - - x = (x >> 1) + - ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) - ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) - ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) - ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); - - *state = x; - return _f20(x); -} - -// "MIKRON" = O N M I K R -// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key -// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear -// Random = 65 6E 45 72 - Random IV, transmitted in clear -//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream - -// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". -// The inverse of the first 4 bytes is sent to the tag to authenticate. -// The rest is encrypted by XORing it with the subsequent keystream. - -uint32_t _hitag2_byte(uint64_t *x) { - uint32_t i, c; - for (i = 0, c = 0; i < 8; i++) { - c += (uint32_t) _hitag2_round(x) << (i ^ 7); - } - return c; -} - -void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) { - uint64_t key = ((uint64_t)tag->sectors[2][2]) | - ((uint64_t)tag->sectors[2][3] << 8) | - ((uint64_t)tag->sectors[1][0] << 16) | - ((uint64_t)tag->sectors[1][1] << 24) | - ((uint64_t)tag->sectors[1][2] << 32) | - ((uint64_t)tag->sectors[1][3] << 40); - uint32_t uid = ((uint32_t)tag->sectors[0][0]) | - ((uint32_t)tag->sectors[0][1] << 8) | - ((uint32_t)tag->sectors[0][2] << 16) | - ((uint32_t)tag->sectors[0][3] << 24); - uint32_t iv_ = (((uint32_t)(iv[0]))) | - (((uint32_t)(iv[1])) << 8) | - (((uint32_t)(iv[2])) << 16) | - (((uint32_t)(iv[3])) << 24); - tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_)); -} - -int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) { - uint8_t authenticator_should[4]; - authenticator_should[0] = ~_hitag2_byte(cs); - authenticator_should[1] = ~_hitag2_byte(cs); - authenticator_should[2] = ~_hitag2_byte(cs); - authenticator_should[3] = ~_hitag2_byte(cs); - return (memcmp(authenticator_should, authenticator_is, 4) == 0); -} - -int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) { - int i; - for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs); - for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i); - return 0; -} - diff --git a/armsrc/hitag2_crypto.h b/armsrc/hitag2_crypto.h deleted file mode 100644 index 8af1af412..000000000 --- a/armsrc/hitag2_crypto.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef __HITAG2_CRYPTO_H -#define __HITAG2_CRYPTO_H - -#ifdef __cplusplus -extern "C" { -#endif - -#include "string.h" -#include "util.h" - -struct hitag2_tag { - uint32_t uid; - enum { - TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr - TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password - TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands - TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written - } state; - uint16_t active_sector; - uint8_t crypto_active; - uint64_t cs; - uint8_t sectors[12][4]; -}; - -extern uint32_t _f20(const uint64_t x); -extern uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV); -extern uint64_t _hitag2_round(uint64_t *state); -extern uint32_t _hitag2_byte(uint64_t *x); -extern void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv); -extern int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is); -extern int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ; -#ifdef __cplusplus -} -#endif - -#endif diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 5fece9d26..b53112081 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -10,46 +10,109 @@ //----------------------------------------------------------------------------- // Some code was copied from Hitag2.c //----------------------------------------------------------------------------- - +#include +#include "proxmark3.h" +#include "apps.h" +#include "util.h" #include "hitagS.h" +#include "hitag2.h" +#include "string.h" +#include "BigBuf.h" #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) + static bool bQuiet; static bool bSuccessful; static struct hitagS_tag tag; static byte_t page_to_be_written = 0; static int block_data_left = 0; - typedef enum modulation { AC2K = 0, AC4K, MC4K, MC8K } MOD; - -static MOD m = AC2K; // used modulation +static MOD m = AC2K; //used modulation static uint32_t temp_uid; static int temp2 = 0; -static int sof_bits; // number of start-of-frame bits -static byte_t pwdh0, pwdl0, pwdl1; // password bytes -static uint32_t rnd = 0x74124485; // randomnumber +static int sof_bits; //number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; //password bytes +static uint32_t rnd = 0x74124485; //randomnumber static int test = 0; size_t blocknr; bool end = false; +// Single bit Hitag2 functions: +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 #define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) #define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) #define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) +#define uf20bs u32 + +static u32 f20(const u64 x) { + u32 i5; + + i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 + + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 + + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 + + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 + + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; + + return (ht2_f5c >> i5) & 1; +} +static u64 hitag2_round(u64 *state) { + u64 x = *state; + + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) + ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) + ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) + & 1) << 47); + + *state = x; + return f20(x); +} +static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) { + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; + for (i = 0; i < 32; i++) { + x >>= 1; + x += (u64)(f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; + } + return x; +} +static u32 hitag2_byte(u64 *x) { + u32 i, c; + + for (i = 0, c = 0; i < 8; i++) + c += (u32) hitag2_round(x) << (i ^ 7); + return c; +} // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 -#ifndef T0 #define T0 192 -#endif + +#define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #define HITAG_FRAME_LEN 20 #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ @@ -195,85 +258,100 @@ static void hitag_send_bit(int bit) { } } -static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { - // SOF - send start of frame +static void hitag_send_frame(const byte_t *frame, size_t frame_len) { +// Send start of frame + for (size_t i = 0; i < sof_bits; i++) { hitag_send_bit(1); } - // Send the content of the frame +// Send the content of the frame for (size_t i = 0; i < frame_len; i++) { hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } - +// Drop the modulation LOW(GPIO_SSC_DOUT); } static void hitag_reader_send_bit(int bit) { - +//Dbprintf("BIT: %d",bit); LED_A_ON(); - // Reset clock for the next bit +// Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Binary puls length modulation (BPLM) is used to encode the data stream - // This means that a transmission of a one takes longer than that of a zero +// Binary puls length modulation (BPLM) is used to encode the data stream +// This means that a transmission of a one takes longer than that of a zero +// Enable modulation, which means, drop the the field HIGH(GPIO_SSC_DOUT); - if (test == 1) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + // SpinDelayUs(8*8); + + // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; + + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; + + // SpinDelayUs(22*8); } } else { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + // SpinDelayUs(8*8); + + // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; + + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; + + // SpinDelayUs(22*8); } } LED_A_OFF(); } -static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { - // Send the content of the frame +static void hitag_reader_send_frame(const byte_t *frame, size_t frame_len) { +// Send the content of the frame for (size_t i = 0; i < frame_len; i++) { -// if (frame[0] == 0xf8) { - //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); -// } + if (frame[0] == 0xf8) { + //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); + } hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } - // send EOF +// Send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - +// Enable modulation, which means, drop the the field HIGH(GPIO_SSC_DOUT); - - // Wait for 4-10 times the carrier period +// Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; +// Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); } /* * to check if the right uid was selected */ -static int check_select(uint8_t *rx, uint32_t uid) { +static int check_select(byte_t *rx, uint32_t uid) { unsigned char resp[48]; int i; uint32_t ans = 0x0; @@ -281,32 +359,31 @@ static int check_select(uint8_t *rx, uint32_t uid) { resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; for (i = 0; i < 32; i++) ans += resp[5 + i] << (31 - i); - + /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 + && rx[4] == 0x65 && rx[5] == 0x38) + Dbprintf("got uid %X", ans);*/ temp_uid = ans; if (ans == tag.uid) return 1; - return 0; } /* * handles all commands from a reader */ -static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, - uint8_t *tx, size_t *txlen) { - uint8_t rx_air[HITAG_FRAME_LEN]; - uint8_t page; +static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, + byte_t *tx, size_t *txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; + byte_t page; int i; - uint64_t state; + u64 state; unsigned char crc; - // Copy the (original) received frame how it is send over the air +// Copy the (original) received frame how it is send over the air memcpy(rx_air, rx, nbytes(rxlen)); - - // Reset the transmission frame length +// Reset the transmission frame length *txlen = 0; - - // Try to find out which command was send by selecting on length (in bits) +// Try to find out which command was send by selecting on length (in bits) switch (rxlen) { case 5: { //UID request with a selected response protocol mode @@ -375,13 +452,11 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, Dbprintf("Challenge for UID: %X", temp_uid); temp2++; *txlen = 32; - state = _hitag2_init(REV64(tag.key), - REV32(tag.pages[0][0]), - REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])) - ); - Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", - rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); - + state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), + rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); + Dbprintf( + ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", + rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); switch (tag.mode) { case HT_STANDARD: sof_bits = 1; @@ -400,13 +475,12 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, } for (i = 0; i < 4; i++) - _hitag2_byte(&state); - - //send con2, pwdh0, pwdl0, pwdl1 encrypted as a response - tx[0] = _hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); - tx[1] = _hitag2_byte(&state) ^ tag.pwdh0; - tx[2] = _hitag2_byte(&state) ^ tag.pwdl0; - tx[3] = _hitag2_byte(&state) ^ tag.pwdl1; + hitag2_byte(&state); + //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response + tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); + tx[1] = hitag2_byte(&state) ^ tag.pwdh0; + tx[2] = hitag2_byte(&state) ^ tag.pwdl0; + tx[3] = hitag2_byte(&state) ^ tag.pwdl1; if (tag.mode != HT_STANDARD) { //add crc8 *txlen = 40; @@ -415,12 +489,14 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, calc_crc(&crc, tag.pwdh0, 8); calc_crc(&crc, tag.pwdl0, 8); calc_crc(&crc, tag.pwdl1, 8); - tx[4] = (crc ^ _hitag2_byte(&state)); + tx[4] = (crc ^ hitag2_byte(&state)); } /* * some readers do not allow to authenticate multiple times in a row with the same tag. * use this to change the uid between authentications. + */ + /* if (temp2 % 2 == 0) { tag.uid = 0x11223344; tag.pages[0][0] = 0x44332211; @@ -644,17 +720,18 @@ static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, /* * to autenticate to a tag with the given key or challenge */ -static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { - uint8_t rx_air[HITAG_FRAME_LEN]; +static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, byte_t *rx, const size_t rxlen, byte_t *tx, + size_t *txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; int response_bit[200]; int i, j, z, k; unsigned char mask = 1; unsigned char uid[32]; - uint8_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; + byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; unsigned char crc; - uint64_t state; - uint8_t auth_ks[4]; - uint8_t conf_pages[3]; + u64 state; + byte_t auth_ks[4]; + byte_t conf_pages[3]; memcpy(rx_air, rx, nbytes(rxlen)); *txlen = 0; @@ -680,45 +757,16 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA if (k > 31) break; } - uid1 = (uid[0] << 7) - | (uid[1] << 6) - | (uid[2] << 5) - | (uid[3] << 4) - | (uid[4] << 3) - | (uid[5] << 2) - | (uid[6] << 1) - | uid[7]; - - uid2 = (uid[8] << 7) - | (uid[9] << 6) - | (uid[10] << 5) - | (uid[11] << 4) - | (uid[12] << 3) - | (uid[13] << 2) - | (uid[14] << 1) - | uid[15]; - - uid3 = (uid[16] << 7) - | (uid[17] << 6) - | (uid[18] << 5) - | (uid[19] << 4) - | (uid[20] << 3) - | (uid[21] << 2) - | (uid[22] << 1) - | uid[23]; - - uid4 = (uid[24] << 7) - | (uid[25] << 6) - | (uid[26] << 5) - | (uid[27] << 4) - | (uid[28] << 3) - | (uid[29] << 2) - | (uid[30] << 1) - | uid[31]; - + uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) + | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; + uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) + | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; + uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) + | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; + uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) + | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; if (DEBUG) Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); - tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); //select uid @@ -729,40 +777,29 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA calc_crc(&crc, uid2, 8); calc_crc(&crc, uid3, 8); calc_crc(&crc, uid4, 8); - for (i = 0; i < 100; i++) { response_bit[i] = 0; } - for (i = 0; i < 5; i++) { response_bit[i] = 0; } - for (i = 5; i < 37; i++) { response_bit[i] = uid[i - 5]; } - for (j = 0; j < 8; j++) { response_bit[i] = 0; if ((crc & ((mask << 7) >> j)) != 0) response_bit[i] = 1; i++; } - k = 0; for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) - | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) - | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) - | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) - | response_bit[k + 7]; - + tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) | response_bit[k + 7]; k += 8; } - tag.pstate = HT_INIT; } else if (tag.pstate == HT_INIT && rxlen == 44) { // received configuration after select command @@ -810,17 +847,18 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA tag.LCK0 = response_bit[27]; if (DEBUG) - Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); - + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], + conf_pages[1], conf_pages[2]); if (tag.auth == 1) { //if the tag is in authentication mode try the key or challenge *txlen = 64; if (end != true) { if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY - state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); + state = hitag2_init(rev64(key), rev32(tag.uid), + rev32(rnd)); for (i = 0; i < 4; i++) { - auth_ks[i] = _hitag2_byte(&state) ^ 0xff; + auth_ks[i] = hitag2_byte(&state) ^ 0xff; } *txlen = 64; tx[0] = rnd & 0xff; @@ -868,18 +906,21 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA pwdl1 = 0; if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY { - state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); + state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); for (i = 0; i < 5; i++) - _hitag2_byte(&state); - - pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) ^ _hitag2_byte(&state); - pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) ^ _hitag2_byte(&state); - pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state); + hitag2_byte(&state); + pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) + ^ hitag2_byte(&state); } if (DEBUG) Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); + //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); //rnd += 1; } @@ -892,22 +933,18 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA /* * Emulates a Hitag S Tag with the given data from the .hts file */ -void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { - - StopTicks(); - - int frame_count = 0, response = 0, overflow = 0; +void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { + int frame_count; + int response; + int overflow; int i, j; - uint8_t rx[HITAG_FRAME_LEN]; + byte_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; + //bool bQuitTraceFull = false; bQuiet = false; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t *tx = txbuf; size_t txlen = 0; - - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); @@ -921,18 +958,16 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { tag.pstate = HT_READY; tag.tstate = HT_NO_OP; - for (i = 0; i < 16; i++) for (j = 0; j < 4; j++) tag.pages[i][j] = 0x0; - - // read tag data into memory + //read tag data into memory if (tag_mem_supplied) { DbpString("Loading hitagS memory..."); - memcpy((uint8_t *)tag.pages, data, 4 * 64); + memcpy((byte_t *)tag.pages, data, 4 * 64); } - tag.uid = (uint32_t)tag.pages[0]; + Dbprintf("Hitag S simulation started"); tag.key = (intptr_t)tag.pages[3]; tag.key <<= 16; tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1]; @@ -982,48 +1017,48 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { if ((tag.pages[1][1] & 0x1) == 0x01) tag.LCK0 = 1; - // Set up simulator mode, frequency divisor which will drive the FPGA - // and analog mux selection. +// Set up simulator mode, frequency divisor which will drive the FPGA +// and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + SpinDelay(20); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Configure output pin that is connected to the FPGA (for modulating) +// Configure output pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Disable modulation at default, which means release resistance +// Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; +// Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on rising edge of TIOA. +// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - // Enable and reset counter - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; +// Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; + +// Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - + while (!BUTTON_PRESS()) { + // Watchdog hit WDT_HIT(); // Receive frame, watch for at most T0*EOF periods @@ -1063,7 +1098,12 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // Check if frame was captured if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, true); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, true)) { + DbpString("Trace full"); + clear_trace(); + } + } // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1076,13 +1116,20 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) // periods. The gap time T_Low varies (4..10). All timer values are in // terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) {}; + while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) + ; // Send and store the tag answer (if there is any) if (txlen > 0) { // Transmit the tag frame hitag_send_frame(tx, txlen); - LogTrace(tx, nbytes(txlen), 0, 0, NULL, false); + // Store the frame in the trace + if (!bQuiet) { + if (!LogTraceHitag(tx, txlen, 0, 0, false)) { + DbpString("Trace full"); + clear_trace(); + } + } } // Reset the received frame and response timing info @@ -1100,19 +1147,11 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - // release allocated memory from BigBuff. - BigBuf_free(); - - StartTicks(); - - DbpString("Sim Stopped"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } /* @@ -1121,23 +1160,22 @@ void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { * Reads every page of a hitag S transpoder. */ void ReadHitagS(hitag_function htf, hitag_data *htd) { - - StopTicks(); - int i, j, z, k; - int frame_count = 0, response = 0; + int frame_count; int response_bit[200]; - uint8_t rx[HITAG_FRAME_LEN]; + int response; + byte_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t *tx = txbuf; size_t txlen = 0; - int lastbit = 1; + int lastbit; bool bSkip; - int reset_sof = 1; + int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; + bool bQuitTraceFull = false; int sendNum = 0; unsigned char mask = 1; unsigned char crc; @@ -1145,31 +1183,31 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { page_to_be_written = 0; //read given key/challenge - uint8_t NrAr_[8]; + byte_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - uint8_t key_[6]; - + byte_t key_[6]; switch (htf) { - case RHTSF_CHALLENGE: { + case 01: { //RHTS_CHALLENGE DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; - break; } - case RHTSF_KEY: { + break; + case 02: { //RHTS_KEY DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; - break; } + break; default: { Dbprintf("Error , unknown function: %d", htf); return; } + break; } FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1181,36 +1219,40 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { clear_trace(); bQuiet = false; + bQuitTraceFull = true; LED_D_ON(); + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + + // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; + RELAY_OFF(); // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | @@ -1222,20 +1264,32 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - // Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; + + reset_sof = 1; t_wait = 200; - while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { - + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } // By default reset the transmission buffer @@ -1245,14 +1299,13 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { if (rxlen == 0) { //start authentication txlen = 5; - memcpy(tx, "\xC0", nbytes(txlen)); + memcpy(tx, "\xc0", nbytes(txlen)); tag.pstate = HT_READY; tag.tstate = HT_NO_OP; } else if (tag.pstate != HT_SELECTED) { if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1) bStop = !false; } - if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { //send read request tag.tstate = HT_READING_PAGE; @@ -1263,8 +1316,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED - && tag.tstate == HT_READING_PAGE + } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE && rxlen > 0) { //save received data z = 0; @@ -1309,19 +1361,15 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { sendNum++; //display key and password if possible if (sendNum == 2 && tag.auth == 1 && tag.LKP) { - if (htf == RHTSF_KEY) { + if (htf == 02) { //RHTS_KEY Dbprintf("Page[ 2]: %02X %02X %02X %02X", - (uint8_t)(key >> 8) & 0xff, - (uint8_t) key & 0xff, - pwdl1, - pwdl0 - ); + (byte_t)(key >> 8) & 0xff, + (byte_t) key & 0xff, pwdl1, pwdl0); Dbprintf("Page[ 3]: %02X %02X %02X %02X", - (uint8_t)(key >> 40) & 0xff, - (uint8_t)(key >> 32) & 0xff, - (uint8_t)(key >> 24) & 0xff, - (uint8_t)(key >> 16) & 0xff - ); + (byte_t)(key >> 40) & 0xff, + (byte_t)(key >> 32) & 0xff, + (byte_t)(key >> 24) & 0xff, + (byte_t)(key >> 16) & 0xff); } else { //if the authentication is done with a challenge the key and password are unknown Dbprintf("Page[ 2]: __ __ __ __"); @@ -1362,7 +1410,17 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } } // Reset values for receiving frames @@ -1433,17 +1491,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } } end = false; - - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - StartTicks(); - cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1452,14 +1505,12 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { * Writes the given 32Bit data into page_ */ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { - - StopTicks(); - - int frame_count = 0, response = 0; - uint8_t rx[HITAG_FRAME_LEN]; + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1467,106 +1518,124 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; + bool bQuitTraceFull = false; int page = page_; unsigned char crc; - uint8_t data[4] = {0, 0, 0, 0}; - - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - - bSuccessful = false; - - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + byte_t data[4] = {0, 0, 0, 0}; //read given key/challenge, the page and the data - uint8_t NrAr_[8]; + byte_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - uint8_t key_[6]; + byte_t key_[6]; switch (htf) { - case WHTSF_CHALLENGE: { + case 03: { //WHTS_CHALLENGE memcpy(data, htd->auth.data, 4); DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; - break; } - - case WHTSF_KEY: { + break; + case 04: { //WHTS_KEY memcpy(data, htd->crypto.data, 4); DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; - break; } + break; default: { Dbprintf("Error , unknown function: %d", htf); return; } + break; } Dbprintf("Page: %d", page_); Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); +// Reset the return status + bSuccessful = false; tag.pstate = HT_READY; tag.tstate = HT_NO_OP; +// Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + bQuiet = false; + bQuitTraceFull = true; + LED_D_ON(); - // Configure output and enable pin that is connected to the FPGA (for modulating) +// Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); +// Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + +// Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Disable modulation at default, which means enable the field +// Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); +// Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; +// Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. +// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING - | AT91C_TC_ABETRG + | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - // Enable and reset counters +// Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV > 0); - - // Reset the received frame, frame count and timing info +// Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; lastbit = 1; bStop = false; + reset_sof = 1; t_wait = 200; - while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { - + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } //check for valid input @@ -1642,7 +1711,9 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1653,7 +1724,17 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } } // Reset values for receiving frames @@ -1663,7 +1744,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { bSkip = true; tag_sof = reset_sof; response = 0; - uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { @@ -1714,13 +1794,9 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } else { // Ignore wierd value, is to small to mean anything - errorCount++; } } - // if we saw over 100 wierd values break it probably isn't hitag... - if (errorCount > 100) break; - // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) @@ -1729,15 +1805,11 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } end = false; - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - StartTicks(); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1748,16 +1820,17 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { * is not received correctly due to Antenna problems. This function * detects these challenges. */ -void check_challenges(bool file_given, uint8_t *data) { +void check_challenges(bool file_given, byte_t *data) { int i, j, z, k; - uint8_t uid_byte[4]; - int frame_count = 0, response = 0; - uint8_t rx[HITAG_FRAME_LEN]; - uint8_t unlocker[60][8]; + byte_t uid_byte[4]; + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; + byte_t unlocker[60][8]; int u1 = 0; size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t *tx = txbuf; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1766,71 +1839,76 @@ void check_challenges(bool file_given, uint8_t *data) { int t_wait = HITAG_T_WAIT_MAX; int STATE = 0; bool bStop; + bool bQuitTraceFull = false; int response_bit[200]; unsigned char mask = 1; unsigned char uid[32]; unsigned char crc; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status +// Reset the return status bSuccessful = false; - // Clean up trace and prepare it for storing frames +// Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); bQuiet = false; + bQuitTraceFull = true; LED_D_ON(); - // Configure output and enable pin that is connected to the FPGA (for modulating) +// Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now +// Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + SpinDelay(50); + +// Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Disable modulation at default, which means enable the field +// Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for - // TIMER_CLOCK0, used to measure exact timing before answering - // TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); +// Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; +// Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; - - // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. +// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING - | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; - // Enable and reset counters + | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + +// Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV > 0) {}; - - // Reset the received frame, frame count and timing info +// Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; lastbit = 1; bStop = false; + reset_sof = 1; t_wait = 200; if (file_given) { DbpString("Loading challenges..."); - memcpy((uint8_t *)unlocker, data, 60 * 8); + memcpy((byte_t *)unlocker, data, 60 * 8); } while (file_given && !bStop && !BUTTON_PRESS()) { @@ -1840,7 +1918,16 @@ void check_challenges(bool file_given, uint8_t *data) { // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - LogTrace(rx, nbytes(rxlen), response, 0, NULL, false); + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } } tx = txbuf; @@ -1856,7 +1943,7 @@ void check_challenges(bool file_given, uint8_t *data) { STATE = 0; txlen = 5; //start new authentication - memcpy(tx, "\xC0", nbytes(txlen)); + memcpy(tx, "\xc0", nbytes(txlen)); } else if (rxlen >= 67 && STATE == 0) { //received uid z = 0; @@ -1956,7 +2043,9 @@ void check_challenges(bool file_given, uint8_t *data) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1967,7 +2056,17 @@ void check_challenges(bool file_given, uint8_t *data) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, 0, NULL, true); + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } } // Reset values for receiving frames @@ -2037,16 +2136,11 @@ void check_challenges(bool file_given, uint8_t *data) { } } } - - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - + LED_B_OFF(); + LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - - StartTicks(); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h deleted file mode 100644 index 49a885c4c..000000000 --- a/armsrc/hitagS.h +++ /dev/null @@ -1,31 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- -// HitagS emulation (preliminary test version) -// -// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg -// -//----------------------------------------------------------------------------- - -#ifndef _HITAGS_H_ -#define _HITAGS_H_ - -#include -#include -#include -#include "hitag2_crypto.h" -#include "hitag.h" -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "BigBuf.h" - -void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data); -void ReadHitagS(hitag_function htf, hitag_data *htd); -void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); -void check_challenges(bool file_given, uint8_t *data); - -#endif diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 1326306b1..7bd725eab 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -18,7 +18,7 @@ // // FIX: // ==== -// We still have sometimes a demodulation error when sniffing iClass communication. +// We still have sometimes a demodulation error when snooping iClass communication. // The resulting trace of a read-block-03 command may look something like this: // // + 22279: : 0c 03 e8 01 @@ -2456,4 +2456,4 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); switch_off(); -} +} \ No newline at end of file diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index f599e779c..e556e0ff1 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2781,7 +2781,7 @@ void DetectNACKbug() { bool received_nack; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). - int32_t sync_cycles = PRNG_SEQUENCE_LENGTH; + uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; BigBuf_free(); BigBuf_Clear_ext(false); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 5d988459b..5b6a85477 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -1413,7 +1413,7 @@ static void iso1444b_setup_sniff(void) { FpgaDownloadAndGo(FPGA_BITSTREAM_HF); BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); + clear_trace();//setup snoop set_tracing(true); // Initialize Demod and Uart structs @@ -1570,7 +1570,6 @@ void iso14b_set_trigger(bool enable) { void SendRawCommand14443B_Ex(UsbCommand *c) { iso14b_command_t param = c->arg[0]; size_t len = c->arg[1] & 0xffff; - uint32_t timeout = c->arg[2]; uint8_t *cmd = c->d.asBytes; uint8_t status = 0; uint32_t sendlen = sizeof(iso14b_card_select_t); @@ -1587,9 +1586,6 @@ void SendRawCommand14443B_Ex(UsbCommand *c) { clear_trace(); } - if ((param & ISO14B_SET_TIMEOUT)) - iso14b_set_timeout(timeout); - set_tracing(true); if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { @@ -1638,4 +1634,4 @@ out: switch_off(); // disconnect raw SpinDelay(20); } -} +} \ No newline at end of file diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 12e9cc815..b6d53ccea 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -621,8 +621,8 @@ void Iso15693InitReader(void) { // Encode (into the ToSend buffers) an identify request, which is the first // thing that you must send to a tag to get a response. -// It expects "out" to be at least CMD_ID_RESP large static void BuildIdentifyRequest(uint8_t *out) { + uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; // flags cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; @@ -665,7 +665,6 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb */ // Now the VICC>VCD responses when we are simulating a tag -// It expects "out" to be at least CMD_INV_RESP large static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -687,7 +686,7 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { // CRC AddCrc(cmd, 10); CodeIso15693AsReader(cmd, CMD_INV_RESP); - memcpy(out, cmd, CMD_INV_RESP); + memcpy(out, cmd, CMD_ID_RESP); } // Universal Method for sending to and recv bytes from a tag @@ -740,50 +739,50 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { if (len > 3) { if (d[0] & (1 << 3)) - strncat(status, "ProtExt ", DBD15STATLEN - strlen(status)); + strncat(status, "ProtExt ", DBD15STATLEN); if (d[0] & 1) { // error - strncat(status, "Error ", DBD15STATLEN - strlen(status)); + strncat(status, "Error ", DBD15STATLEN); switch (d[1]) { case 0x01: - strncat(status, "01: not supported", DBD15STATLEN - strlen(status)); + strncat(status, "01: not supported", DBD15STATLEN); break; case 0x02: - strncat(status, "02: not recognized", DBD15STATLEN - strlen(status)); + strncat(status, "02: not recognized", DBD15STATLEN); break; case 0x03: - strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status)); + strncat(status, "03: opt not supported", DBD15STATLEN); break; case 0x0f: - strncat(status, "0F: no info", DBD15STATLEN - strlen(status)); + strncat(status, "0F: no info", DBD15STATLEN); break; case 0x10: - strncat(status, "10: dont exist", DBD15STATLEN - strlen(status)); + strncat(status, "10: dont exist", DBD15STATLEN); break; case 0x11: - strncat(status, "11: lock again", DBD15STATLEN - strlen(status)); + strncat(status, "11: lock again", DBD15STATLEN); break; case 0x12: - strncat(status, "12: locked", DBD15STATLEN - strlen(status)); + strncat(status, "12: locked", DBD15STATLEN); break; case 0x13: - strncat(status, "13: program error", DBD15STATLEN - strlen(status)); + strncat(status, "13: program error", DBD15STATLEN); break; case 0x14: - strncat(status, "14: lock error", DBD15STATLEN - strlen(status)); + strncat(status, "14: lock error", DBD15STATLEN); break; default: - strncat(status, "unknown error", DBD15STATLEN - strlen(status)); + strncat(status, "unknown error", DBD15STATLEN); } - strncat(status, " ", DBD15STATLEN - strlen(status)); + strncat(status, " ", DBD15STATLEN); } else { - strncat(status, "No error ", DBD15STATLEN - strlen(status)); + strncat(status, "No error ", DBD15STATLEN); } if (CheckCrc(d, len)) - strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status)); + strncat(status, "[+] crc OK", DBD15STATLEN); else - strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status)); + strncat(status, "[!] crc fail", DBD15STATLEN); if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); } @@ -1000,4 +999,4 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint } else { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); } -} +} \ No newline at end of file diff --git a/armsrc/lfops.c b/armsrc/lfops.c index a40e5e977..ac9f08ed3 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -21,6 +21,13 @@ #include "common.h" #include "flashmem.h" // persistence on mem +#ifndef SHORT_COIL +# define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#endif +#ifndef OPEN_COIL +# define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#endif + //#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) //#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) //#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) @@ -310,7 +317,7 @@ void ReadTItag(void) { // expected for either the low or high frequency if ((samples > (sampleslo - threshold)) && (samples < (sampleslo + threshold))) { // low frequency represents a 1 - shift3 |= (1u << 31); + shift3 |= (1 << 31); } else if ((samples > (sampleshi - threshold)) && (samples < (sampleshi + threshold))) { // high frequency represents a 0 } else { @@ -474,7 +481,7 @@ void AcquireTiType(void) { // unpack buffer for (i = TIBUFLEN - 1; i >= 0; i--) { for (j = 0; j < 32; j++) { - if (buf[i] & (1u << j)) { + if (buf[i] & (1 << j)) { dest[--n] = 1; } else { dest[--n] = -1; @@ -723,6 +730,8 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { uint8_t halfFC = fc >> 1; uint8_t wavesPerClock = clock / fc; uint8_t mod = clock % fc; //modifier + uint8_t modAdj = fc / mod; //how often to apply modifier + bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; // loop through clock - step field clock for (uint8_t idx = 0; idx < wavesPerClock; idx++) { @@ -731,24 +740,20 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { memset(dest + (*n) + (fc - halfFC), 1, halfFC); *n += fc; } - if (mod > 0) { - uint8_t modAdj = fc / mod; //how often to apply modifier - bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; - (*modCnt)++; + if (mod > 0)(*modCnt)++; - if (modAdjOk) { //fsk2 - if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave - memset(dest + (*n), 0, fc - halfFC); - memset(dest + (*n) + (fc - halfFC), 1, halfFC); - *n += fc; - } - } - if (!modAdjOk) { //fsk1 - memset(dest + (*n), 0, mod - (mod >> 1)); - memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); - *n += mod; + if ((mod > 0) && modAdjOk) { //fsk2 + if ((*modCnt % modAdj) == 0) { //if 4th 8 length wave in a rf/50 add extra 8 length wave + memset(dest + (*n), 0, fc - halfFC); + memset(dest + (*n) + (fc - halfFC), 1, halfFC); + *n += fc; } } + if (mod > 0 && !modAdjOk) { //fsk1 + memset(dest + (*n), 0, mod - (mod >> 1)); + memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); + *n += mod; + } } // prepare a waveform pattern in the buffer based on the ID given then @@ -824,7 +829,7 @@ void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol) { // prepare a waveform pattern in the buffer based on the ID given then // simulate a FSK tag until the button is pressed // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock -void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int ledcontrol) { +void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // free eventually allocated BigBuf memory @@ -833,7 +838,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int clear_trace(); set_tracing(false); - int n = 0, i = 0; + int ledcontrol = 1, n = 0, i = 0; uint8_t fcHigh = arg1 >> 8; uint8_t fcLow = arg1 & 0xFF; uint16_t modCnt = 0; @@ -901,11 +906,11 @@ static void stAskSimBit(int *n, uint8_t clock) { } // args clock, ask/man or askraw, invert, transmission separator -void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) { +void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - int n = 0, i = 0; + int ledcontrol = 1, n = 0, i = 0; uint8_t clk = (arg1 >> 8) & 0xFF; uint8_t encoding = arg1 & 0xFF; uint8_t separator = arg2 & 1; @@ -968,11 +973,11 @@ static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, b } // args clock, carrier, invert, -void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) { +void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - int n = 0, i = 0; + int ledcontrol = 1, n = 0, i = 0; uint8_t clk = arg1 >> 8; uint8_t carrier = arg1 & 0xFF; uint8_t invert = arg2 & 0xFF; @@ -1061,8 +1066,12 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) } } else { //if bit 38 is not set then 37 bit format is used bitlen = 37; - cardnum = (lo >> 1) & 0x7FFFF; - fc = ((hi & 0xF) << 12) | (lo >> 20); + fc = 0; + cardnum = 0; + if (bitlen == 37) { + cardnum = (lo >> 1) & 0x7FFFF; + fc = ((hi & 0xF) << 12) | (lo >> 20); + } } Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", hi, @@ -1373,6 +1382,8 @@ void T55xxResetRead(void) { //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); + StartTicks(); + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... @@ -1405,6 +1416,8 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) bool testMode = arg & 0x4; uint32_t i = 0; + StartTicks(); + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1478,7 +1491,7 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { // Read one card block in page [page] void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { LED_A_ON(); - bool PwdMode = arg0 & 0x1; + bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; bool brute_mem = arg0 & 0x4; @@ -1500,6 +1513,8 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { //make sure block is at max 7 Block &= 0x7; + StartTicks(); + // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... @@ -1576,23 +1591,26 @@ void T55xx_ChkPwds() { uint32_t candidate = 0; #ifdef WITH_FLASH - BigBuf_Clear_EM(); - uint16_t isok = 0; - uint8_t counter[2] = {0x00, 0x00}; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter)); - if (isok != sizeof(counter)) - goto OUT; + bool use_flashmem = true; + if (use_flashmem) { + BigBuf_Clear_EM(); + uint16_t isok = 0; + uint8_t counter[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter)); + if (isok != sizeof(counter)) + goto OUT; - pwdCount = counter[1] << 8 | counter[0]; + pwdCount = counter[1] << 8 | counter[0]; - if (pwdCount == 0 || pwdCount == 0xFFFF) - goto OUT; + if (pwdCount == 0 && pwdCount == 0xFFFF) + goto OUT; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4); - if (isok != pwdCount * 4) - goto OUT; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET + 2, pwds, pwdCount * 4); + if (isok != pwdCount * 4) + goto OUT; - Dbprintf("[=] Password dictionary count %d ", pwdCount); + Dbprintf("[=] Password dictionary count %d ", pwdCount); + } #endif uint32_t pwd = 0, curr = 0, prev = 0; @@ -1643,6 +1661,8 @@ void T55xxWakeUp(uint32_t Pwd) { LED_B_ON(); uint32_t i = 0; + StartTicks(); + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 7018fbae2..53b8e75b3 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -29,7 +29,7 @@ void printConfig() { /** * Called from the USB-handler to set the sampling configuration - * The sampling config is used for std reading and sniffing. + * The sampling config is used for std reading and snooping. * * Other functions may read samples and ignore the sampling config, * such as functions to read the UID from a prox tag or similar. @@ -239,9 +239,9 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { if (!silent) printConfig(); LFSetupFPGAForADC(config.divisor, activeField); - uint32_t ret = DoAcquisition_config(silent, sample_size); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + uint32_t ret = DoAcquisition_config(silent, sample_size); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** @@ -250,15 +250,15 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { **/ uint32_t SampleLF(bool printCfg, int sample_size) { BigBuf_Clear_ext(false); - return ReadLF(true, printCfg, sample_size); + return ReadLF(true, printCfg, sample_size); } /** -* Initializes the FPGA for sniffer-mode (field off), and acquires the samples. +* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SniffLF() { +uint32_t SnoopLF() { BigBuf_Clear_ext(false); - return ReadLF(false, true, 0); + return ReadLF(false, true, 0); } /** @@ -427,10 +427,12 @@ uint32_t doCotagAcquisitionManchester() { if (sample > COTAG_ONE_THRESHOLD) { prev = curr; curr = 1; - } else if (sample < COTAG_ZERO_THRESHOLD) { + } + else if ( sample < COTAG_ZERO_THRESHOLD) { prev = curr; curr = 0; - } else { + } + else { curr = prev; } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index 8556cd327..94c370ed9 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -30,10 +30,10 @@ void doT55x7Acquisition(size_t sample_size); uint32_t SampleLF(bool silent, int sample_size); /** -* Initializes the FPGA for sniff-mode (field off), and acquires the samples. +* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ -uint32_t SniffLF(); +uint32_t SnoopLF(); // adds sample size to default options uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after); @@ -67,7 +67,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field); /** * Called from the USB-handler to set the sampling configuration - * The sampling config is used for std reading and sniffing. + * The sampling config is used for std reading and snooping. * * Other functions may read samples and ignore the sampling config, * such as functions to read the UID from a prox tag or similar. diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 9e771679b..1f1932e27 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1247,7 +1247,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da keyCount = size[1] << 8 | size[0]; - if (keyCount == 0 || keyCount == 0xFFFF) + if (keyCount == 0 && keyCount == 0xFFFF) goto OUT; datain = BigBuf_malloc(keyCount * 6); @@ -2098,4 +2098,4 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(false); -} +} \ No newline at end of file diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index 51ed76ca5..595d46395 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -25,4 +25,4 @@ #include "crc.h" #include "protocols.h" #include "parity.h" -#endif +#endif \ No newline at end of file diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 0e75aac35..8f391207e 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -322,4 +322,4 @@ void RAMFUNC MfSniffSend() { LED_B_ON(); cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. LED_B_OFF(); -} +} \ No newline at end of file diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index 9b5cb8609..debfd5a09 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -39,4 +39,4 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui void RAMFUNC MfSniffSend(void); void MfSniffEnd(void); -#endif +#endif \ No newline at end of file diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 90a6f5d64..ef371b233 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -518,4 +518,4 @@ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) { tab[u + 2] = c + tab[u + 1]; return 0; -} +} \ No newline at end of file diff --git a/armsrc/pcf7931.h b/armsrc/pcf7931.h index b8121c29f..bed33dadc 100644 --- a/armsrc/pcf7931.h +++ b/armsrc/pcf7931.h @@ -17,4 +17,4 @@ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p); bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab); void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data); -#endif +#endif \ No newline at end of file diff --git a/armsrc/start.c b/armsrc/start.c index b5947bdf3..a6503f1ea 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -77,4 +77,4 @@ void __attribute__((section(".startos"))) Vector(void) { AppMain(); } -#endif +#endif \ No newline at end of file diff --git a/armsrc/string.h b/armsrc/string.h index f6f094c48..de8f3ac20 100644 --- a/armsrc/string.h +++ b/armsrc/string.h @@ -24,4 +24,4 @@ char *strcat(char *dest, const char *src); void strreverse(char s[]); void itoa(int n, char s[]); -#endif /* __STRING_H */ +#endif /* __STRING_H */ \ No newline at end of file diff --git a/armsrc/ticks.h b/armsrc/ticks.h index d24d2aac5..6e5e334f0 100644 --- a/armsrc/ticks.h +++ b/armsrc/ticks.h @@ -44,4 +44,4 @@ extern void WaitUS(uint16_t us); extern void WaitMS(uint16_t ms); extern void StopTicks(void); -#endif +#endif \ No newline at end of file diff --git a/armsrc/util.h b/armsrc/util.h index 15f93d1f9..19b104f51 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -17,18 +17,7 @@ #include "BigBuf.h" #include "ticks.h" -// Basic macros -#ifndef SHORT_COIL -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#endif - -#ifndef OPEN_COIL -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) -#endif - -#ifndef BYTEx #define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) -#endif #define LED_RED 1 #define LED_ORANGE 2 @@ -54,34 +43,6 @@ # define NTIME(n) for (int _index = 0; _index < n; _index++) #endif -#ifndef REV8 -#define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#endif - -#ifndef REV16 -#define REV16(x) (REV8(x) + (REV8 (x >> 8) << 8)) -#endif - -#ifndef REV32 -#define REV32(x) (REV16(x) + (REV16(x >> 16) << 16)) -#endif - -#ifndef REV64 -#define REV64(x) (REV32(x) + (REV32(x >> 32) << 32)) -#endif - -#ifndef BIT32 -#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#endif - -#ifndef INV32 -#define INV32(x,i,n) ((x)[(i)>>5]^=((uint32_t)(n))<<((i)&31)) -#endif - -#ifndef ROTL64 -#define ROTL64(x, n) ((((uint64_t)(x))<<((n)&63))+(((uint64_t)(x))>>((0-(n))&63))) -#endif - size_t nbytes(size_t nbits); extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index 78c8f4d1e..a687cb0b1 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -8,7 +8,7 @@ #include #include #include -#include "../loclass/fileutils.h" +#include "../loclass/fileutil.h" #define NTAG215_SIZE 540 diff --git a/client/cli.c b/client/cli.c index 270689732..19e472586 100644 --- a/client/cli.c +++ b/client/cli.c @@ -21,7 +21,7 @@ int main(int argc, char **argv) { if (argc != 3 && argc != 4) { printf("\n\tusage: cli [logfile (default cli.log)]\n"); printf("\n"); - printf("\texample: cli hf 14a sniff hf 14a list h14a.log\n"); + printf("\texample: cli hi14asnoop hi14alist h14a.log\n"); printf("\n"); return -1; } diff --git a/client/cmdcrc.c b/client/cmdcrc.c index be74fc39a..1a17d1428 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -483,4 +483,4 @@ int CmdrevengSearch(const char *Cmd) { if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); return 1; -} +} \ No newline at end of file diff --git a/client/cmddata.c b/client/cmddata.c index aa44611ed..5aeaca388 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -417,16 +417,18 @@ int CmdPrintDemodBuff(const char *Cmd) { return 0; } length = (length > (DemodBufferLen - offset)) ? DemodBufferLen - offset : length; + int numBits = (length) & 0x00FFC; //make sure we don't exceed our string if (hexMode) { char *buf = (char *)(DemodBuffer + offset); - int numBits = binarraytohex(hex, sizeof(hex), buf, length); + numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; + numBits = binarraytohex(hex, buf, numBits); if (numBits == 0) { return 0; } PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); } else { - PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, length, 16)); + PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer + offset, numBits, 16)); } return 1; } @@ -473,15 +475,14 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, size_t BitLen = getFromGraphBuf(bits); - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) #samples from graphbuff: %d", BitLen); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); if (BitLen < 255) return 0; if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; int foundclk = 0; - - //amplify signal before ST check + //amp before ST check if (amp == 'a') askAmp(bits, BitLen); @@ -495,8 +496,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, clk = (clk == 0) ? foundclk : clk; CursorCPos = ststart; CursorDPos = stend; - if (verbose) - PrintAndLogEx(DEBUG, "Found Sequence Terminator - First one is shown by orange / blue graph markers"); + if (verbose || g_debugMode) + PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); } int startIdx = 0; @@ -512,19 +513,19 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, return 0; } - if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); //output setDemodBuf(bits, BitLen, 0); setClockGrid(clk, startIdx); - if (verbose) { + if (verbose || g_debugMode) { if (errCnt > 0) - PrintAndLogEx(DEBUG, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); + PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d", errCnt); if (askType) - PrintAndLogEx(DEBUG, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); + PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:", clk); else - PrintAndLogEx(DEBUG, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); + PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:", clk); // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(); } @@ -623,7 +624,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); if (DemodBufferLen == 0) { - PrintAndLogEx(WARNING, "DemodBuffer Empty - run " _YELLOW_("'data rawdemod ar'")" first"); + PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); return 0; } @@ -642,7 +643,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { } if (errCnt > 0) - PrintAndLogEx(WARNING, "# Errors found during Demod (shown as " _YELLOW_("7")" in bit stream): %d", errCnt); + PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d", errCnt); PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:", offset, invert); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); @@ -715,7 +716,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph // sanity check if (window > len) window = len; - if (verbose) PrintAndLogEx(INFO, "performing " _YELLOW_("%d")" correlations", GraphTraceLen - window); + if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); //test double autocv = 0.0; // Autocovariance value @@ -768,11 +769,10 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } int foo = ABS(hi - hi_1); - int bar = (int)((int)((hi + hi_1) / 2) * 0.04); - + int bar = (int)((int)((hi + hi_1) / 2) * 0.03); if (verbose && foo < bar) { distance = idx_1 - idx; - PrintAndLogEx(SUCCESS, "possible 4% visible correlation %4d samples", distance); + PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); } else if (verbose && (correlation > 1)) { PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); } else { @@ -1069,7 +1069,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) { } return 1; } else { - PrintAndLogEx(DEBUG, "no FSK data found"); + if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); } return 0; } @@ -1128,7 +1128,7 @@ int PSKDemod(const char *Cmd, bool verbose) { return 1; } -int CmdIdteckDemod(const char *Cmd) { +int CmdPSKIdteck(const char *Cmd) { if (!PSKDemod("", false)) { PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); diff --git a/client/cmddata.h b/client/cmddata.h index 1091c48c2..86f19d81d 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -54,7 +54,7 @@ int CmdDetectClockRate(const char *Cmd); int CmdFSKrawdemod(const char *Cmd); int CmdPSK1rawDemod(const char *Cmd); int CmdPSK2rawDemod(const char *Cmd); -int CmdIdteckDemod(const char *Cmd); +int CmdPSKIdteck(const char *Cmd); int CmdGrid(const char *Cmd); int CmdGetBitStream(const char *Cmd); int CmdHexsamples(const char *Cmd); diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index c75fadb3c..0701f1d2d 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -245,7 +245,7 @@ int CmdFlashMemLoad(const char *Cmd) { break; default: - res = loadFile(filename, "bin", data, FLASH_MEM_MAX_SIZE, &datalen); + res = loadFile(filename, "bin", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if (res) { free(data); diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 099a4e3b1..0a56ebed4 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -42,4 +42,4 @@ extern int CmdFlashMemWipe(const char *Cmd); extern int CmdFlashMemInfo(const char *Cmd); #endif -#endif +#endif \ No newline at end of file diff --git a/client/cmdhf.c b/client/cmdhf.c index 8368160f8..237149348 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -21,7 +21,7 @@ int usage_hf_search() { return 0; } int usage_hf_sniff() { - PrintAndLogEx(NORMAL, "The high frequence sniffer will assign all available memory on device for sniffed data"); + PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for sniffed data"); PrintAndLogEx(NORMAL, "Use " _YELLOW_("'data samples'")" command to download from device, and " _YELLOW_("'data plot'")" to look at it"); PrintAndLogEx(NORMAL, "Press button to quit the sniffing.\n"); PrintAndLogEx(NORMAL, "Usage: hf sniff "); @@ -42,7 +42,7 @@ int CmdHFSearch(const char *Cmd) { if (cmdp == 'h') return usage_hf_search(); PrintAndLogEx(INFO, "Checking for known tags...\n"); - + int ans = CmdHF14AInfo("s"); if (ans > 0) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("ISO14443-A tag") " found\n"); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 6dd7149f2..6d4b39e4e 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -803,7 +803,7 @@ int CmdHF14ASniff(const char *Cmd) { if (ctmp == 'c') param |= 0x01; if (ctmp == 'r') param |= 0x02; } - UsbCommand c = {CMD_SNIFF_ISO_14443a, {param, 0, 0}}; + UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 9d542f228..564b18012 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -33,7 +33,7 @@ int usage_hf_14b_reader(void) { return 0; } int usage_hf_14b_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s / -ss] [-t] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " -h this help"); PrintAndLogEx(NORMAL, " -r do not read response"); @@ -41,7 +41,6 @@ int usage_hf_14b_raw(void) { PrintAndLogEx(NORMAL, " -p leave the field on after receive"); PrintAndLogEx(NORMAL, " -s active signal field ON with select"); PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); - PrintAndLogEx(NORMAL, " -t timeout in ms"); PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); return 0; @@ -146,20 +145,20 @@ int CmdHF14BSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_sniff(); - UsbCommand c = {CMD_SNIFF_ISO_14443B, {0, 0, 0}}; + UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } int CmdHF14BCmdRaw(const char *Cmd) { - bool reply = true, power = false, select = false, hasTimeout = false; + bool reply = true, power = false, select = false; char buf[5] = ""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; uint16_t datalen = 0; uint32_t flags = ISO14B_CONNECT; - uint32_t temp = 0, user_timeout = 0, time_wait = 0; + uint32_t temp = 0; if (strlen(Cmd) < 3) return usage_hf_14b_raw(); @@ -190,13 +189,6 @@ int CmdHF14BCmdRaw(const char *Cmd) { flags |= ISO14B_SELECT_STD; } break; - case 't': - hasTimeout = true; - sscanf(Cmd + i + 2, "%d", &user_timeout); - i += 3; - while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } - i -= 2; - break; default: return usage_hf_14b_raw(); } @@ -222,17 +214,7 @@ int CmdHF14BCmdRaw(const char *Cmd) { return 0; } - if (hasTimeout) { -#define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s - flags |= ISO14B_SET_TIMEOUT; - if (user_timeout > MAX_TIMEOUT) { - user_timeout = MAX_TIMEOUT; - PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); - } - time_wait = 13560000 / 1000 / (8 * 16) * user_timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) - } - - if (power == 0) + if (!power) flags |= ISO14B_DISCONNECT; if (datalen > 0) @@ -241,7 +223,7 @@ int CmdHF14BCmdRaw(const char *Cmd) { // Max buffer is USB_CMD_DATA_SIZE datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, time_wait}}; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; memcpy(c.d.asBytes, data, datalen); clearCommandBuffer(); SendCommand(&c); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 23a756062..2e784962c 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -684,15 +684,15 @@ int CmdHF15Dump(const char *Cmd) { //Validations if (errors) return usage_15_dump(); - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } - if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } + fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr, uid, "-dump", sizeof(uid)); } @@ -796,7 +796,7 @@ int CmdHF15Restore(const char *Cmd) { case '2': case 'o': strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix) - 1); - strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - strlen(newCmdPrefix) - 1); + strncat(newCmdPrefix, param, sizeof(newCmdPrefix) - 1); break; default: PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); @@ -1315,4 +1315,4 @@ int CmdHF15(const char *Cmd) { int CmdHF15Help(const char *Cmd) { CmdsHelp(CommandTable15); return 0; -} +} \ No newline at end of file diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 0386155c1..fce18f11b 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -176,4 +176,4 @@ int CmdHFEPA(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; -} +} \ No newline at end of file diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 33d506a58..59ddc5d65 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -218,7 +218,7 @@ int CmdHFFelicaSniff(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_hf_felica_sniff(); - UsbCommand c = {CMD_FELICA_SNIFF, {samples2skip, triggers2skip, 0}}; + UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -609,4 +609,4 @@ int CmdHFFelica(const char *Cmd) { int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} +} \ No newline at end of file diff --git a/client/cmdhffido.h b/client/cmdhffido.h index 96f9153ed..2460a170f 100644 --- a/client/cmdhffido.h +++ b/client/cmdhffido.h @@ -24,4 +24,4 @@ extern int CmdHFFido(const char *Cmd); -#endif +#endif \ No newline at end of file diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index ad0f510a7..b71f2fd03 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -279,7 +279,7 @@ int CmdHFiClassList(const char *Cmd) { int CmdHFiClassSniff(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_iclass_sniff(); - UsbCommand c = {CMD_SNIFF_ICLASS}; + UsbCommand c = {CMD_SNOOP_ICLASS}; SendCommand(&c); return 0; } @@ -1375,14 +1375,11 @@ int CmdHFiClassCloneTag(const char *Cmd) { return 2; } - fclose(f); - uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t div_key[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; - if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) { + if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)) return 0; - } UsbCommand w = {CMD_ICLASS_CLONE, {startblock, endblock}}; uint8_t *ptr; @@ -1404,7 +1401,6 @@ int CmdHFiClassCloneTag(const char *Cmd) { PrintAndLogEx(NORMAL, " %02x%02x%02x%02x%02x%02x%02x%02x |", p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); PrintAndLogEx(NORMAL, " MAC |%02x%02x%02x%02x|\n", p[8], p[9], p[10], p[11]); } - UsbCommand resp; clearCommandBuffer(); SendCommand(&w); diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index db65447ac..a509873da 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1317,4 +1317,4 @@ int CmdHFLegic(const char *Cmd) { int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; -} +} \ No newline at end of file diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 3c1fb83bd..6bcfe0b20 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1251,4 +1251,4 @@ uint64_t GetCrypto1ProbableKey(TAuthData *ad) { crypto1_get_lfsr(revstate, &key); crypto1_destroy(revstate); return key; -} +} \ No newline at end of file diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index cea2b5508..71bdb2ec8 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2570,7 +2570,7 @@ int CmdHF14AMfELoad(const char *Cmd) { uint8_t *data = calloc(4096, sizeof(uint8_t)); size_t datalen = 0; - //int res = loadFile(filename, "bin", data, maxdatalen, &datalen); + //int res = loadFile(filename, "bin", data, &datalen); int res = loadFileEML(filename, "eml", data, &datalen); if (res) { free(data); @@ -2856,7 +2856,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { size_t datalen = 0; int res = 0; if (fillFromBin) { - res = loadFile(fileName, "bin", data, maxdatalen, &datalen); + res = loadFile(fileName, "bin", data, &datalen); } else { if (fillFromJson) { res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); @@ -3535,7 +3535,7 @@ static command_t CommandTable[] = { {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, {"chk", CmdHF14AMfChk, 0, "Check keys"}, {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, - {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt sniff or trace"}, + {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, {"-----------", CmdHelp, 1, ""}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, diff --git a/client/cmdhfmfdesfire.h b/client/cmdhfmfdesfire.h index cc5481b0e..c29fd262a 100644 --- a/client/cmdhfmfdesfire.h +++ b/client/cmdhfmfdesfire.h @@ -2,4 +2,4 @@ static int CmdHelp(const char *Cmd); int CmdHF14AMfDESAuth(const char *Cmd); int CmdHFMFDesfire(const char *Cmd); -int CmdHelp(const char *Cmd); +int CmdHelp(const char *Cmd); \ No newline at end of file diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index ed9d36b79..a5cacb518 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -15,4 +15,4 @@ extern int CmdHFMFP(const char *Cmd); -#endif +#endif \ No newline at end of file diff --git a/client/cmdlf.c b/client/cmdlf.c index 948cf2235..b6da222c6 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -70,8 +70,8 @@ int usage_lf_config(void) { PrintAndLogEx(NORMAL, " a resolution of 4 bits per sample."); PrintAndLogEx(NORMAL, " lf read"); PrintAndLogEx(NORMAL, " Performs a read (active field)"); - PrintAndLogEx(NORMAL, " lf sniff"); - PrintAndLogEx(NORMAL, " Performs a sniff (no active field)"); + PrintAndLogEx(NORMAL, " lf snoop"); + PrintAndLogEx(NORMAL, " Performs a snoop (no active field)"); return 0; } int usage_lf_simfsk(void) { @@ -216,7 +216,7 @@ int CmdFlexdemod(const char *Cmd) { } if (start == size - LONG_WAIT) { - PrintAndLogEx(WARNING, "nothing to wait for"); + PrintAndLogEx(WARNING, "nothing to wait for"); return 0; } @@ -389,7 +389,7 @@ int CmdLFSniff(const char *Cmd) { uint8_t cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_lf_sniff(); - UsbCommand c = {CMD_LF_SNIFF_RAW_ADC_SAMPLES, {0, 0, 0}}; + UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK, NULL); @@ -839,12 +839,12 @@ bool CheckChipType(bool getDeviceData) { //check for t55xx chip... if (tryDetectP1(true)) { - PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found"); + PrintAndLogEx(SUCCESS, "\nChipset detection : " _GREEN_("Atmel T55xx") " found"); PrintAndLogEx(SUCCESS, "Try " _YELLOW_("`lf t55xx`")" commands"); retval = true; goto out; } - + out: save_restoreGB(GRAPH_RESTORE); save_restoreDB(GRAPH_RESTORE); @@ -896,15 +896,12 @@ int CmdLFfind(const char *Cmd) { } if (EM4x50Read("", false)) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM4x50 ID") " found!"); return 1;} - - if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} if (CmdAWIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("AWID ID") " found!"); goto out;} - if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} - if (CmdEM410xDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("EM410x ID") " found!"); goto out;} if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("FDX-B ID") " found!"); goto out;} if (CmdGuardDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Guardall G-Prox II ID") " found!"); goto out; } - if (CmdIdteckDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} + if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("HID Prox ID") " found!"); goto out;} + if (CmdPSKIdteck("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Idteck ID") " found!"); goto out;} if (CmdIndalaDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Indala ID") " found!"); goto out;} if (CmdIOProxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("IO Prox ID") " found!"); goto out;} if (CmdJablotronDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Jablotron ID") " found!"); goto out;} @@ -913,7 +910,7 @@ int CmdLFfind(const char *Cmd) { if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Noralsy ID") " found!"); goto out;} if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("KERI ID") " found!"); goto out;} if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("PAC/Stanley ID") " found!"); goto out;} - + if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Paradox ID") " found!"); goto out;} if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Presco ID") " found!"); goto out;} if (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Pyramid ID") " found!"); goto out;} if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Securakey ID") " found!"); goto out;} @@ -948,19 +945,19 @@ int CmdLFfind(const char *Cmd) { bool st = true; if (ASKDemod_ext("0 0 0", true, false, 1, &st)) { PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag found!"); - PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'")); + PrintAndLogEx(NORMAL, "if it does not look right it could instead be ASK/Biphase - try " _YELLOW_("'data rawdemod ab'") ); goto out; } if (CmdPSK1rawDemod("")) { PrintAndLogEx(NORMAL, "Possible unknown PSK1 Modulated Tag found above!"); - PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'")); + PrintAndLogEx(NORMAL, " Could also be PSK2 - try " _YELLOW_("'data rawdemod p2'") ); PrintAndLogEx(NORMAL, " Could also be PSK3 - [currently not supported]"); - PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr")); + PrintAndLogEx(NORMAL, " Could also be NRZ - try " _YELLOW_("'data rawdemod nr") ); goto out; } - PrintAndLogEx(FAILED, _RED_("\nNo data found!")); + PrintAndLogEx(FAILED, _RED_("\nNo data found!") ); } out: // identify chipset diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 5a7d58307..719c01a96 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -17,68 +17,23 @@ #include "common.h" #include "util.h" #include "parity.h" -#include "hitag.h" +#include "hitag2.h" +#include "hitagS.h" #include "util_posix.h" #include "comms.h" #include "cmddata.h" -#include "loclass/fileutils.h" // savefile static int CmdHelp(const char *Cmd); size_t nbytes(size_t nbits) { return (nbits / 8) + ((nbits % 8) > 0); } -int usage_hitag_sniff(void) { - PrintAndLogEx(NORMAL, "Sniff traffic between Hitag reader and tag. Use " _YELLOW_("`lf hitag list`")" to view collected data."); - PrintAndLogEx(NORMAL, "Usage: lf hitag sniff [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); -// PrintAndLogEx(NORMAL, " p Password"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag sniff"); - return 0; -} -int usage_hitag_sim(void) { - PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); - PrintAndLogEx(NORMAL, "Usage: lf hitag sim [h] [2|s] e|j|b "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " [2|s] 2 = hitag2, s = hitagS"); - PrintAndLogEx(NORMAL, " e Load data from EML file"); - PrintAndLogEx(NORMAL, " j Load data from JSON file"); - PrintAndLogEx(NORMAL, " b Load data from BIN file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); - return 0; -} -int usage_hitag_info(void) { - PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " p password"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag info"); - return 0; -} -int usage_hitag_dump(void) { - PrintAndLogEx(NORMAL, "Usage: lf hitag dump [h] p f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); -// PrintAndLogEx(NORMAL, " p password"); -// PrintAndLogEx(NORMAL, " f data filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); - PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); - return 0; -} -int usage_hitag_reader(void) { - PrintAndLogEx(NORMAL, "Hitag reader functions"); + +int usage_hitag_reader(void) +{ PrintAndLogEx(NORMAL, "Usage: lf hitag reader [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " HitagS (0*)"); PrintAndLogEx(NORMAL, " 01 Challenge, read all pages from a Hitag S tag"); PrintAndLogEx(NORMAL, " 02 Set to 0 if no authentication is needed. Read all pages from a Hitag S tag"); @@ -88,41 +43,11 @@ int usage_hitag_reader(void) { PrintAndLogEx(NORMAL, " 22 Authentication"); PrintAndLogEx(NORMAL, " 23 Authentication, key is in format: ISK high + ISK low"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); - PrintAndLogEx(NORMAL, " 26 Just read UID"); - return 0; -} -int usage_hitag_writer(void) { - PrintAndLogEx(NORMAL, "Hitag writer functions"); - PrintAndLogEx(NORMAL, "Usage: lf hitag write [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " HitagS (0*)"); - PrintAndLogEx(NORMAL, " 03 (Challenge) write page on a Hitag S tag"); - PrintAndLogEx(NORMAL, " 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); - PrintAndLogEx(NORMAL, " Hitag1 (1*)"); - PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 24 (set to 0 if no authentication is needed) write page on a Hitag2 tag"); - return 0; -} -int usage_hitag_checkchallenges(void) { - PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); - PrintAndLogEx(NORMAL, "The file should be 8 * 60 bytes long, the file extension defaults to " _YELLOW_("`.cc`")); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf hitag cc [h] f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " f Load data from BIN file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); + PrintAndLogEx(NORMAL, " 26 Just read UID"); return 0; } int CmdLFHitagList(const char *Cmd) { - CmdTraceList("hitag"); - return 0; - - /* uint8_t *got = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if (!got) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); @@ -247,15 +172,10 @@ int CmdLFHitagList(const char *Cmd) { free(got); return 0; - */ } -int CmdLFHitagSniff(const char *Cmd) { - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hitag_sniff(); - - UsbCommand c = {CMD_SNIFF_HITAG, {0, 0, 0}}; +int CmdLFHitagSnoop(const char *Cmd) { + UsbCommand c = {CMD_SNOOP_HITAG}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -263,249 +183,40 @@ int CmdLFHitagSniff(const char *Cmd) { int CmdLFHitagSim(const char *Cmd) { - bool errors = false; - bool tag_mem_supplied = false; - uint8_t cmdp = 0; - size_t maxdatalen = 48; - uint8_t *data = calloc(4 * 64, sizeof(uint8_t)); - size_t datalen = 0; - int res = 0; + UsbCommand c = {CMD_SIMULATE_HITAG}; char filename[FILE_PATH_SIZE] = { 0x00 }; + FILE *f; + bool tag_mem_supplied; - UsbCommand c = {CMD_SIMULATE_HITAG, {0, 0, 0}}; + int len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - free(data); - return usage_hitag_sim(); - case '2': - maxdatalen = 48; - cmdp++; - break; - case 's': - c.cmd = CMD_SIMULATE_HITAG_S; - maxdatalen = 4 * 64; - cmdp++; - break; - case 'e': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFileEML(filename, "eml", data, &datalen); - if (res > 0 || datalen != maxdatalen) { - PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - case 'j': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFileJSON(filename, "json", data, maxdatalen, &datalen); - if (res > 0) { - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - case 'b': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFile(filename, "bin", data, maxdatalen, &datalen); - if (res > 0) { - errors = true; - break; - } - tag_mem_supplied = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + if (strlen(filename) > 0) { + f = fopen(filename, "rb+"); + if (!f) { + PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); + return 1; } - } - - //Validations - if (errors || cmdp == 0) { - free(data); - return usage_hitag_sim(); - } - - c.arg[0] = (uint32_t)tag_mem_supplied; - if (tag_mem_supplied) { - memcpy(c.d.asBytes, data, datalen); - } - clearCommandBuffer(); - SendCommand(&c); - - free(data); - return 0; -} - -static void printHitagConfiguration(uint8_t config) { - - char msg[100]; - memset(msg, 0, sizeof(msg)); - - char bits[9]; - char *bs = bits; - for (uint8_t i = 0 ; i < 8 ; i++) { - snprintf(bs, sizeof(bits), "%d", (config >> (7 - i)) & 1); - bs++; - } - - PrintAndLogEx(INFO, "\n\nHitag2 tag information "); - PrintAndLogEx(INFO, "------------------------------------"); - - //configuration byte - PrintAndLogEx(SUCCESS, "Config byte : %02X - %s", config, bits); - - // encoding - strcat(msg, "Encoding : "); - if (config & 0x1) { - strcat(msg + strlen(msg), _YELLOW_("Biphase")); + tag_mem_supplied = true; + size_t bytes_read = fread(c.d.asBytes, 1, 48, f); + if (bytes_read == 48) { + PrintAndLogEx(WARNING, "Error: File reading error"); + fclose(f); + return 1; + } + fclose(f); } else { - strcat(msg + strlen(msg), _YELLOW_("Manchester")); + tag_mem_supplied = false; } - PrintAndLogEx(SUCCESS, "%s", msg); - memset(msg, 0, sizeof(msg)); - // version - strcat(msg, "Coding in HITAG 2 operation: %s"); - uint8_t foo = (config & 0x6) >> 1; - switch (foo) { - case 0: - PrintAndLogEx(SUCCESS, "Version : public mode B, Coding: biphase"); - PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); - break; - case 1: - PrintAndLogEx(SUCCESS, "Version : public mode A, Coding: manchester"); - PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); - break; - case 2: - PrintAndLogEx(SUCCESS, "Version : public mode C, Coding: biphase"); - PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); - break; - case 3: - PrintAndLogEx(SUCCESS, "Version : Hitag2"); - PrintAndLogEx(SUCCESS, msg, (config & 0x1) ? "biphase" : "manchester"); - break; - } - memset(msg, 0, sizeof(msg)); - - // mode - strcat(msg, "Tag is in : "); - if (config & 0x8) { - strcat(msg + strlen(msg), _YELLOW_("Crypto mode")); - } else { - strcat(msg + strlen(msg), _YELLOW_("Password mode")); - } - PrintAndLogEx(SUCCESS, "%s", msg); - memset(msg, 0, sizeof(msg)); - - // page access - strcat(msg, "Page 6,7 : "); - if (config & 0x10) { - strcat(msg + strlen(msg), "read only"); - } else { - strcat(msg + strlen(msg), _GREEN_("read write")); - } - PrintAndLogEx(SUCCESS, "%s", msg); - memset(msg, 0, sizeof(msg)); - - // page access - strcat(msg, "Page 4,5 : "); - if (config & 0x20) { - strcat(msg + strlen(msg), "read only"); - } else { - strcat(msg + strlen(msg), _GREEN_("read write")); - } - PrintAndLogEx(SUCCESS, "%s", msg); - memset(msg, 0, sizeof(msg)); - - // OTP - strcat(msg, "Page 3 : "); - if (config & 0x40) { - strcat(msg + strlen(msg), "read only. Configuration byte and password tag " _RED_("FIXED / IRREVERSIBLE")); - } else { - strcat(msg + strlen(msg), _GREEN_("read write")); - } - PrintAndLogEx(SUCCESS, "%s", msg); - memset(msg, 0, sizeof(msg)); - - // OTP - if (config & 0x80) { - strcat(msg, "Page 1 : " _RED_("locked") "\n"); - - strcat(msg + strlen(msg), "Page 2 : "); - if (config & 0x8) { - strcat(msg + strlen(msg), _RED_("locked")); - } else { - strcat(msg + strlen(msg), "read only"); - } - } else { - strcat(msg, "Page 1,2 : " _GREEN_("read write")); - } - PrintAndLogEx(SUCCESS, "%s", msg); - PrintAndLogEx(INFO, "------------------------------------"); -} - -static bool getHitagUid(uint32_t *uid) { - - UsbCommand c = {CMD_READER_HITAG, {RHT2F_UID_ONLY, 0, 0} }; + // Does the tag comes with memory + c.arg[0] = (uint32_t)tag_mem_supplied; clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return false; - } - - if (resp.arg[0] == false) { - PrintAndLogEx(DEBUG, "DEBUG: Error - failed getting UID"); - return false; - } - - if ( uid ) - *uid = bytes_to_num(resp.d.asBytes, 4); - - return true; -} - -int CmdLFHitagInfo(const char *Cmd) { - PrintAndLogEx(INFO, "Hitag2 tag information "); - PrintAndLogEx(INFO, "To be done!"); - PrintAndLogEx(INFO, "------------------------------------"); - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hitag_info(); - - // pwd or key - - // read UID - uint32_t uid = 0; - if ( getHitagUid( &uid ) == false ) - return 1; - - PrintAndLogEx(SUCCESS, "UID: %08X", uid); - - // how to detemine Hitag types? - - // read block3, get configuration byte. - - // common configurations. - printHitagConfiguration(0x06); - //printHitagConfiguration( 0x0E ); - //printHitagConfiguration( 0x02 ); - //printHitagConfiguration( 0x00 ); - //printHitagConfiguration( 0x04 ); return 0; } -// TODO: iceman -// Hitag2 reader, problem is that this command mixes up stuff. So 26 give uid. 21 etc will also give you a memory dump !? -// int CmdLFHitagReader(const char *Cmd) { UsbCommand c = {CMD_READER_HITAG, {0, 0, 0} }; @@ -517,25 +228,25 @@ int CmdLFHitagReader(const char *Cmd) { c.cmd = CMD_READ_HITAG_S; num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4); - break; + break; } case RHTSF_KEY: { c.cmd = CMD_READ_HITAG_S; num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); - break; + break; } case RHT2F_PASSWORD: { num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->pwd.password); - break; + break; } case RHT2F_AUTHENTICATE: { num_to_bytes(param_get32ex(Cmd, 1, 0, 16), 4, htd->auth.NrAr); num_to_bytes(param_get32ex(Cmd, 2, 0, 16), 4, htd->auth.NrAr + 4); - break; + break; } case RHT2F_CRYPTO: { num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); - break; + break; } case RHT2F_TEST_AUTH_ATTEMPTS: { // No additional parameters needed @@ -546,6 +257,7 @@ int CmdLFHitagReader(const char *Cmd) { break; } default: { + PrintAndLogEx(NORMAL, "\nError: unkown reader function %d", htf); return usage_hitag_reader(); } } @@ -566,136 +278,150 @@ int CmdLFHitagReader(const char *Cmd) { uint32_t id = bytes_to_num(resp.d.asBytes, 4); - PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id); - if (htf != RHT2F_UID_ONLY) { - - PrintAndLogEx(SUCCESS, "Dumping tag memory..." ); - uint8_t *data = resp.d.asBytes; - + if (htf == RHT2F_UID_ONLY) { + PrintAndLogEx(NORMAL, "Valid Hitag2 tag found - UID: %08x", id); + } else { char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - fnameptr += sprintf(fnameptr, "lf-hitag-"); - FillFileNameByUID(fnameptr, data, "-dump", 4); + FILE *f = NULL; + sprintf(filename, "%08x_%04x.ht2", id, (rand() & 0xffff)); + f = fopen(filename, "wb"); + if (!f) { + PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); + return 1; + } - saveFile(filename, "bin", data, 48); - saveFileEML(filename, "eml", data, 48, 4); - saveFileJSON(filename, "json", jsfHitag, data, 48); - - // block3, 1 byte - printHitagConfiguration(data[4*3] ); + // Write the 48 tag memory bytes to file and finalize + fwrite(resp.d.asBytes, 1, 48, f); + fclose(f); + PrintAndLogEx(NORMAL, "Succesfully saved tag memory to [%s]", filename); } return 0; } -int CmdLFHitagCheckChallenges(const char *Cmd) { - - UsbCommand c = { CMD_TEST_HITAGS_TRACES, {0, 0, 0}}; +int CmdLFHitagSimS(const char *Cmd) { + UsbCommand c = { CMD_SIMULATE_HITAG_S }; char filename[FILE_PATH_SIZE] = { 0x00 }; - size_t datalen = 0; - int res = 0; - bool file_given = false; - bool errors = false; - uint8_t cmdp = 0; - uint8_t *data = calloc(8 * 60, sizeof(uint8_t)); + FILE *f; + bool tag_mem_supplied; + int len = strlen(Cmd); + if (len > FILE_PATH_SIZE) + len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - free(data); - return usage_hitag_checkchallenges(); - case 'f': - param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)); - res = loadFile(filename, "cc", data, 8 * 60, &datalen); - if (res > 0) { - errors = true; - break; - } - - memcpy(c.d.asBytes, data, datalen); - file_given = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; + if (strlen(filename) > 0) { + f = fopen(filename, "rb+"); + if (!f) { + PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); + return 1; } + tag_mem_supplied = true; + size_t bytes_read = fread(c.d.asBytes, 1, 4 * 64, f); + if (bytes_read == 4 * 64) { + PrintAndLogEx(WARNING, "Error: File reading error"); + fclose(f); + return 1; + } + fclose(f); + } else { + tag_mem_supplied = false; } - //Validations - if (errors) { - free(data); - return usage_hitag_checkchallenges(); + // Does the tag comes with memory + c.arg[0] = (uint32_t) tag_mem_supplied; + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +int CmdLFHitagCheckChallenges(const char *Cmd) { + UsbCommand c = { CMD_TEST_HITAGS_TRACES }; + char filename[FILE_PATH_SIZE] = { 0x00 }; + FILE *f; + bool file_given; + int len = strlen(Cmd); + if (len > FILE_PATH_SIZE) + len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); + + if (strlen(filename) > 0) { + f = fopen(filename, "rb+"); + if (!f) { + PrintAndLogEx(WARNING, "Error: Could not open file [%s]", filename); + return 1; + } + file_given = true; + size_t bytes_read = fread(c.d.asBytes, 1, 8 * 60, f); + if (bytes_read == 8 * 60) { + PrintAndLogEx(WARNING, "Error: File reading error"); + fclose(f); + return 1; + } + fclose(f); + } else { + file_given = false; } //file with all the challenges to try c.arg[0] = (uint32_t)file_given; clearCommandBuffer(); SendCommand(&c); - - free(data); return 0; } -int CmdLFHitagWriter(const char *Cmd) { - UsbCommand c = { CMD_WR_HITAG_S, {0, 0, 0}}; +int CmdLFHitagWP(const char *Cmd) { + UsbCommand c = { CMD_WR_HITAG_S }; hitag_data *htd = (hitag_data *)c.d.asBytes; hitag_function htf = param_get32ex(Cmd, 0, 0, 10); - switch (htf) { - case WHTSF_CHALLENGE: { + case 03: { //WHTSF_CHALLENGE num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 8, htd->auth.NrAr); c.arg[2] = param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->auth.data); - break; } - case WHTSF_KEY: - case WHT2F_CRYPTO: { + break; + case 04: + case 24: { + //WHTSF_KEY num_to_bytes(param_get64ex(Cmd, 1, 0, 16), 6, htd->crypto.key); c.arg[2] = param_get32ex(Cmd, 2, 0, 10); num_to_bytes(param_get32ex(Cmd, 3, 0, 16), 4, htd->crypto.data); - break; - } - default: { - return usage_hitag_writer(); - } - } + } + break; + default: { + PrintAndLogEx(WARNING, "Error: unkown writer function %d", htf); + PrintAndLogEx(NORMAL, "Hitag writer functions"); + PrintAndLogEx(NORMAL, " HitagS (0*)"); + PrintAndLogEx(NORMAL, " 03 (Challenge) write page on a Hitag S tag"); + PrintAndLogEx(NORMAL, " 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); + PrintAndLogEx(NORMAL, " Hitag1 (1*)"); + PrintAndLogEx(NORMAL, " Hitag2 (2*)"); + return 1; + } + break; + } + // Copy the hitag function into the first argument c.arg[0] = htf; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; - } + WaitForResponse(CMD_ACK, &resp); - if (resp.arg[0] == false) { - PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed"); - return 1; - } - return 0; -} - -int CmdLFHitagDump(const char *Cmd) { - PrintAndLogEx(INFO, "Dumping of tag memory"); - PrintAndLogEx(INFO, "To be done!"); - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hitag_dump(); + // Check the return status, stored in the first argument + if (resp.arg[0] == false) return 1; return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help" }, - {"list", CmdLFHitagList, 0, "List Hitag trace history" }, - {"info", CmdLFHitagInfo, 1, "Tag information" }, - {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader" }, - {"sim", CmdLFHitagSim, 1, "Simulate Hitag transponder" }, - {"sniff", CmdLFHitagSniff, 1, "Eavesdrop Hitag communication" }, - {"writer", CmdLFHitagWriter, 1, "Act like a Hitag Writer" }, - {"cc", CmdLFHitagCheckChallenges, 1, "Test all challenges" }, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdLFHitagList, 1, " List Hitag trace history"}, + {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, + {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, + {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, + {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, + {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, + {"check_challenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, { NULL, NULL, 0, NULL } }; diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index eb5bb2dd0..e43ed58ff 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -14,12 +14,11 @@ extern int CmdLFHitag(const char *Cmd); extern int CmdLFHitagList(const char *Cmd); -extern int CmdLFHitagSniff(const char *Cmd); -extern int CmdLFHitagSim(const char *Cmd); -extern int CmdLFHitagInfo(const char *Cmd); extern int CmdLFHitagReader(const char *Cmd); +extern int CmdLFHitagSim(const char *Cmd); +extern int CmdLFHitagSimS(const char *Cmd); +extern int CmdLFHitagSnoop(const char *Cmd); +extern int CmdLFHitagWP(const char *Cmd); extern int CmdLFHitagCheckChallenges(const char *Cmd); -extern int CmdLFHitagWriter(const char *Cmd); -extern int CmdLFHitagDump(const char *cmd); #endif diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 41512c6b9..91f4a456f 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1882,7 +1882,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { // first try fliping each bit in the expected password while (bit < 32) { - curr_password = orig_password ^ (1u << bit); + curr_password = orig_password ^ (1 << bit); found = tryOnePassword(curr_password); if (found == -1) return 0; bit++; @@ -1897,7 +1897,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { // from low bit to high bit bit = 0; while (bit < 32) { - mask += (1u << bit); + mask += (1 << bit); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again if (prev_password == curr_password) { @@ -1916,7 +1916,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { bit = 0; mask = 0xffffffff; while (bit < 32) { - mask -= (1u << bit); + mask -= (1 << bit); curr_password = orig_password & mask; // if updated mask didn't change the password, don't try it again if (prev_password == curr_password) { diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 5d3c2e399..6abb9b5de 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -191,7 +191,7 @@ int CmdTIDemod(const char *Cmd) { bits[i] = '1'; maxPos += highLen; // bitstream arrives lsb first so shift right - shift3 |= (1u << 31); + shift3 |= (1 << 31); } else { bits[i] = '.'; maxPos += lowLen; diff --git a/client/cmdmain.c b/client/cmdmain.c index 5bbd689e1..608a0e668 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -74,4 +74,4 @@ int CmdRev(const char *Cmd) { //----------------------------------------------------------------------------- int CommandReceived(char *Cmd) { return CmdsParse(CommandTable, Cmd); -} +} \ No newline at end of file diff --git a/client/cmdscript.c b/client/cmdscript.c index e1a21ffc4..2e2ec5f53 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -193,4 +193,4 @@ int CmdScript(const char *Cmd) { int CmdHelp(const char *Cmd) { PrintAndLogEx(NORMAL, "This is a feature to run Lua-scripts. You can place lua-scripts within the scripts/-folder. "); return 0; -} +} \ No newline at end of file diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 8d00fa128..27b2afc39 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -49,13 +49,13 @@ int usage_sm_info(void) { return 0; } int usage_sm_upgrade(void) { - PrintAndLogEx(NORMAL, "Upgrade RDV4.0 Sim module firmware"); + PrintAndLogEx(NORMAL, "Upgrade firmware"); PrintAndLogEx(NORMAL, "Usage: sc upgrade f "); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " f : firmware file name"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc upgrade f ../tools/simmodule/SIM011.BIN"); + PrintAndLogEx(NORMAL, " sc upgrade f myfile"); return 0; } int usage_sm_setclock(void) { @@ -116,7 +116,7 @@ uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) { return atr[2]; } - return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1. + return 0x11; // default value is ‘0x11’, corresponding to fmax=5 MHz, Fi=372, Di=1. } int DiArray[] = { @@ -196,8 +196,6 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { uint8_t T0 = atr[1]; uint8_t K = T0 & 0x0F; uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; - bool protocol_T0_present = true; - bool protocol_T15_present = false; if (T0 & 0x10) { PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); @@ -217,14 +215,6 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (T0 & 0x80) { TD1 = atr[2 + T1len]; PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); - protocol_T0_present = false; - if ((TD1 & 0x0f) == 0) { - protocol_T0_present = true; - } - if ((TD1 & 0x0f) == 15) { - protocol_T15_present = true; - } - T1len++; if (TD1 & 0x10) { @@ -242,12 +232,6 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (TD1 & 0x80) { uint8_t TDi = atr[2 + T1len + TD1len]; PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); - if ((TDi & 0x0f) == 0) { - protocol_T0_present = true; - } - if ((TDi & 0x0f) == 15) { - protocol_T15_present = true; - } TD1len++; bool nextCycle = true; @@ -278,20 +262,19 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { } } - if (!protocol_T0_present || protocol_T15_present) { // there is CRC Check Byte TCK - uint8_t vxor = 0; - for (int i = 1; i < atrlen; i++) - vxor ^= atr[i]; + uint8_t vxor = 0; + for (int i = 1; i < atrlen; i++) + vxor ^= atr[i]; - if (vxor) - PrintAndLogEx(WARNING, "Check sum error. Must be 0 got 0x%02X", vxor); - else - PrintAndLogEx(INFO, "Check sum OK."); - } + if (vxor) + PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); + else + PrintAndLogEx(INFO, "Check summ OK."); if (atr[0] != 0x3b) PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); + uint8_t calen = 2 + T1len + TD1len + TDilen + K; if (atrlen != calen && atrlen != calen + 1) // may be CRC @@ -578,9 +561,8 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave int CmdSmartUpgrade(const char *Cmd) { - PrintAndLogEx(WARNING, "WARNING - Sim module firmware upgrade."); - PrintAndLogEx(WARNING, "A dangerous command, do wrong and you could brick the sim module"); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); + PrintAndLogEx(WARNING, "A dangerous command, do wrong and you will brick the smart card socket"); FILE *f; char filename[FILE_PATH_SIZE] = {0}; @@ -610,33 +592,10 @@ int CmdSmartUpgrade(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_sm_upgrade(); - - char sha512filename[FILE_PATH_SIZE] = {'\0'}; - char *bin_extension = filename; - char *dot_position = NULL; - while ((dot_position = strchr(bin_extension, '.')) != NULL) { - bin_extension = dot_position + 1; - } - - if (!strcmp(bin_extension, "BIN") -#ifdef _WIN32 - || !strcmp(bin_extension, "bin") -#endif - ) { - memcpy(sha512filename, filename, strlen(filename) - strlen("bin")); - strcat(sha512filename, "sha512.txt"); - } else { - PrintAndLogEx(FAILED, "Filename extension of firmware upgrade file must be .BIN"); - return 1; - } - - PrintAndLogEx(INFO, "firmware file : " _YELLOW_("%s"), filename); - PrintAndLogEx(INFO, "Checking integrity : " _YELLOW_("%s"), sha512filename); - - // load firmware file + // load file f = fopen(filename, "rb"); if (!f) { - PrintAndLogEx(FAILED, "Firmware file " _YELLOW_("%s") " not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_("%s") ": not found or locked.", filename); return 1; } @@ -646,77 +605,27 @@ int CmdSmartUpgrade(const char *Cmd) { fseek(f, 0, SEEK_SET); if (fsize < 0) { - PrintAndLogEx(WARNING, "error, when getting filesize"); + PrintAndLogDevice(WARNING, "error, when getting filesize"); fclose(f); return 1; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { - PrintAndLogEx(WARNING, "error, cannot allocate memory "); + PrintAndLogDevice(WARNING, "error, cannot allocate memory "); fclose(f); return 1; } - size_t firmware_size = fread(dump, 1, fsize, f); - if (f) { - fclose(f); - } - - // load sha512 file - f = fopen(sha512filename, "rb"); - if (!f) { - PrintAndLogEx(FAILED, "SHA-512 file not found or locked."); - return 1; - } - - // get filesize in order to malloc memory - fseek(f, 0, SEEK_END); - fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - if (fsize < 0) { - PrintAndLogEx(FAILED, "Could not determine size of SHA-512 file"); - fclose(f); - return 1; - } - - if (fsize < 128) { - PrintAndLogEx(FAILED, "SHA-512 file too short"); - fclose(f); - return 1; - } - - char hashstring[129]; - size_t bytes_read = fread(hashstring, 1, 128, f); - hashstring[128] = '\0'; - + size_t bytes_read = fread(dump, 1, fsize, f); if (f) fclose(f); - uint8_t hash1[64]; - if (bytes_read != 128 || param_gethex(hashstring, 0, hash1, 128)) { - PrintAndLogEx(FAILED, "Couldn't read SHA-512 file"); - return 1; - } - - uint8_t hash2[64]; - if (sha512hash(dump, firmware_size, hash2)) { - PrintAndLogEx(FAILED, "Couldn't calculate SHA-512 of firmware"); - return 1; - } - - if (memcmp(hash1, hash2, 64)) { - PrintAndLogEx(FAILED, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)")); - return 1; - } - - PrintAndLogEx(SUCCESS, "Sim module firmware uploading to PM3"); - + PrintAndLogEx(SUCCESS, "Smartcard socket firmware uploading to PM3"); //Send to device uint32_t index = 0; uint32_t bytes_sent = 0; - uint32_t bytes_remaining = firmware_size; + uint32_t bytes_remaining = bytes_read; while (bytes_remaining > 0) { uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining); @@ -740,10 +649,10 @@ int CmdSmartUpgrade(const char *Cmd) { } free(dump); printf("\n"); - PrintAndLogEx(SUCCESS, "Sim module firmware updating, don\'t turn off your PM3!"); + PrintAndLogEx(SUCCESS, "Smartcard socket firmware updating, don\'t turn off your PM3!"); // trigger the firmware upgrade - UsbCommand c = {CMD_SMART_UPGRADE, {firmware_size, 0, 0}}; + UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -751,12 +660,10 @@ int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; } - if ((resp.arg[0] & 0xFF)) { - PrintAndLogEx(SUCCESS, "Sim module firmware upgrade " _GREEN_("successful")); - PrintAndLogEx(SUCCESS, "\n run " _YELLOW_("`hw status`") " to validate the fw version "); - } else { - PrintAndLogEx(FAILED, "Sim module firmware upgrade " _RED_("failed")); - } + if ((resp.arg[0] & 0xFF)) + PrintAndLogEx(SUCCESS, "Smartcard socket firmware upgraded successful"); + else + PrintAndLogEx(FAILED, "Smartcard socket firmware updating failed"); return 0; } @@ -967,11 +874,11 @@ static void smart_brute_prim() { if (len > 2) { - // if ( decodeTLV ) { - // if (!TLVPrintFromBuffer(buf, len-2)) { + //if ( decodeTLV ) { + //if (!TLVPrintFromBuffer(buf, len-2)) { PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); - // } - // } + //} + //} } len = 0; } @@ -1217,14 +1124,14 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdSmartList, 0, "List ISO 7816 history"}, - {"info", CmdSmartInfo, 1, "Tag information"}, - {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, - {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, - {"upgrade", CmdSmartUpgrade, 1, "Upgrade sim module firmware"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdSmartList, 0, "List ISO 7816 history"}, + {"info", CmdSmartInfo, 1, "Tag information"}, + {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, + {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, + {"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware"}, {"setclock", CmdSmartSetClock, 1, "Set clock speed"}, - {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, + {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 251859761..14e79cd4e 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -25,7 +25,6 @@ #include "emv/emvcore.h" // decodeTVL #include "emv/apduinfo.h" // APDUcode description #include "emv/dump.h" // dump_buffer -#include "crypto/libpcrypto.h" // sha512hash extern int CmdSmartcard(const char *Cmd); @@ -41,4 +40,4 @@ extern int usage_sm_raw(void); extern int usage_sm_reader(void); extern int usage_sm_info(void); extern int usage_sm_upgrade(void); -#endif +#endif \ No newline at end of file diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 05a85a050..77f85ce5c 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -36,7 +36,6 @@ int usage_trace_list() { PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); PrintAndLogEx(NORMAL, " legic - interpret data as LEGIC communications"); PrintAndLogEx(NORMAL, " felica - interpret data as ISO18092 / FeliCa communications"); - PrintAndLogEx(NORMAL, " hitag - interpret data as Hitag2 / HitagS communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " trace list 14a f"); @@ -176,7 +175,6 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso15693_CRC_check(frame, data_len); break; case ISO_7816_4: - case PROTO_HITAG: default: break; } @@ -191,12 +189,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui for (int j = 0; j < data_len && j / 18 < 18; j++) { uint8_t parityBits = parityBytes[j >> 3]; - if (protocol != LEGIC - && protocol != ISO_14443B - && protocol != ISO_7816_4 - && protocol != PROTO_HITAG - && (isResponse || protocol == ISO_14443A) - && (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { + if (protocol != LEGIC && + protocol != ISO_14443B && + protocol != ISO_7816_4 && + (isResponse || protocol == ISO_14443A) && + (oddparity8(frame[j]) != ((parityBits >> (7 - (j & 0x0007))) & 0x01))) { snprintf(line[j / 18] + ((j % 18) * 4), 110, "%02x! ", frame[j]); } else { @@ -559,17 +556,16 @@ int CmdTraceList(const char *Cmd) { // validate type of output if (strcmp(type, "iclass") == 0) protocol = ICLASS; - else if (strcmp(type, "14a") == 0) protocol = ISO_14443A; - else if (strcmp(type, "14b") == 0) protocol = ISO_14443B; - else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; - else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4; - else if (strcmp(type, "des") == 0) protocol = MFDES; - else if (strcmp(type, "legic") == 0) protocol = LEGIC; - else if (strcmp(type, "15") == 0) protocol = ISO_15693; - else if (strcmp(type, "felica") == 0) protocol = FELICA; - else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; - else if (strcmp(type, "hitag") == 0) protocol = PROTO_HITAG; - else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations + else if (strcmp(type, "14a") == 0) protocol = ISO_14443A; + else if (strcmp(type, "14b") == 0) protocol = ISO_14443B; + else if (strcmp(type, "topaz") == 0) protocol = TOPAZ; + else if (strcmp(type, "7816") == 0) protocol = ISO_7816_4; + else if (strcmp(type, "des") == 0) protocol = MFDES; + else if (strcmp(type, "legic") == 0) protocol = LEGIC; + else if (strcmp(type, "15") == 0) protocol = ISO_15693; + else if (strcmp(type, "felica") == 0) protocol = FELICA; + else if (strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; + else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations else errors = true; cmdp++; @@ -629,8 +625,6 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if (protocol == ISO_7816_4) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); - if (protocol == PROTO_HITAG) - PrintAndLogEx(NORMAL, "Hitag2 / HitagS - Timings in ETU (8us)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); @@ -648,8 +642,8 @@ int CmdTraceLoad(const char *Cmd) { FILE *f = NULL; char filename[FILE_PATH_SIZE]; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_load(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load(); param_getstr(Cmd, 0, filename, sizeof(filename)); @@ -694,13 +688,13 @@ int CmdTraceLoad(const char *Cmd) { int CmdTraceSave(const char *Cmd) { if (traceLen == 0) { - PrintAndLogEx(WARNING, "trace is empty, nothing to save"); + PrintAndLogEx(WARNING, "trace is empty, exiting..."); return 0; } char filename[FILE_PATH_SIZE]; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_trace_save(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_save(); param_getstr(Cmd, 0, filename, sizeof(filename)); saveFile(filename, "bin", trace, traceLen); diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 095d16af3..883de0dbb 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include #include @@ -107,20 +106,6 @@ int sha256hash(uint8_t *input, int length, uint8_t *hash) { return 0; } -int sha512hash(uint8_t *input, int length, uint8_t *hash) { - if (!hash || !input) - return 1; - - mbedtls_sha512_context sctx; - mbedtls_sha512_init(&sctx); - mbedtls_sha512_starts(&sctx, 0); //SHA-512, not 384 - mbedtls_sha512_update(&sctx, input, length); - mbedtls_sha512_finish(&sctx, hash); - mbedtls_sha512_free(&sctx); - - return 0; -} - int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char *key_d, char *key_x, char *key_y) { if (!ctx) return 1; diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h index 2cb4644a8..5f3592b7a 100644 --- a/client/crypto/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -22,7 +22,6 @@ extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); extern int sha256hash(uint8_t *input, int length, uint8_t *hash); -extern int sha512hash(uint8_t *input, int length, uint8_t *hash); extern int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy); extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index b5edfa81c..31886cf75 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -288,7 +288,6 @@ int CmdEMVGPO(const char *cmd) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); - free(pdol_data_tlv); return 4; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1578,7 +1577,6 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); - free(pdol_data_tlv); DropFieldEx(channel); return 6; } diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 18326083f..d47109f7c 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -38,4 +38,4 @@ extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbu extern bool ParamLoadFromJson(struct tlvdb *tlv); -#endif +#endif \ No newline at end of file diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 7c5a4a883..36e5872e0 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -322,42 +322,42 @@ static int FpgaGatherVersion(FILE *infile, char *infile_name, char *dst, int len } if (!memcmp("fpga_lf", basename(infile_name), 7)) - strncat(dst, "LF", len - strlen(dst) - 1); + strncat(dst, "LF", len - 1); else if (!memcmp("fpga_hf", basename(infile_name), 7)) - strncat(dst, "HF", len - strlen(dst) - 1); + strncat(dst, "HF", len - 1); - strncat(dst, " image built", len - strlen(dst) - 1); + strncat(dst, " image built", len - 1); if (bitparse_find_section(infile, 'b', &fpga_info_len)) { - strncat(dst, " for ", len - strlen(dst) - 1); + strncat(dst, " for ", len - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - strlen(dst) - 1); + strncat(dst, tempstr, len - 1); } if (bitparse_find_section(infile, 'c', &fpga_info_len)) { - strncat(dst, " on ", len - strlen(dst) - 1); + strncat(dst, " on ", len - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - strlen(dst) - 1); + strncat(dst, tempstr, len - 1); } if (bitparse_find_section(infile, 'd', &fpga_info_len)) { - strncat(dst, " at ", len - strlen(dst) - 1); + strncat(dst, " at ", len - 1); for (uint16_t i = 0; i < fpga_info_len; i++) { char c = (char)fgetc(infile); if (i < sizeof(tempstr)) { tempstr[i] = c; } } - strncat(dst, tempstr, len - strlen(dst) - 1); + strncat(dst, tempstr, len - 1); } return 0; } diff --git a/client/hardnested/hardnested_tables.c b/client/hardnested/hardnested_tables.c index 09de7f5d7..bc92e5f10 100644 --- a/client/hardnested/hardnested_tables.c +++ b/client/hardnested/hardnested_tables.c @@ -577,4 +577,4 @@ int main(int argc, char *argv[]) { free_part_sum_bitarrays(); return 0; -} +} \ No newline at end of file diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index ac563bd26..5e562c10b 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -96,7 +96,7 @@ typedef struct { #define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_CLONE_TAG 0x021B #define CMD_EM410X_DEMOD 0x021c -// Sampling configuration for LF reader/sniffer +// Sampling configuration for LF reader/snooper #define CMD_SET_LF_SAMPLING_CONFIG 0x021d #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F @@ -119,10 +119,10 @@ typedef struct { #define CMD_ISO_15693_COMMAND 0x0313 #define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 +#define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 // For Hitag2 transponders -#define CMD_SNIFF_HITAG 0x0370 +#define CMD_SNOOP_HITAG 0x0370 #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 @@ -135,8 +135,8 @@ typedef struct { #define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNIFF_ISO_14443B 0x0382 -#define CMD_SNIFF_ISO_14443a 0x0383 +#define CMD_SNOOP_ISO_14443B 0x0382 +#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 @@ -151,7 +151,7 @@ typedef struct { #define CMD_LEGIC_ESET 0x03BD #define CMD_LEGIC_EGET 0x03BE -#define CMD_SNIFF_ICLASS 0x0392 +#define CMD_SNOOP_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS_REPLAY 0x0395 diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 038d8e475..41be3d39c 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -692,4 +692,4 @@ int testElite() { errors += _test_iclass_key_permutation(); errors += _testBruteforce(); return errors; -} +} \ No newline at end of file diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 0c345ca14..4d58c7084 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -155,12 +155,11 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty json_t *root = json_object(); JsonSaveStr(root, "Created", "proxmark3"); switch (ftype) { - case jsfRaw: { + case jsfRaw: JsonSaveStr(root, "FileType", "raw"); JsonSaveBufAsHexCompact(root, "raw", data, datalen); break; - } - case jsfCardMemory: { + case jsfCardMemory: JsonSaveStr(root, "FileType", "mfcard"); for (int i = 0; i < (datalen / 16); i++) { char path[PATH_MAX_LENGTH] = {0}; @@ -209,8 +208,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty } } break; - } - case jsfMfuMemory: { + case jsfMfuMemory: JsonSaveStr(root, "FileType", "mfu"); mfu_dump_t *tmp = (mfu_dump_t *)data; @@ -232,26 +230,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4; for (int i = 0; i < len; i++) { + char path[PATH_MAX_LENGTH] = {0}; sprintf(path, "$.blocks.%d", i); JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); } break; - } - case jsfHitag: { - JsonSaveStr(root, "FileType", "hitag"); - uint8_t uid[4] = {0}; - memcpy(uid, data, 4); - - JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid)); - - for (int i = 0; i < (datalen / 4); i++) { - char path[PATH_MAX_LENGTH] = {0}; - sprintf(path, "$.blocks.%d", i); - JsonSaveBufAsHexCompact(root, path, data + (i * 4), 4); - } - break; - } } int res = json_dump_file(root, fileName, JSON_INDENT(2)); @@ -269,7 +253,7 @@ out: return retval; } -int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen) { +int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen) { if (preferredName == NULL) return 1; if (suffix == NULL) return 1; @@ -314,11 +298,6 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m goto out; } - if (bytes_read != maxdatalen) { - PrintAndLogDevice(WARNING, "Warning, bytes read exeed calling array limit. Max bytes is %d bytes", maxdatalen); - bytes_read = maxdatalen; - } - memcpy((data), dump, bytes_read); free(dump); @@ -468,29 +447,8 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size *datalen = sptr; } - if (!strcmp(ctype, "hitag")) { - size_t sptr = 0; - for (int i = 0; i < (maxdatalen / 4); i++) { - if (sptr + 4 > maxdatalen) { - retval = 5; - goto out; - } - char path[30] = {0}; - sprintf(path, "$.blocks.%d", i); - - size_t len = 0; - JsonLoadBufAsHex(root, path, &udata[sptr], 4, &len); - if (!len) - break; - - sptr += len; - } - - *datalen = sptr; - } - - PrintAndLogEx(SUCCESS, "loaded from JSON file " _YELLOW_("%s"), fileName); + PrintAndLog("loaded from JSON file " _YELLOW_("%s"), fileName); out: json_decref(root); free(fileName); diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 7b358331a..c2888c196 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -55,11 +55,6 @@ typedef enum { jsfRaw, jsfCardMemory, jsfMfuMemory, - jsfHitag, -// jsf14b, -// jsf15, -// jsfLegic, -// jsfT55xx, } JSONFileType; int fileExists(const char *filename); @@ -112,11 +107,10 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT * @param preferredName * @param suffix the file suffix. Leave out the ".". * @param data The data array to store the loaded bytes from file - * @param maxdatalen the number of bytes that your data array has * @param datalen the number of bytes loaded from file * @return 0 for ok, 1 for failz */ -extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); +extern int loadFile(const char *preferredName, const char *suffix, void *data, size_t *datalen); /** * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. diff --git a/client/lualibs/7816_error.lua b/client/lualibs/7816_error.lua index 15f4ef471..038f668fb 100644 --- a/client/lualibs/7816_error.lua +++ b/client/lualibs/7816_error.lua @@ -75,4 +75,4 @@ _errorcodes.tostring = function(command) end return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) end -return _errorcodes +return _errorcodes \ No newline at end of file diff --git a/client/lualibs/hf_reader.lua b/client/lualibs/hf_reader.lua index b99b521da..d0550a335 100644 --- a/client/lualibs/hf_reader.lua +++ b/client/lualibs/hf_reader.lua @@ -32,4 +32,4 @@ end return { waitForTag = waitForTag, -} +} \ No newline at end of file diff --git a/client/lualibs/precalc.lua b/client/lualibs/precalc.lua index 7da08f006..71d91c05a 100644 --- a/client/lualibs/precalc.lua +++ b/client/lualibs/precalc.lua @@ -91,4 +91,4 @@ local PreCalc = return list end, } -return PreCalc +return PreCalc \ No newline at end of file diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index 2ee86c378..3711c02a3 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -155,4 +155,4 @@ local library = { ISO14B_COMMAND = ISO14B_COMMAND, } -return library +return library \ No newline at end of file diff --git a/client/lualibs/taglib.lua b/client/lualibs/taglib.lua index 0612ed2d3..715a29487 100644 --- a/client/lualibs/taglib.lua +++ b/client/lualibs/taglib.lua @@ -121,4 +121,4 @@ return { return m[value] or "no tag-info available" end, -} +} \ No newline at end of file diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index ed9874e40..697e48b72 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -427,4 +427,4 @@ local Utils = -- end } -return Utils +return Utils \ No newline at end of file diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 626d2cd07..1d9f0c3ab 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -100,4 +100,4 @@ extern int detect_classic_prng(void); extern int detect_classic_nackbug(bool verbose); extern void detect_classic_magic(void); extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); -#endif +#endif \ No newline at end of file diff --git a/client/pm3_eml_mfd_test.py b/client/pm3_eml_mfd_test.py index 171bad843..478a050df 100644 --- a/client/pm3_eml_mfd_test.py +++ b/client/pm3_eml_mfd_test.py @@ -21,7 +21,7 @@ class TestEmlMfd(unittest.TestCase): ] def test_eml2mfd(self): self.three_argument_test(pm3_eml2mfd.main, self.EML2MFD_TESTCASES) - + def test_mfd2eml(self): self.three_argument_test(pm3_mfd2eml.main, imap(reversed, self.EML2MFD_TESTCASES), c14n=hex_c14n) diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 2f305a285..d5bdac2dd 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -939,4 +939,4 @@ static void munpack(model_t *dest, const struct mpreset *src) { dest->flags = src->flags; /* link to the name as it is static */ dest->name = (src->alias) ? src->alias->name : NULL; -} +} \ No newline at end of file diff --git a/client/scandir.h b/client/scandir.h index 7155c5a79..a41a13319 100644 --- a/client/scandir.h +++ b/client/scandir.h @@ -19,4 +19,4 @@ extern int scandir(const char *dir, struct dirent ***namelist, int (*select)(con extern int alphasort(const struct dirent **a, const struct dirent **b); #endif // _WIN32 -#endif // SCANDIR_H__ +#endif // SCANDIR_H__ \ No newline at end of file diff --git a/client/scripting.c b/client/scripting.c index 719798177..14dc35774 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -776,4 +776,4 @@ int set_pm3_libraries(lua_State *L) { strcat(libraries_path, LUA_LIBRARIES_WILDCARD); setLuaPath(L, libraries_path); return 1; -} +} \ No newline at end of file diff --git a/client/scripts/Legic_clone.lua b/client/scripts/Legic_clone.lua index 21d756d0e..dcac7f323 100644 --- a/client/scripts/Legic_clone.lua +++ b/client/scripts/Legic_clone.lua @@ -538,4 +538,4 @@ function main(args) end -- call main with arguments -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/brutesim.lua b/client/scripts/brutesim.lua index a15cf6e60..9527d8970 100644 --- a/client/scripts/brutesim.lua +++ b/client/scripts/brutesim.lua @@ -297,4 +297,4 @@ local function main(args) core.console('hw ping') end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/calc_di.lua b/client/scripts/calc_di.lua index 9a8c051a4..e0b587332 100644 --- a/client/scripts/calc_di.lua +++ b/client/scripts/calc_di.lua @@ -173,4 +173,4 @@ local function main(args) dumptofile( keys ) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/calc_ev1_it.lua b/client/scripts/calc_ev1_it.lua index b4e995e96..c6070d20d 100644 --- a/client/scripts/calc_ev1_it.lua +++ b/client/scripts/calc_ev1_it.lua @@ -175,4 +175,4 @@ local function main(args) print(string.format('PWD | %s', pwd)) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/calc_mizip.lua b/client/scripts/calc_mizip.lua index 8844f6d66..42f13c578 100644 --- a/client/scripts/calc_mizip.lua +++ b/client/scripts/calc_mizip.lua @@ -194,4 +194,4 @@ local function main(args) dumptofile( keys ) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/calypso.lua b/client/scripts/calypso.lua index 74de3cb9a..2b7252261 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/calypso.lua @@ -273,4 +273,4 @@ if "--test"==args then else -- Call the main main(args) -end +end \ No newline at end of file diff --git a/client/scripts/e.lua b/client/scripts/e.lua index 1f9a14eb0..6b9d80364 100644 --- a/client/scripts/e.lua +++ b/client/scripts/e.lua @@ -74,4 +74,4 @@ function main(args) end end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/emul2dump.lua b/client/scripts/emul2dump.lua index 0cbc3a4c2..04b9da12b 100644 --- a/client/scripts/emul2dump.lua +++ b/client/scripts/emul2dump.lua @@ -57,4 +57,4 @@ local function main(args) ExitMsg(("Wrote a BIN dump to the file %s"):format(filename)) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/emul2html.lua b/client/scripts/emul2html.lua index 36230f8af..db76ec9c0 100644 --- a/client/scripts/emul2html.lua +++ b/client/scripts/emul2html.lua @@ -64,4 +64,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua index fe9cf32e5..90801b2a2 100644 --- a/client/scripts/formatMifare.lua +++ b/client/scripts/formatMifare.lua @@ -213,4 +213,4 @@ local function main(args) end end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/hf_read.lua b/client/scripts/hf_read.lua index 00238a67c..7653e6e75 100644 --- a/client/scripts/hf_read.lua +++ b/client/scripts/hf_read.lua @@ -15,4 +15,4 @@ local function main(args) end return end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/htmldump.lua b/client/scripts/htmldump.lua index afd76abee..40f3028b4 100644 --- a/client/scripts/htmldump.lua +++ b/client/scripts/htmldump.lua @@ -62,4 +62,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/lf_bulk.lua b/client/scripts/lf_bulk.lua index dc59572f3..b4604bebb 100644 --- a/client/scripts/lf_bulk.lua +++ b/client/scripts/lf_bulk.lua @@ -190,4 +190,4 @@ local function main(args) end end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index ff739683d..18078b822 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -272,4 +272,4 @@ local function main(args) print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec') end -main( args) +main( args) \ No newline at end of file diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index 0bb597a52..4a740d7e6 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -244,4 +244,4 @@ local function main( args) prlog(string.format("Dumped data into %s", filename)) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/ntag_3d.lua b/client/scripts/ntag_3d.lua index 2f08aac85..890f29d94 100644 --- a/client/scripts/ntag_3d.lua +++ b/client/scripts/ntag_3d.lua @@ -380,4 +380,4 @@ local function main(args) write_tag(uid, t) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/parameters.lua b/client/scripts/parameters.lua index 4eb86446d..f51266f7f 100644 --- a/client/scripts/parameters.lua +++ b/client/scripts/parameters.lua @@ -42,4 +42,4 @@ In the future, we may implement so that scripts are invoked directly into a 'main' function, instead of being executed blindly. For future compatibility, I have done so, but I invoke my main from here. --]] -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/test_t55x7_ask.lua b/client/scripts/test_t55x7_ask.lua index 0e0d3d9e3..3f224b28a 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/scripts/test_t55x7_ask.lua @@ -137,4 +137,4 @@ local function main(args) test() print( string.rep('--',20) ) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/test_t55x7_fsk.lua b/client/scripts/test_t55x7_fsk.lua index 492f71681..9dbb1b6bb 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/scripts/test_t55x7_fsk.lua @@ -137,4 +137,4 @@ local function main(args) test(7) print( string.rep('--',20) ) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index f48abff6c..2a5545497 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -282,4 +282,4 @@ local function main(args) core.clearCommandBuffer() end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/tracetest.lua b/client/scripts/tracetest.lua index c3ddedf87..96d1f79c6 100644 --- a/client/scripts/tracetest.lua +++ b/client/scripts/tracetest.lua @@ -123,4 +123,4 @@ local function main(args) print( string.rep('--',20) ) end -main(args) +main(args) \ No newline at end of file diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua index f91949166..67949fd94 100644 --- a/client/scripts/ufodump.lua +++ b/client/scripts/ufodump.lua @@ -173,4 +173,4 @@ if "--test"==args then else -- Call the main main(args) -end +end \ No newline at end of file diff --git a/client/snooper.c b/client/snooper.c index 35267bc22..88a30edaa 100644 --- a/client/snooper.c +++ b/client/snooper.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// Sniff binary +// Snooper binary //----------------------------------------------------------------------------- #include "util_posix.h" @@ -19,7 +19,7 @@ int main() { usb_init(); - SetLogFilename("sniffer.log"); + SetLogFilename("snooper.log"); return_on_error = 1; @@ -27,7 +27,7 @@ int main() { while (!OpenProxmark()) { sleep(1); } while (1) { UsbCommand cmdbuf; - CommandReceived("hf 14a sniff"); + CommandReceived("hf 14a snoop"); HANDLE_ERROR; ReceiveCommand(&cmdbuf); HANDLE_ERROR; diff --git a/client/util.c b/client/util.c index a3f275a0b..0b3211264 100644 --- a/client/util.c +++ b/client/util.c @@ -252,10 +252,7 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea // loop through the out_index to make sure we don't go too far for (out_index = 0; out_index < rowlen; out_index++) { // set character - if (data[in_index] == 7) // Manchester wrong bit marker - sprintf(tmp++, "."); - else - sprintf(tmp++, "%u", data[in_index]); + sprintf(tmp++, "%u", data[in_index]); // check if a line break is needed and we have room to print it in our array if ((breaks > 0) && !((in_index + 1) % breaks) && (out_index + 1 != rowlen)) { // increment and print line break @@ -686,45 +683,24 @@ int hextobinstring(char *target, char *source) { return length; } -// convert binary array of 0x00/0x01 values to hex +// convert binary array of 0x00/0x01 values to hex (safe to do in place as target will always be shorter than source) // return number of bits converted -int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen) { - uint8_t i = 0, x = 0; - uint32_t t = 0; // written target chars - uint32_t r = 0; // consumed bits - uint8_t w = 0; // wrong bits separator printed - for (size_t s = 0 ; s < srclen; s++) { - if ((source[s] == 0) || (source[s] == 1)) { - w = 0; - x += (source[s] << (3 - i)); - i++; - if (i == 4) { - if (t >= targetlen - 2) return r; - sprintf(target + t, "%X", x); - t++; - r += 4; - x = 0; - i = 0; - } - } else { - if (i > 0) { - if (t >= targetlen - 5) return r; - w = 0; - sprintf(target + t, "%X[%i]", x, i); - t += 4; - r += i; - x = 0; - i = 0; - } - if (w == 0) { - if (t >= targetlen - 2) return r; - sprintf(target + t, " "); - t++; - } - r++; - } +int binarraytohex(char *target, char *source, int length) { + unsigned char i, x; + int j = length; + + if (j % 4) + return 0; + + while (j) { + for (i = x = 0 ; i < 4 ; ++i) + x += (source[i] << (3 - i)); + sprintf(target, "%X", x); + ++target; + source += 4; + j -= 4; } - return r; + return length; } // convert binary array to human readable binary @@ -897,4 +873,4 @@ extern char *strmcopy(char *buf) { strcpy(str, buf); } return str; -} +} \ No newline at end of file diff --git a/client/util.h b/client/util.h index c754542ab..9c68900e7 100644 --- a/client/util.h +++ b/client/util.h @@ -241,7 +241,7 @@ extern int param_getstr(const char *line, int paramnum, char *str, size_t buffer extern int hextobinarray(char *target, char *source); extern int hextobinstring(char *target, char *source); -extern int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen); +extern int binarraytohex(char *target, char *source, int length); extern void binarraytobinstring(char *target, char *source, int length); extern uint8_t GetParity(uint8_t *string, uint8_t type, int length); extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); @@ -263,4 +263,4 @@ extern bool str_startswith(const char *s, const char *pre); // check for prefi extern void strcleanrn(char *buf, size_t len); extern void strcreplace(char *buf, size_t len, char from, char to); extern char *strmcopy(char *buf); -#endif +#endif \ No newline at end of file diff --git a/client/util_darwin.h b/client/util_darwin.h index d89b681f2..15af75404 100644 --- a/client/util_darwin.h +++ b/client/util_darwin.h @@ -16,4 +16,4 @@ void enableAppNap(); void makeUnfocusable(); void makeFocusable(); -#endif +#endif \ No newline at end of file diff --git a/common/bucketsort.h b/common/bucketsort.h index 0a56509c1..1de175ae5 100644 --- a/common/bucketsort.h +++ b/common/bucketsort.h @@ -21,4 +21,4 @@ typedef struct bucket_info { void bucket_sort_intersect(uint32_t *const estart, uint32_t *const estop, uint32_t *const ostart, uint32_t *const ostop, bucket_info_t *bucket_info, bucket_array_t bucket); -#endif +#endif \ No newline at end of file diff --git a/common/cmd.c b/common/cmd.c index 3b45c08ad..5f42c669a 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -61,4 +61,4 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void #endif return sendlen; -} +} \ No newline at end of file diff --git a/common/crc.c b/common/crc.c index 2ad7609b1..0846697de 100644 --- a/common/crc.c +++ b/common/crc.c @@ -123,4 +123,4 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size) { for (int i = 0; i < size; ++i) crc_update2(&crc, buff[i], 8); return reflect8(crc_finish(&crc)); -} +} \ No newline at end of file diff --git a/common/crc16.h b/common/crc16.h index 9a202f514..b88995a40 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -67,4 +67,4 @@ void reset_table(void); void generate_table(uint16_t polynomial, bool refin); uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bool refout); -#endif +#endif \ No newline at end of file diff --git a/common/crc32.c b/common/crc32.c index 440bed910..3ee102ce5 100644 --- a/common/crc32.c +++ b/common/crc32.c @@ -29,4 +29,4 @@ void crc32_ex(const uint8_t *data, const size_t len, uint8_t *crc) { void crc32_append(uint8_t *data, const size_t len) { crc32_ex(data, len, data + len); -} +} \ No newline at end of file diff --git a/common/crc64.c b/common/crc64.c index 23360f6bd..7d582da02 100644 --- a/common/crc64.c +++ b/common/crc64.c @@ -80,4 +80,4 @@ void crc64(const uint8_t *data, const size_t len, uint64_t *crc) { } } -//suint8_t x = (c & 0xFF00000000000000 ) >> 56; +//suint8_t x = (c & 0xFF00000000000000 ) >> 56; \ No newline at end of file diff --git a/common/i2c.h b/common/i2c.h index df7f6698c..4254a73c3 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -48,4 +48,4 @@ void SmartCardUpgrade(uint64_t arg0); void SmartCardSetBaud(uint64_t arg0); void SmartCardSetClock(uint64_t arg0); void I2C_print_status(void); -#endif +#endif \ No newline at end of file diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 795d1be60..7b64c99d1 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -14,13 +14,12 @@ // return: ptr to string char *Iso15693sprintUID(char *target, uint8_t *uid) { - static char tempbuf[3 * 8 + 1] = {0}; + static char tempbuf[2 * 8 + 1] = {0}; if (target == NULL) target = tempbuf; - sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0] ); return target; -} +} \ No newline at end of file diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 26a7a87a7..d7a1b2bb5 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -123,4 +123,4 @@ static const int Iso15693FrameEOF[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; -#endif +#endif \ No newline at end of file diff --git a/common/legic_prng.c b/common/legic_prng.c index 5406161fc..fd5543cf7 100644 --- a/common/legic_prng.c +++ b/common/legic_prng.c @@ -62,4 +62,4 @@ uint32_t legic_prng_get_bits(uint8_t len) { legic_prng_forward(1); } return a; -} +} \ No newline at end of file diff --git a/common/lfdemod.c b/common/lfdemod.c index 653c2a308..f356e7578 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1357,7 +1357,6 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { //by marshmellow //take 10 and 01 and manchester decode //run through 2 times and take least errCnt -// "7" indicates 00 or 11 wrong bit int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) { // sanity check @@ -1369,7 +1368,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) //find correct start position [alignment] for (k = 0; k < 2; ++k) { - for (i = k; i < *size - 1; i += 2) { + for (i = k; i < *size - 3; i += 2) { if (bits[i] == bits[i + 1]) errCnt++; } @@ -1381,7 +1380,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) } *alignPos = bestRun; //decode - for (i = bestRun; i < *size - 1; i += 2) { + for (i = bestRun; i < *size - 3; i += 2) { if (bits[i] == 1 && (bits[i + 1] == 0)) { bits[bitnum++] = invert; } else if ((bits[i] == 0) && bits[i + 1] == 1) { diff --git a/common/lfdemod.h b/common/lfdemod.h index 96a91363f..883393cc3 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -22,7 +22,7 @@ #include "util.h" // for ARRAYLEN //might not be high enough for noisy environments -#define NOISE_AMPLITUDE_THRESHOLD 15 +#define NOISE_AMPLITUDE_THRESHOLD 10 //ignore buffer with less than x samples #define SIGNAL_MIN_SAMPLES 100 //ignore first x samples of the buffer diff --git a/common/prng.h b/common/prng.h index b9f49c6b6..f160d6b30 100644 --- a/common/prng.h +++ b/common/prng.h @@ -21,4 +21,4 @@ void burtle_init_mod(prng_ctx *x, uint32_t seed); void burtle_init(prng_ctx *x, uint32_t seed); uint32_t GetSimplePrng(uint32_t seed); -#endif /* __PRNG_H */ +#endif /* __PRNG_H */ \ No newline at end of file diff --git a/common/protocols.h b/common/protocols.h index 9fc168d46..00e3ef902 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -277,7 +277,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO_15693 7 #define FELICA 8 #define PROTO_MIFARE 9 -#define PROTO_HITAG 10 //-- Picopass fuses #define FUSE_FPERS 0x80 diff --git a/common/radixsort.c b/common/radixsort.c index 83b26d609..67f2910c1 100644 --- a/common/radixsort.c +++ b/common/radixsort.c @@ -96,4 +96,4 @@ uint64_t *radixSort(uint64_t *array, uint32_t size) { } free(cpy); return array; -} +} \ No newline at end of file diff --git a/common/radixsort.h b/common/radixsort.h index 41a036461..29faf9825 100644 --- a/common/radixsort.h +++ b/common/radixsort.h @@ -20,4 +20,4 @@ typedef union { } rscounts_t; uint64_t *radixSort(uint64_t *array, uint32_t size); -#endif // RADIXSORT_H__ +#endif // RADIXSORT_H__ \ No newline at end of file diff --git a/common/random.h b/common/random.h index 85c90dd38..315794f8d 100644 --- a/common/random.h +++ b/common/random.h @@ -18,4 +18,4 @@ void fast_prand(); void fast_prandEx(uint32_t seed); uint32_t prand(); -#endif +#endif \ No newline at end of file diff --git a/common/tea.h b/common/tea.h index 43ac93428..3a12a769d 100644 --- a/common/tea.h +++ b/common/tea.h @@ -15,4 +15,4 @@ #include void tea_encrypt(uint8_t *v, uint8_t *key); void tea_decrypt(uint8_t *v, uint8_t *key); -#endif /* __TEA_H */ +#endif /* __TEA_H */ \ No newline at end of file diff --git a/common/usart.c b/common/usart.c index 869179091..46e8517fc 100644 --- a/common/usart.c +++ b/common/usart.c @@ -140,4 +140,4 @@ void usart_init(void) { // re-enable receiver / transmitter pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); -} +} \ No newline at end of file diff --git a/common/usb_cdc.c b/common/usb_cdc.c index c871de241..d70c8ee04 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -949,4 +949,4 @@ void AT91F_CDC_Enumerate() { AT91F_USB_SendStall(pUdp); break; } -} +} \ No newline at end of file diff --git a/common/wiegand.c b/common/wiegand.c index e319e1a08..2da88b085 100644 --- a/common/wiegand.c +++ b/common/wiegand.c @@ -236,4 +236,4 @@ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, default: break; } -} +} \ No newline at end of file diff --git a/include/at91sam7s512.h b/include/at91sam7s512.h index f9f5f69b1..f8fa2e8d4 100644 --- a/include/at91sam7s512.h +++ b/include/at91sam7s512.h @@ -375,7 +375,7 @@ typedef struct _AT91S_DBGU { #define AT91C_US_TXBUFE (0x1 << 11) // (DBGU) TXBUFE Interrupt #define AT91C_US_RXBUFF (0x1 << 12) // (DBGU) RXBUFF Interrupt #define AT91C_US_COMM_TX (0x1 << 30) // (DBGU) COMM_TX Interrupt -#define AT91C_US_COMM_RX (0x1u << 31) // (DBGU) COMM_RX Interrupt +#define AT91C_US_COMM_RX (0x1 << 31) // (DBGU) COMM_RX Interrupt // -------- DBGU_IDR : (DBGU Offset: 0xc) Debug Unit Interrupt Disable Register -------- // -------- DBGU_IMR : (DBGU Offset: 0x10) Debug Unit Interrupt Mask Register -------- // -------- DBGU_CSR : (DBGU Offset: 0x14) Debug Unit Channel Status Register -------- diff --git a/include/common.h b/include/common.h index 8bf8ab702..2c3febc98 100644 --- a/include/common.h +++ b/include/common.h @@ -115,4 +115,4 @@ typedef struct { #ifdef __cplusplus } #endif -#endif +#endif \ No newline at end of file diff --git a/include/hitag.h b/include/hitag.h deleted file mode 100644 index 742d7ecd0..000000000 --- a/include/hitag.h +++ /dev/null @@ -1,117 +0,0 @@ -//----------------------------------------------------------------------------- -// 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. -//----------------------------------------------------------------------------- -// Hitag2, HitagS -// -// (c) 2012 Roel Verdult -// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg -// -//----------------------------------------------------------------------------- - - -#ifndef HITAG_H__ -#define HITAG_H__ - -#ifdef _MSC_VER -#define PACKED -#else -#define PACKED __attribute__((packed)) -#endif - -typedef enum { - RHTSF_CHALLENGE = 01, - RHTSF_KEY = 02, - WHTSF_CHALLENGE = 03, - WHTSF_KEY = 04, - RHT2F_PASSWORD = 21, - RHT2F_AUTHENTICATE = 22, - RHT2F_CRYPTO = 23, - WHT2F_CRYPTO = 24, - RHT2F_TEST_AUTH_ATTEMPTS = 25, - RHT2F_UID_ONLY = 26, -} hitag_function; - -typedef struct { - uint8_t password[4]; -} PACKED rht2d_password; - -typedef struct { - uint8_t NrAr[8]; - uint8_t data[4]; -} PACKED rht2d_authenticate; - -typedef struct { - uint8_t key[6]; - uint8_t data[4]; -} PACKED rht2d_crypto; - -typedef union { - rht2d_password pwd; - rht2d_authenticate auth; - rht2d_crypto crypto; -} hitag_data; - - -//--------------------------------------------------------- -// Hitag S -//--------------------------------------------------------- -// protocol-state -typedef enum PROTO_STATE { - HT_READY = 0, - HT_INIT, - HT_AUTHENTICATE, - HT_SELECTED, - HT_QUIET, - HT_TTF, - HT_FAIL -} PSTATE; - -typedef enum TAG_STATE { - HT_NO_OP = 0, - HT_READING_PAGE, - HT_WRITING_PAGE_ACK, - HT_WRITING_PAGE_DATA, - HT_WRITING_BLOCK_DATA -} TSATE; - -//number of start-of-frame bits -typedef enum SOF_TYPE { - HT_STANDARD = 0, - HT_ADVANCED, - HT_FAST_ADVANCED, - HT_ONE, - HT_NO_BITS -} stype; - -struct hitagS_tag { - PSTATE pstate; //protocol-state - TSATE tstate; //tag-state - uint32_t uid; - uint8_t pages[64][4]; - uint64_t key; - uint8_t pwdl0, pwdl1, pwdh0; - //con0 - int max_page; - stype mode; - //con1 - bool auth; //0=Plain 1=Auth - bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase - int TTFDR; //data rate in TTF Mode - int TTFM; //the number of pages that are sent to the RWD - bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP - bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode - //con2 - //0=read write 1=read only - bool LCK7; //page4/5 - bool LCK6; //page6/7 - bool LCK5; //page8-11 - bool LCK4; //page12-15 - bool LCK3; //page16-23 - bool LCK2; //page24-31 - bool LCK1; //page32-47 - bool LCK0; //page48-63 -}; - -#endif diff --git a/include/mifare.h b/include/mifare.h index 83b5ccd12..d0b1168fa 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -72,8 +72,7 @@ typedef enum ISO14B_COMMAND { ISO14B_REQUEST_TRIGGER = (1 << 4), ISO14B_APPEND_CRC = (1 << 5), ISO14B_SELECT_STD = (1 << 6), - ISO14B_SELECT_SR = (1 << 7), - ISO14B_SET_TIMEOUT = (1 << 8), + ISO14B_SELECT_SR = (1 << 7) } iso14b_command_t; typedef enum ISO15_COMMAND { diff --git a/include/usb_cmd.h b/include/usb_cmd.h index bd270c9d4..7ee961466 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -129,7 +129,7 @@ typedef struct { #define CMD_IO_DEMOD_FSK 0x021A #define CMD_IO_CLONE_TAG 0x021B #define CMD_EM410X_DEMOD 0x021c -// Sampling configuration for LF reader/sniffer +// Sampling configuration for LF reader/snooper #define CMD_SET_LF_SAMPLING_CONFIG 0x021d #define CMD_FSK_SIM_TAG 0x021E #define CMD_ASK_SIM_TAG 0x021F @@ -154,10 +154,10 @@ typedef struct { #define CMD_ISO_15693_COMMAND 0x0313 #define CMD_ISO_15693_COMMAND_DONE 0x0314 #define CMD_ISO_15693_FIND_AFI 0x0315 -#define CMD_LF_SNIFF_RAW_ADC_SAMPLES 0x0317 +#define CMD_LF_SNOOP_RAW_ADC_SAMPLES 0x0317 // For Hitag2 transponders -#define CMD_SNIFF_HITAG 0x0370 +#define CMD_SNOOP_HITAG 0x0370 #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 @@ -170,9 +170,9 @@ typedef struct { #define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 -#define CMD_SNIFF_ISO_14443B 0x0382 +#define CMD_SNOOP_ISO_14443B 0x0382 -#define CMD_SNIFF_ISO_14443a 0x0383 +#define CMD_SNOOP_ISO_14443a 0x0383 #define CMD_SIMULATE_TAG_ISO_14443a 0x0384 #define CMD_READER_ISO_14443a 0x0385 @@ -192,7 +192,7 @@ typedef struct { #define CMD_ICLASS_READCHECK 0x038F #define CMD_ICLASS_CLONE 0x0390 #define CMD_ICLASS_DUMP 0x0391 -#define CMD_SNIFF_ICLASS 0x0392 +#define CMD_SNOOP_ICLASS 0x0392 #define CMD_SIMULATE_TAG_ICLASS 0x0393 #define CMD_READER_ICLASS 0x0394 #define CMD_READER_ICLASS_REPLAY 0x0395 @@ -204,7 +204,7 @@ typedef struct { // For ISO1092 / FeliCa #define CMD_FELICA_SIMULATE_TAG 0x03A0 -#define CMD_FELICA_SNIFF 0x03A1 +#define CMD_FELICA_SNOOP 0x03A1 #define CMD_FELICA_COMMAND 0x03A2 //temp #define CMD_FELICA_LITE_DUMP 0x03AA diff --git a/proxmark3.sh b/proxmark3.sh index b109d82e6..34691b95a 100755 --- a/proxmark3.sh +++ b/proxmark3.sh @@ -2,7 +2,7 @@ function wait4proxmark_Linux { echo >&2 "Waiting for Proxmark to appear..." - while [ ! -c /dev/ttyACM? -a ! -c /dev/pm3-? ]; do + while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do sleep .1 done local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` diff --git a/tools/Makefile b/tools/Makefile index 3b1dc1b0f..51a76677b 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -16,4 +16,4 @@ get_xorsearch: # Mingw # unzzip-big XORSearch_V1_11_2.zip # linux -# gunzip XORSearch_V1_11_2.zip +# gunzip XORSearch_V1_11_2.zip \ No newline at end of file diff --git a/tools/findbits_test.py b/tools/findbits_test.py index db8dda8fa..4415ce726 100644 --- a/tools/findbits_test.py +++ b/tools/findbits_test.py @@ -65,4 +65,4 @@ class OutputBuffer(object): if __name__ == '__main__': - unittest.main() + unittest.main() \ No newline at end of file diff --git a/tools/mkversion.pl b/tools/mkversion.pl index ed5cea206..023c84c8b 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -4,7 +4,7 @@ # Normally a couple of lines of bash would be enough (see openpcd project, original firmware by Harald Welte and Milosch Meriac) # but this will, at least in theory, also work on Windows with our current compile environment. # -- Henryk Plötz 2009-09-28 -# Modified april 2014 because of the move to github. +# Modified april 2014 because of the move to github. # --- Martin Holst Swende # Modified january 2016 to work with Travis-CI # --- iceman @@ -19,9 +19,9 @@ my $ctime; # GIT status 0 = dirty, 1 = clean , 2 = undecided my $clean = 2; -# Do we have acces to git command? +# Do we have acces to git command? ####### -# solves some bug on macos i.e: +# solves some bug on macos i.e: ## # perl ../tools/mkversion.pl .. > version.c || cp ../common/default_version.c version.c # /usr/bin/which: /usr/bin/which: cannot execute binary file diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 6107a564e..0717a24cb 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -174,4 +174,4 @@ bool uart_send(const serial_port sp, const uint8_t *p_tx, const size_t len) { return WriteFile(((serial_port_windows *)sp)->hPort, p_tx, len, &txlen, NULL); } -#endif +#endif \ No newline at end of file From 77ebf1ddbf37c2d875bc08bf5316f2671b1a1f72 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 23:14:19 +0100 Subject: [PATCH 05/19] Correct return --- armsrc/mifaresim.c | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index a0978a53c..ab060b919 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -36,38 +36,32 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act | ((sector_trailer[8] >> 7) & 0x01); switch (action) { case AC_KEYA_READ: { - return false; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); - break; + return false; } case AC_KEYA_WRITE: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); - break; } case AC_KEYB_READ: { - return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); - break; + return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); } case AC_KEYB_WRITE: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); - break; } case AC_AC_READ: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); return ((keytype == AUTHKEYA) || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); - break; } case AC_AC_WRITE: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x01)) || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); - break; } default: return false; @@ -93,18 +87,21 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action AC = ((sector_trailer[7] >> 2) & 0x04) | ((sector_trailer[8] << 1) & 0x02) | ((sector_trailer[8] >> 4) & 0x01); + if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x00"); break; } case 0x01: { AC = ((sector_trailer[7] >> 3) & 0x04) | ((sector_trailer[8] >> 0) & 0x02) | ((sector_trailer[8] >> 5) & 0x01); + if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x01"); break; } case 0x02: { AC = ((sector_trailer[7] >> 4) & 0x04) | ((sector_trailer[8] >> 1) & 0x02) | ((sector_trailer[8] >> 6) & 0x01); + if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x02"); break; } default: @@ -113,28 +110,24 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action switch (action) { case AC_DATA_READ: { + if (MF_DBGLEVEL >= 2) Dbprintf("AC_DATA_READ: OK"); return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07)) || (keytype == AUTHKEYB && !(AC == 0x07))); - if (MF_DBGLEVEL >= 2) Dbprintf("AC_DATA_READ: OK"); - break; } case AC_DATA_WRITE: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); return ((keytype == AUTHKEYA && (AC == 0x00)) || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); - break; } case AC_DATA_INC: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); return ((keytype == AUTHKEYA && (AC == 0x00)) || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); - break; } case AC_DATA_DEC_TRANS_REST: { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_DEC_TRANS_REST: OK"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x06 || AC == 0x01)) || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06 || AC == 0x01))); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_DEC_TRANS_REST: OK"); - break; } } From ac575cf3ce5259c3dc399a698bb29a210e7a672d Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 16 Mar 2019 00:17:13 +0100 Subject: [PATCH 06/19] Correct flags & test --- armsrc/mifaresim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index ab060b919..83f82078c 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -496,7 +496,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t crypto1_destroy(pcs); cardAUTHKEY = AUTHKEYNONE; //nonce = prng_successor(selTimer, 32) // RRG Repo, same as prand() ??? - if (flags & FLAG_RANDOM_NONCE) { + if (( flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE ) { nonce = prand(); } LED_B_OFF(); @@ -944,7 +944,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // switch to moebius collection gettingMoebius = true; mM = ATTACK_KEY_COUNT; - if (flags & FLAG_RANDOM_NONCE) { + if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) { nonce = prand(); } else { nonce = nonce * 7; @@ -1093,7 +1093,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // NR AR ATTACK - if (flags & FLAG_NR_AR_ATTACK && MF_DBGLEVEL >= 1) { + if (((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) && (MF_DBGLEVEL >= 1)) { for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { if (ar_nr_collected[i] == 2) { Dbprintf("Collected two pairs of AR/NR which can be used to extract %s from reader for sector %d:", (i < ATTACK_KEY_COUNT / 2) ? "keyA" : "keyB", ar_nr_resp[i].sector); From 0a648e38071fcbee94bb4eddd2a278eaaa0a419b Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 16 Mar 2019 01:25:10 +0100 Subject: [PATCH 07/19] Add Data Block debug --- armsrc/mifaresim.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 83f82078c..07c9df116 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -105,6 +105,7 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action break; } default: + if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: Error"); return false; } @@ -697,7 +698,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t cardSTATE = MFEMUL_WORK; LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); break; } cardSTATE_TO_IDLE(); @@ -784,7 +785,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t blockNo = receivedCmd_dec[1]; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); emlGetMem(response, blockNo, 1); - if (MF_DBGLEVEL >= 2) Dbprintf("Data Block: %02x%02x%02x%02x%02x%02x%02x%02x%02x", response); + if (MF_DBGLEVEL >= 2) { + Dbprintf("Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, + response[0], response[1], response[2], response[3], response[4], response[5], response[6], + response[7], response[8], response[9], response[10], response[11], response[12], response[13], + response[14],response[15]); + } if (IsSectorTrailer(blockNo)) { @@ -1000,7 +1006,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t ); } LED_C_ON(); - //cardSTATE = MFEMUL_WORK; + cardSTATE = MFEMUL_WORK; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); break; } From a3e0e90bf3a53d176a3772e4bd74ab502bd94498 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 16 Mar 2019 03:01:03 +0100 Subject: [PATCH 08/19] Add Variable for MAX_MIFARE_FRAME_SIZE --- armsrc/mifaresim.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 07c9df116..1c0fc3a20 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -36,7 +36,7 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act | ((sector_trailer[8] >> 7) & 0x01); switch (action) { case AC_KEYA_READ: { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); + if (MF_DBGLEVEL >= 2) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); return false; } case AC_KEYA_WRITE: { @@ -45,7 +45,7 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); } case AC_KEYB_READ: { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); + if (MF_DBGLEVEL >= 2) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); } case AC_KEYB_WRITE: { @@ -811,9 +811,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } } AppendCrc14443a(response, 16); - mf_crypto1_encrypt(pcs, response, 18, response_par); - EmSendCmdPar(response, 18, response_par); + mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); + EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); numReads++; + if (MF_DBGLEVEL >= 2) Dbprintf("Num Read: %d",numReads); if (exitAfterNReads > 0 && numReads == exitAfterNReads) { Dbprintf("%d reads done, exiting", numReads); finished = true; @@ -1014,7 +1015,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // WRITE BL2 case MFEMUL_WRITEBL2: { - if (receivedCmd_len == 18) { + if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) { mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); if (HasValidCRC(receivedCmd_dec, receivedCmd_len)) { if (IsSectorTrailer(cardWRBL)) { From 619ef2ba373ed71439b6b78b558f1fc90ca40f40 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 16 Mar 2019 03:46:36 +0100 Subject: [PATCH 09/19] Use Variable --- armsrc/mifareutil.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 929851b4b..fa4a6518e 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -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 @@ -601,9 +601,11 @@ void emlClearMem(void) { } uint8_t SectorTrailer(uint8_t blockNo) { - if (blockNo < 32 * 4) { + 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); } } From 86955c1de26e7ec887c0dfede0e95842d78e1a36 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Mon, 18 Mar 2019 13:36:36 +0100 Subject: [PATCH 10/19] Log Level --- armsrc/mifaresim.c | 69 ++++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 1c0fc3a20..adecf4cf9 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -36,32 +36,32 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act | ((sector_trailer[8] >> 7) & 0x01); switch (action) { case AC_KEYA_READ: { - if (MF_DBGLEVEL >= 2) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_READ"); return false; } case AC_KEYA_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) - || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); } case AC_KEYB_READ: { - if (MF_DBGLEVEL >= 2) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); return (keytype == AUTHKEYA && (AC == 0x00 || AC == 0x02 || AC == 0x01)); } case AC_KEYB_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) - || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); } case AC_AC_READ: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); return ((keytype == AUTHKEYA) - || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); + || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); } case AC_AC_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x01)) - || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); + || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); } default: return false; @@ -73,9 +73,9 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action uint8_t sector_trailer[16]; emlGetMem(sector_trailer, SectorTrailer(blockNo), 1); - + uint8_t sector_block; - if (blockNo < MIFARE_2K_MAXBLOCK) { + if (blockNo <= MIFARE_2K_MAXBLOCK) { sector_block = blockNo & 0x03; } else { sector_block = (blockNo & 0x0f) / 5; @@ -85,43 +85,43 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action switch (sector_block) { case 0x00: { AC = ((sector_trailer[7] >> 2) & 0x04) - | ((sector_trailer[8] << 1) & 0x02) - | ((sector_trailer[8] >> 4) & 0x01); - if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x00"); + | ((sector_trailer[8] << 1) & 0x02) + | ((sector_trailer[8] >> 4) & 0x01); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC); break; } case 0x01: { AC = ((sector_trailer[7] >> 3) & 0x04) - | ((sector_trailer[8] >> 0) & 0x02) - | ((sector_trailer[8] >> 5) & 0x01); - if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x01"); + | ((sector_trailer[8] >> 0) & 0x02) + | ((sector_trailer[8] >> 5) & 0x01); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC); break; } case 0x02: { AC = ((sector_trailer[7] >> 4) & 0x04) - | ((sector_trailer[8] >> 1) & 0x02) - | ((sector_trailer[8] >> 6) & 0x01); - if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: case 0x02"); + | ((sector_trailer[8] >> 1) & 0x02) + | ((sector_trailer[8] >> 6) & 0x01); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC); break; } default: - if (MF_DBGLEVEL >= 2) Dbprintf("IsDataAccessAllowed: Error"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: Error"); return false; } switch (action) { case AC_DATA_READ: { - if (MF_DBGLEVEL >= 2) Dbprintf("AC_DATA_READ: OK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_READ: OK"); return ((keytype == AUTHKEYA && !(AC == 0x03 || AC == 0x05 || AC == 0x07)) || (keytype == AUTHKEYB && !(AC == 0x07))); } case AC_DATA_WRITE: { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_WRITE: OK"); return ((keytype == AUTHKEYA && (AC == 0x00)) || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x04 || AC == 0x06 || AC == 0x03))); } case AC_DATA_INC: { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("AC_DATA_WRITE: OK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed - AC_DATA_INC: OK"); return ((keytype == AUTHKEYA && (AC == 0x00)) || (keytype == AUTHKEYB && (AC == 0x00 || AC == 0x06))); } @@ -785,36 +785,45 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t blockNo = receivedCmd_dec[1]; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); emlGetMem(response, blockNo, 1); - if (MF_DBGLEVEL >= 2) { - Dbprintf("Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("[ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7], response[8], response[9], response[10], response[11], response[12], response[13], response[14],response[15]); } - if (IsSectorTrailer(blockNo)) { - memset(response, 0x00, 6); // keyA can never be read - if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); + + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) { + memset(response, 0x00, 6); // keyA can never be read, Why ??? Need source ? + // a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); + } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { memset(response + 10, 0x00, 6); // keyB cannot be read - if (MF_DBGLEVEL >= 2) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { memset(response + 6, 0x00, 4); // AC bits cannot be read - if (MF_DBGLEVEL >= 2) Dbprintf("[IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); } } else { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) { memset(response, 0x00, 16); // datablock cannot be read - if (MF_DBGLEVEL >= 2) Dbprintf("[IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); } } AppendCrc14443a(response, 16); mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); + if (MF_DBGLEVEL >= 2) { + Dbprintf("[EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, + response[0], response[1], response[2], response[3], response[4], response[5], response[6], + response[7], response[8], response[9], response[10], response[11], response[12], response[13], + response[14],response[15]); + } numReads++; - if (MF_DBGLEVEL >= 2) Dbprintf("Num Read: %d",numReads); + if (exitAfterNReads > 0 && numReads == exitAfterNReads) { Dbprintf("%d reads done, exiting", numReads); finished = true; From c8a805c99c65dde69e9da0da23988f048e5a5a10 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Tue, 19 Mar 2019 17:09:16 +0100 Subject: [PATCH 11/19] LogTrace --- armsrc/mifaresim.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index adecf4cf9..2989ca63d 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -268,7 +268,6 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // UID 10B case 10: - switch (MifareCardType) { case 1: memcpy(rATQA, rATQA_1k_10B, sizeof rATQA_1k_10B); @@ -512,7 +511,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t case MFEMUL_HALTED: if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("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); Need to be convert ? + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_IDLE"); break; } @@ -712,6 +711,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have exactly 4 bytes: receivedCmd_len=%d", receivedCmd_len); break; } + bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; if (encrypted_data) { // decrypt seqence @@ -740,14 +740,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // first authentication if (!encrypted_data) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); crypto1_word(pcs, cuid ^ nonce, 0); //Update crypto state num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce + if (MF_DBGLEVEL >= 2) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d - %s", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, emlGetKey(cardAUTHSC, cardAUTHKEY)); } else { // nested authentication - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + if (MF_DBGLEVEL >= 2) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); num_to_bytes(ans, 4, rAUTH_AT); } + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); cardSTATE = MFEMUL_AUTH1; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { @@ -816,7 +817,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t AppendCrc14443a(response, 16); mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); - if (MF_DBGLEVEL >= 2) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("[EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, response[0], response[1], response[2], response[3], response[4], response[5], response[6], response[7], response[8], response[9], response[10], response[11], response[12], response[13], @@ -829,7 +830,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t finished = true; } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[ISO14443A_CMD_READBLOCK] Finish"); break; } @@ -911,7 +911,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t case MFEMUL_AUTH1: { if (receivedCmd_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); + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 => cardSTATE_TO_IDLE())"); break; } @@ -1050,7 +1050,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } } 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); + LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); } break; } From a068f7c2bce4b9dac44893d854b51315d2d435ec Mon Sep 17 00:00:00 2001 From: vratiskol Date: Wed, 27 Mar 2019 14:18:26 +0100 Subject: [PATCH 12/19] Mifare Sim Compilation OK Emulation 1k OK with android --- armsrc/mifaresim.c | 321 ++++++++++++++++++++++++++---------------- armsrc/mifaresim.h | 15 -- armsrc/mifareutil.c | 4 +- armsrc/mifareutil.h | 5 - client/cmdhfmfu.c | 10 +- client/reveng/model.c | 4 +- 6 files changed, 208 insertions(+), 151 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 2989ca63d..8c6ce792c 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -42,7 +42,7 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act case AC_KEYA_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYA_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x01)) - || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); } case AC_KEYB_READ: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_READ"); @@ -51,17 +51,17 @@ static bool IsTrailerAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t act case AC_KEYB_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_KEYB_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x00 || AC == 0x04)) - || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); + || (keytype == AUTHKEYB && (AC == 0x04 || AC == 0x03))); } case AC_AC_READ: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_READ"); return ((keytype == AUTHKEYA) - || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); + || (keytype == AUTHKEYB && !(AC == 0x00 || AC == 0x02 || AC == 0x01))); } case AC_AC_WRITE: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsTrailerAccessAllowed: AC_AC_WRITE"); return ((keytype == AUTHKEYA && (AC == 0x01)) - || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); + || (keytype == AUTHKEYB && (AC == 0x03 || AC == 0x05))); } default: return false; @@ -73,7 +73,7 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action uint8_t sector_trailer[16]; emlGetMem(sector_trailer, SectorTrailer(blockNo), 1); - + uint8_t sector_block; if (blockNo <= MIFARE_2K_MAXBLOCK) { sector_block = blockNo & 0x03; @@ -85,22 +85,22 @@ static bool IsDataAccessAllowed(uint8_t blockNo, uint8_t keytype, uint8_t action switch (sector_block) { case 0x00: { AC = ((sector_trailer[7] >> 2) & 0x04) - | ((sector_trailer[8] << 1) & 0x02) - | ((sector_trailer[8] >> 4) & 0x01); + | ((sector_trailer[8] << 1) & 0x02) + | ((sector_trailer[8] >> 4) & 0x01); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x00 - %02x", AC); break; } case 0x01: { AC = ((sector_trailer[7] >> 3) & 0x04) - | ((sector_trailer[8] >> 0) & 0x02) - | ((sector_trailer[8] >> 5) & 0x01); + | ((sector_trailer[8] >> 0) & 0x02) + | ((sector_trailer[8] >> 5) & 0x01); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x01 - %02x", AC); break; } case 0x02: { AC = ((sector_trailer[7] >> 4) & 0x04) - | ((sector_trailer[8] >> 1) & 0x02) - | ((sector_trailer[8] >> 6) & 0x01); + | ((sector_trailer[8] >> 1) & 0x02) + | ((sector_trailer[8] >> 6) & 0x01); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("IsDataAccessAllowed: case 0x02 - %02x", AC); break; } @@ -376,6 +376,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t uint8_t blockNo; + uint32_t nr; + uint32_t ar; + + bool encrypted_data; + uint8_t cardWRBL = 0; uint8_t cardAUTHSC = 0; uint8_t cardAUTHKEY = AUTHKEYNONE; // no authentication @@ -495,10 +500,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // init crypto block crypto1_destroy(pcs); cardAUTHKEY = AUTHKEYNONE; - //nonce = prng_successor(selTimer, 32) // RRG Repo, same as prand() ??? - if (( flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE ) { - nonce = prand(); - } + //nonce = bytes_to_num(rAUTH_NT, 4); + nonce = prng_successor(selTimer, 32); + if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) nonce = prand(); + LED_B_OFF(); LED_C_OFF(); cardSTATE = MFEMUL_SELECT1; @@ -516,7 +521,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t break; } - // The anti-collision sequence, which is a mandatory part of the card activation sequence. // It auto with 4-byte UID (= Single Size UID), // 7 -byte UID (= Double Size UID) or 10-byte UID (= Triple Size UID). @@ -549,6 +553,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], responses[UIDBCC1].response, 4) == 0)) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT CL1 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); + + // Send SAK according UID len switch (uid_len) { case 4: switch (MifareCardType) { @@ -568,27 +574,30 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t LED_B_ON(); cardSTATE = MFEMUL_WORK; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); - continue; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_WORK"); + break; case 7: // SAK => Need another select round EmSendPrecompiledCmd(&responses[SAK1]); cardSTATE = MFEMUL_SELECT2; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); - continue; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); + break; case 10: // SAK => Need another select round EmSendPrecompiledCmd(&responses[SAK1]); cardSTATE = MFEMUL_SELECT2; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_SELECT2"); - continue; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_SELECT2"); + break; default: break; - } - } + } // End Switch (uid_len) - // IDLE - cardSTATE_TO_IDLE(); + } else { + // IDLE + cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT1] cardSTATE = MFEMUL_IDLE"); + } + // Break Case MFEMUL_SELECT1 break; } @@ -612,9 +621,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t case MFEMUL_SELECT2: { if (receivedCmd_len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SELECT ALL CL2 received"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] SELECT ALL CL2 received"); EmSendPrecompiledCmd(&responses[UIDBCC2]); - continue; + break; } // select cl2 card - 0x95 0x70 xxxxxxxxxxxx @@ -625,7 +634,7 @@ 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("SELECT CL2 %02x%02x%02x%02x received", receivedCmd[2], receivedCmd[3], receivedCmd[4], receivedCmd[5]); + 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: @@ -648,13 +657,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // SAK => Need another select round EmSendPrecompiledCmd(&responses[SAK1]); cardSTATE = MFEMUL_SELECT3; - continue; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3"); + break; default: break; } } cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_IDLE"); break; } @@ -697,71 +708,122 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t cardSTATE = MFEMUL_WORK; LED_B_ON(); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); - break; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("[MFEMUL_SELECT3] --> WORK. anticol3 time: %d", GetTickCount() - selTimer); + Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_WORK"); + } + continue; } cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_IDLE"); break; } - + // WORK case MFEMUL_WORK: { - if (receivedCmd_len == 0) { + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Enter in case"); + + if (receivedCmd_len != 4) { LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have exactly 4 bytes: receivedCmd_len=%d", receivedCmd_len); + mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] All commands must have exactly 4 bytes: receivedCmd_len=%d - Cmd: %02X", receivedCmd_len, receivedCmd_dec); break; } - - bool encrypted_data = (cardAUTHKEY != AUTHKEYNONE) ; + + if (receivedCmd_len == 0) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] NO CMD received"); + break; + } + + encrypted_data = (cardAUTHKEY != AUTHKEYNONE); if (encrypted_data) { // decrypt seqence mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, receivedCmd_dec); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("decrypt seqence"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Decrypt seqence"); } else { + // Data in clear memcpy(receivedCmd_dec, receivedCmd, receivedCmd_len); } + if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("All commands must have a valid CRC %d", receivedCmd_dec); + if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); break; } if (receivedCmd_len == 4 && (receivedCmd_dec[0] == MIFARE_AUTH_KEYA || receivedCmd_dec[0] == MIFARE_AUTH_KEYB)) { + + // Reader asks for AUTH: 6X XX + // RCV: 60 XX => Using KEY A + // RCV: 61 XX => Using KEY B + // XX: Block number + // if authenticating to a block that shouldn't exist - as long as we are not doing the reader attack if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK && !((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); break; } - cardAUTHSC = receivedCmd_dec[1] / 4; // received block num, Need to check if ok for 4k card ??? + + authTimer = GetTickCount(); + + // received block num -> sector + // Example: 6X [00] + cardAUTHSC = receivedCmd_dec[1] / 4; + + // cardAUTHKEY: 60 => Auth use Key A + // cardAUTHKEY: 61 => Auth use Key B cardAUTHKEY = receivedCmd_dec[0] & 0x01; - crypto1_destroy(pcs); - crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY: %02X%02X", emlGetKey(cardAUTHSC, cardAUTHKEY)); // first authentication + crypto1_destroy(pcs); + + // Load key into crypto + crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); + if (!encrypted_data) { - crypto1_word(pcs, cuid ^ nonce, 0); //Update crypto state - num_to_bytes(nonce, 4, rAUTH_AT); // Send nonce - if (MF_DBGLEVEL >= 2) Dbprintf("Reader authenticating for block %d (0x%02x) with key %d - %s", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, emlGetKey(cardAUTHSC, cardAUTHKEY)); - } else { // nested authentication - if (MF_DBGLEVEL >= 2) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + // Receive Cmd in clear txt + // Update crypto state (UID ^ NONCE) + crypto1_word(pcs, cuid ^ nonce, 0); + // prepare nonce + num_to_bytes(nonce, 4, rAUTH_AT); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %d - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, rAUTH_AT, cuid); + } else { + // nested authentication ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); num_to_bytes(ans, 4, rAUTH_AT); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); } - + + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); cardSTATE = MFEMUL_AUTH1; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("cardSTATE = MFEMUL_AUTH1"); - } - break; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_AUTH1 - rAUTH_AT: %02X", rAUTH_AT); + continue; } - if (!encrypted_data) { // all other commands must be encrypted (authenticated) - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Commands must be encrypted (authenticated)"); + + // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued + // BUT... ACK --> NACK + if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_ACK) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } - // if Cmd is Read, Write, Inc, Dec, Restore, Transfert + // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) + if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_NACK_NA) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + break; + } + + // if (!encrypted_data) { // all other commands must be encrypted (authenticated) + // if (MF_DBGLEVEL >= 0) Dbprintf("Commands must be encrypted (authenticated)"); + // break; + // } + + // case MFEMUL_WORK => if Cmd is Read, Write, Inc, Dec, Restore, Transfert if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK || receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK || receivedCmd_dec[0] == MIFARE_CMD_INC @@ -771,84 +833,85 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Check if Block num is not too far if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); break; } if (receivedCmd_dec[1] / 4 != cardAUTHSC) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); break; } } - // CMD READ block + // case MFEMUL_WORK => CMD READ block if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK) { blockNo = receivedCmd_dec[1]; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader reading block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader reading block %d (0x%02x)", blockNo, blockNo); emlGetMem(response, blockNo, 1); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("[ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, - response[0], response[1], response[2], response[3], response[4], response[5], response[6], - response[7], response[8], response[9], response[10], response[11], response[12], response[13], - response[14],response[15]); + Dbprintf("[MFEMUL_WORK - ISO14443A_CMD_READBLOCK] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, + response[0], response[1], response[2], response[3], response[4], response[5], response[6], + response[7], response[8], response[9], response[10], response[11], response[12], response[13], + response[14], response[15]); } if (IsSectorTrailer(blockNo)) { - + if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) { memset(response, 0x00, 6); // keyA can never be read, Why ??? Need source ? - // a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); + // a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { memset(response + 10, 0x00, 6); // keyB cannot be read - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyB cannot be read - block %d (0x%02x)", blockNo, blockNo); } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_AC_READ)) { memset(response + 6, 0x00, 4); // AC bits cannot be read - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] AC bits cannot be read - block %d (0x%02x)", blockNo, blockNo); } } else { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_DATA_READ)) { memset(response, 0x00, 16); // datablock cannot be read - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsAccessAllowed] Data block %d (0x%02x) cannot be read", blockNo, blockNo); } } AppendCrc14443a(response, 16); mf_crypto1_encrypt(pcs, response, MAX_MIFARE_FRAME_SIZE, response_par); EmSendCmdPar(response, MAX_MIFARE_FRAME_SIZE, response_par); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("[EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, - response[0], response[1], response[2], response[3], response[4], response[5], response[6], - response[7], response[8], response[9], response[10], response[11], response[12], response[13], - response[14],response[15]); - } + Dbprintf("[MFEMUL_WORK - EmSendCmdPar] Data Block[%d]: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", blockNo, + response[0], response[1], response[2], response[3], response[4], response[5], response[6], + response[7], response[8], response[9], response[10], response[11], response[12], response[13], + response[14], response[15]); + } numReads++; if (exitAfterNReads > 0 && numReads == exitAfterNReads) { - Dbprintf("%d reads done, exiting", numReads); + Dbprintf("[MFEMUL_WORK] %d reads done, exiting", numReads); finished = true; } - break; - } - // CMD WRITEBLOCK + } // End receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK + + // case MFEMUL_WORK => CMD WRITEBLOCK if (receivedCmd_dec[0] == ISO14443A_CMD_WRITEBLOCK) { blockNo = receivedCmd_dec[1]; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0xA0 write block %d (%02x)", blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0xA0 write block %d (%02x)", blockNo, blockNo); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); cardWRBL = blockNo; cardSTATE = MFEMUL_WRITEBL2; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_WRITEBL2"); break; } - // CMD INC/DEC/RES + // case MFEMUL_WORK => CMD INC/DEC/REST if (receivedCmd_dec[0] == MIFARE_CMD_INC || receivedCmd_dec[0] == MIFARE_CMD_DEC || receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { blockNo = receivedCmd_dec[1]; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); if (emlCheckValBl(blockNo)) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate on block, but emlCheckValBl failed, nacking"); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } @@ -858,27 +921,29 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // INC if (receivedCmd_dec[0] == MIFARE_CMD_INC) { cardSTATE = MFEMUL_INTREG_INC; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_INC"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_INC"); } // DEC if (receivedCmd_dec[0] == MIFARE_CMD_DEC) { cardSTATE = MFEMUL_INTREG_DEC; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_DEC"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_DEC"); } // REST if (receivedCmd_dec[0] == MIFARE_CMD_RESTORE) { cardSTATE = MFEMUL_INTREG_REST; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_INTREG_REST"); - break; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_INTREG_REST"); } - } + break; - // TRANSFER + } // End case MFEMUL_WORK => CMD INC/DEC/REST + + + // case MFEMUL_WORK => CMD TRANSFER if (receivedCmd_dec[0] == MIFARE_CMD_TRANSFER) { blockNo = receivedCmd_dec[1]; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0x%02x transfer block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd_dec[1])) EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); else @@ -886,42 +951,46 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t break; } - // HALT + // case MFEMUL_WORK => CMD HALT if (receivedCmd_dec[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) { LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); LED_B_OFF(); LED_C_OFF(); cardSTATE = MFEMUL_HALTED; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_HALTED;"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] cardSTATE = MFEMUL_HALTED"); break; } - // RATS + // case MFEMUL_WORK => CMD RATS if (receivedCmd[0] == ISO14443A_CMD_RATS) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); break; } - // command not allowed - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; + // case MFEMUL_WORK => command not allowed + // if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); + // EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + // break; } + // AUTH1 case MFEMUL_AUTH1: { - if (receivedCmd_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); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 => cardSTATE_TO_IDLE())"); - break; - } + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] Enter case"); - uint32_t nr = bytes_to_num(receivedCmd, 4); - uint32_t ar = bytes_to_num(&receivedCmd[4], 4); + // if (receivedCmd_len != 4) { + // 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); + // if (MF_DBGLEVEL >= 0) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len); + // break; + // } + + nr = bytes_to_num(receivedCmd, 4); + ar = bytes_to_num(&receivedCmd[4], 4); // Collect AR/NR per keytype & sector if ((flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK) { - + if (MF_DBGLEVEL >= 0) Dbprintf("FLAG_NR_AR_ATTACK"); for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { if (ar_nr_collected[i + mM] == 0 || ((cardAUTHSC == ar_nr_resp[i + mM].sector) && (cardAUTHKEY == ar_nr_resp[i + mM].keytype) && (ar_nr_collected[i + mM] > 0))) { // if first auth for sector, or matches sector and keytype of previous auth @@ -986,10 +1055,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t crypto1_word(pcs, nr, 1); cardRr = ar ^ crypto1_word(pcs, 0, 0); - // test if auth OK + // test if auth KO if (cardRr != prng_successor(nonce, 64)) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" + Dbprintf("[MFEMUL_AUTH1] AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" , cardAUTHSC , (cardAUTHKEY == 0) ? 'A' : 'B' , nr @@ -998,18 +1067,23 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t , prng_successor(nonce, 64) ); } - cardAUTHKEY = AUTHKEYNONE; // not authenticated LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardSTATE_TO_IDLE(); break; } - ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); + //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, rAUTH_AT); - EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + mf_crypto1_encrypt(pcs, rAUTH_AT, 4, response_par); + EmSendCmdPar(rAUTH_AT, 4, response_par); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", + Dbprintf("[MFEMUL_AUTH1] AUTH COMPLETED for sector %d with key %c. time=%d", cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', GetTickCount() - authTimer @@ -1017,11 +1091,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } LED_C_ON(); cardSTATE = MFEMUL_WORK; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("cardSTATE = MFEMUL_WORK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] cardSTATE = MFEMUL_WORK"); break; } - // WRITE BL2 case MFEMUL_WRITEBL2: { if (receivedCmd_len == MAX_MIFARE_FRAME_SIZE) { @@ -1046,12 +1119,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t emlSetMem(receivedCmd_dec, cardWRBL, 1); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); // always ACK? cardSTATE = MFEMUL_WORK; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = MFEMUL_WORK"); break; } - } 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); } + cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WRITEBL2] cardSTATE = 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; } @@ -1068,13 +1142,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t cardINTREG = cardINTREG + ans; cardSTATE = MFEMUL_WORK; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_INC] cardSTATE = MFEMUL_WORK"); break; } } // DEC case MFEMUL_INTREG_DEC: { - if (receivedCmd_len == 6) { + if (receivedCmd_len == 6) { // Data is encrypted + // Decrypted cmd mf_crypto1_decryptEx(pcs, receivedCmd, receivedCmd_len, (uint8_t *)&ans); if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); @@ -1085,6 +1161,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t 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; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_DEC] cardSTATE = MFEMUL_WORK"); break; } @@ -1098,6 +1175,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } 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; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_INTREG_REST] cardSTATE = MFEMUL_WORK"); break; } @@ -1144,12 +1222,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen()); } -// Need to be debug - Card not recognize by my phone if uncommented -//if ((flags &FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK - //Send the collected ar_nr in the response -// cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); -//} + if ((flags & FLAG_INTERACTIVE) == FLAG_INTERACTIVE) { // Interactive mode flag, means we need to send ACK + //Send the collected ar_nr in the response + cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, button_pushed, 0, &ar_nr_resp, sizeof(ar_nr_resp)); + } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index f62071966..c7dab05c5 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -17,21 +17,6 @@ extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); -//mifare emulator states -#define MFEMUL_NOFIELD 0 -#define MFEMUL_IDLE 1 -#define MFEMUL_SELECT1 2 -#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 -#define MFEMUL_INTREG_DEC 10 -#define MFEMUL_INTREG_REST 11 -#define MFEMUL_HALTED 12 - #define AC_DATA_READ 0 #define AC_DATA_WRITE 1 #define AC_DATA_INC 2 diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 5e9214196..ddcdbc326 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -592,7 +592,7 @@ void emlClearMem(void) { memset(emCARD, 0, CARD_MEMORY_SIZE); // fill sectors trailer data - for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK ) ? (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 @@ -602,7 +602,7 @@ void emlClearMem(void) { 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)); + 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)); diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 521d80202..4570bb78d 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -33,11 +33,6 @@ #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 diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 85e73d034..4097a0a3a 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -84,11 +84,11 @@ void transform_D(uint8_t *ru) { uint32_t v1 = ((ru[3] << 24) | (ru[2] << 16) | (ru[1] << 8) | ru[0]) + c_D[p++]; uint32_t v2 = ((ru[7] << 24) | (ru[6] << 16) | (ru[5] << 8) | ru[4]) + c_D[p++]; for (i = 0; i < 12; i += 2) { - + uint32_t xor1 = v1 ^ v2; uint32_t t1 = ROTL(xor1, v2 & 0x1F) + c_D[p++]; - uint32_t xor2 = v2 ^ t1; - uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++]; + uint32_t xor2 = v2 ^ t1; + uint32_t t2 = ROTL(xor2, t1 & 0x1F) + c_D[p++]; uint32_t xor3 = t1 ^ t2; uint32_t xor4 = t2 ^ v1; v1 = ROTL(xor3, t2 & 0x1F) + c_D[p++]; @@ -322,9 +322,9 @@ static int ul_read(uint8_t page, uint8_t *response, uint16_t responseLength) { static int ul_comp_write(uint8_t page, uint8_t *data, uint8_t datalen) { - if (data == NULL) + if (data == NULL) return -1; - + uint8_t cmd[18]; memset(cmd, 0x00, sizeof(cmd)); datalen = (datalen > 16) ? 16 : datalen; diff --git a/client/reveng/model.c b/client/reveng/model.c index 16a791312..297f638db 100644 --- a/client/reveng/model.c +++ b/client/reveng/model.c @@ -242,9 +242,9 @@ void mrev(model_t *model) { void mnovel(model_t *model) { /* remove name and check string from modified model */ - /* previous classification no longer applies */ + /* previous classification no longer applies */ model->name = NULL; - model->flags &= ~P_CLMASK; + model->flags &= ~P_CLMASK; pfree(&model->check); pfree(&model->magic); } From 8f11fcc193738fdd209c37b8ffb61b6f6cf15037 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Wed, 27 Mar 2019 22:35:11 +0100 Subject: [PATCH 13/19] Remove FLAG_RANDOM_NONCE --- armsrc/mifaresim.c | 26 ++++---------------------- armsrc/mifareutil.h | 1 - include/usb_cmd.h | 1 - 3 files changed, 4 insertions(+), 24 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 8c6ce792c..84f350e66 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -359,7 +359,6 @@ static bool HasValidCRC(uint8_t *receivedCmd, uint16_t receivedCmd_len) { * FLAG_7B_UID_IN_DATA - means that there is a 7-byte UID in the data-section, we're expected to use that * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section not finished * FLAG_NR_AR_ATTACK - means we should collect NR_AR responses for bruteforcing later -* FLAG_RANDOM_NONCE - means we should generate some pseudo-random nonce data (only allows moebius attack) *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is infinite ... * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) */ @@ -402,7 +401,6 @@ 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 rAUTH_NT[] = {0x01, 0x02, 0x03, 0x04}; uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; //Here, we collect UID,sector,keytype,NT,AR,NR,NT2,AR2,NR2 @@ -422,14 +420,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t uint8_t mM = 0; //moebius_modifier for collection storage // Authenticate response - nonce - uint32_t nonce; - if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) { - nonce = prand(); - } else { - nonce = bytes_to_num(rAUTH_NT, 4); - } - - + uint32_t nonce = prng_successor(selTimer, 32) ; + if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { MifareCardType = 0; Dbprintf("Mifare Mini"); @@ -500,10 +492,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // init crypto block crypto1_destroy(pcs); cardAUTHKEY = AUTHKEYNONE; - //nonce = bytes_to_num(rAUTH_NT, 4); nonce = prng_successor(selTimer, 32); - if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) nonce = prand(); - + LED_B_OFF(); LED_C_OFF(); cardSTATE = MFEMUL_SELECT1; @@ -1029,11 +1019,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // switch to moebius collection gettingMoebius = true; mM = ATTACK_KEY_COUNT; - if ((flags & FLAG_RANDOM_NONCE) == FLAG_RANDOM_NONCE) { - nonce = prand(); - } else { - nonce = nonce * 7; - } + nonce = nonce * 7; break; } } else { @@ -1073,10 +1059,6 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t 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, rAUTH_AT); mf_crypto1_encrypt(pcs, rAUTH_AT, 4, response_par); diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 4570bb78d..a6d4c28fe 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -61,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 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index bd270c9d4..f164b0f8d 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -290,7 +290,6 @@ 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 From edfce24cad0f029290e9ee2d41e0802c6e1a615f Mon Sep 17 00:00:00 2001 From: vratiskol Date: Thu, 28 Mar 2019 00:37:48 +0100 Subject: [PATCH 14/19] cardAUTHKEY log Add key type as A or B --- armsrc/mifaresim.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 84f350e66..31cafb2d4 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -766,7 +766,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // cardAUTHKEY: 61 => Auth use Key B cardAUTHKEY = receivedCmd_dec[0] & 0x01; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY: %02X%02X", emlGetKey(cardAUTHSC, cardAUTHKEY)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY %c: %02X%02X", (cardAUTHKEY == 0) ? 'A' : 'B', emlGetKey(cardAUTHSC, cardAUTHKEY)); // first authentication crypto1_destroy(pcs); @@ -780,12 +780,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t crypto1_word(pcs, cuid ^ nonce, 0); // prepare nonce num_to_bytes(nonce, 4, rAUTH_AT); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %d - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY, rAUTH_AT, cuid); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader authenticating for block %d (0x%02x) with key %c - nonce: %02X - ciud: %02X", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B', rAUTH_AT, cuid); } else { // nested authentication ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); num_to_bytes(ans, 4, rAUTH_AT); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %d", receivedCmd_dec[1], receivedCmd_dec[1], cardAUTHKEY); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd_dec[1], receivedCmd_dec[1], (cardAUTHKEY == 0) ? 'A' : 'B'); } From 4bef91465340d3b1c226d4321f51ba05516097ba Mon Sep 17 00:00:00 2001 From: vratiskol Date: Thu, 28 Mar 2019 15:18:53 +0100 Subject: [PATCH 15/19] Mifare 10B UID --- armsrc/mifaresim.c | 54 +++++++++++++++++++++++++++++++--------------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 31cafb2d4..3ab0c2d8a 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -201,6 +201,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * 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); } switch (*uid_len) { @@ -230,7 +231,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * *cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= 1) { + if (MF_DBGLEVEL >= MF_DBG_ALL) { Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); } break; @@ -260,7 +261,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (MF_DBGLEVEL >= 1) { + if (MF_DBGLEVEL >= MF_DBG_ALL) { Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3], rUIDBCC2[0], rUIDBCC2[1], rUIDBCC2[2], rUIDBCC2[3]); } @@ -293,7 +294,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - if (MF_DBGLEVEL >= 1) { + if (MF_DBGLEVEL >= MF_DBG_ALL) { 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], @@ -421,7 +422,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Authenticate response - nonce uint32_t nonce = prng_successor(selTimer, 32) ; - + if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { MifareCardType = 0; Dbprintf("Mifare Mini"); @@ -493,7 +494,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t crypto1_destroy(pcs); cardAUTHKEY = AUTHKEYNONE; nonce = prng_successor(selTimer, 32); - + LED_B_OFF(); LED_C_OFF(); cardSTATE = MFEMUL_SELECT1; @@ -642,21 +643,23 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } cardSTATE = MFEMUL_WORK; LED_B_ON(); - continue; + break; case 10: // SAK => Need another select round EmSendPrecompiledCmd(&responses[SAK1]); cardSTATE = MFEMUL_SELECT3; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_SELECT3"); - break; default: break; } - } - cardSTATE_TO_IDLE(); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_IDLE"); - break; + } else { + // IDLE + cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_IDLE"); + } + // Break Case MFEMUL_SELECT2 + continue; } @@ -703,9 +706,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_WORK"); } continue; + } else { + // IDLE + cardSTATE_TO_IDLE(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_IDLE"); } - cardSTATE_TO_IDLE(); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT3] cardSTATE = MFEMUL_IDLE"); + // Break Case MFEMUL_SELECT3 break; } @@ -738,7 +744,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); break; } @@ -845,11 +851,25 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t response[14], response[15]); } + // Access permission managment: + // + // Sector Trailer: + // - KEY A access + // - KEY B access + // - AC bits access + // + // Data block: + // - Data access + + // If permission is not allowed, data is cleared (00) in emulator memeory. + // ex: a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 + + + // Check if selected Block is a Sector Trailer if (IsSectorTrailer(blockNo)) { if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYA_READ)) { - memset(response, 0x00, 6); // keyA can never be read, Why ??? Need source ? - // a0a1a2a3a4a561e789c1b0b1b2b3b4b5 => 00000000000061e789c1b0b1b2b3b4b5 + memset(response, 0x00, 6); // keyA can never be read if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK - IsSectorTrailer] keyA can never be read - block %d (0x%02x)", blockNo, blockNo); } if (!IsAccessAllowed(blockNo, cardAUTHKEY, AC_KEYB_READ)) { @@ -954,7 +974,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // case MFEMUL_WORK => CMD RATS if (receivedCmd[0] == ISO14443A_CMD_RATS) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RCV RATS => NACK"); break; } From bc11ff88ea67d779b428a01386b4adca65b9132c Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 5 Apr 2019 03:58:15 +0200 Subject: [PATCH 16/19] Add Encrypted data test --- armsrc/mifaresim.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 3ab0c2d8a..8c8d18c4d 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -743,7 +743,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); break; } @@ -804,13 +804,13 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued // BUT... ACK --> NACK if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_ACK) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); break; } // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) if (receivedCmd_len == 1 && receivedCmd_dec[0] == CARD_NACK_NA) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_ACK) : CARD_ACK); break; } @@ -973,15 +973,15 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // case MFEMUL_WORK => CMD RATS if (receivedCmd[0] == ISO14443A_CMD_RATS) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + 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 => command not allowed - // if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); - // EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - // break; + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Received command not allowed, nacking"); + EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); + break; } // AUTH1 @@ -1074,8 +1074,9 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t ); } cardAUTHKEY = AUTHKEYNONE; // not authenticated - LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + // LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardSTATE_TO_IDLE(); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } From 7f198192ec6596def6d300ea0fa5b744145a9cde Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 5 Apr 2019 04:09:20 +0200 Subject: [PATCH 17/19] ReSync file --- client/cmdlffdx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index bc1f1e9dc..972ef9627 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -160,7 +160,7 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t int CmdFDXBdemodBI(const char *Cmd) { int clk = 32; - int invert = 1, errCnt = 0, offset = 0, maxErr = 0; + int invert = 1, errCnt = 0, offset = 0, maxErr = 100; uint8_t bs[MAX_DEMOD_BUF_LEN]; size_t size = getFromGraphBuf(bs); @@ -236,7 +236,7 @@ int CmdFdxDemod(const char *Cmd) { //Differential Biphase / di-phase (inverted biphase) //get binary from ask wave - if (!ASKbiphaseDemod("0 32 1 0", false)) { + if (!ASKbiphaseDemod("0 32 1 100", false)) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDX-B ASKbiphaseDemod failed"); return 0; } From e24a0cfe17274ae33e0dd6364eb15fa95dfc6739 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 6 Apr 2019 00:32:11 +0200 Subject: [PATCH 18/19] Verbose mode --- armsrc/mifaresim.c | 63 ++++++++++++++++++++++++++++------------------ 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index 8c8d18c4d..a300e7b57 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -10,6 +10,12 @@ // Mifare Classic Card Simulation //----------------------------------------------------------------------------- +// Verbose Mode: +// MF_DBG_NONE 0 +// MF_DBG_ERROR 1 +// MF_DBG_ALL 2 +// MF_DBG_EXTENDED 4 + #include "iso14443a.h" #include "mifaresim.h" #include "iso14443crc.h" @@ -149,8 +155,8 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // ATQA 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_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 @@ -231,7 +237,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * *cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= MF_DBG_ALL) { + if (MF_DBGLEVEL >= MF_DBG_NONE) { Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], rUIDBCC1[3]); } break; @@ -240,6 +246,10 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * 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: memcpy(rATQA, rATQA_1k_7B, sizeof rATQA_1k_7B); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_7B"); @@ -261,7 +271,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // 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_ALL) { + 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]); } @@ -270,6 +280,10 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * // 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: memcpy(rATQA, rATQA_1k_10B, sizeof rATQA_1k_10B); if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("=> Using rATQA_1k_10B"); @@ -294,7 +308,7 @@ static void MifareSimInit(uint16_t flags, uint8_t *datain, tag_response_info_t * 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_ALL) { + 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], @@ -421,7 +435,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t uint8_t mM = 0; //moebius_modifier for collection storage // Authenticate response - nonce - uint32_t nonce = prng_successor(selTimer, 32) ; + uint32_t nonce = 0; + // = prng_successor(selTimer, 32) ; if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { MifareCardType = 0; @@ -659,7 +674,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_SELECT2] cardSTATE = MFEMUL_IDLE"); } // Break Case MFEMUL_SELECT2 - continue; + break; } @@ -718,7 +733,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // WORK case MFEMUL_WORK: { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Enter in case"); + if (MF_DBGLEVEL >= 1) Dbprintf("[MFEMUL_WORK] Enter in case"); if (receivedCmd_len != 4) { LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); @@ -744,7 +759,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (!HasValidCRC(receivedCmd_dec, receivedCmd_len)) { // all commands must have a valid CRC EmSend4bit(encrypted_data ? mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA) : CARD_NACK_NA); - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] All commands must have a valid CRC %02X (%d)", receivedCmd_dec, receivedCmd_len); break; } @@ -768,11 +783,11 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Example: 6X [00] cardAUTHSC = receivedCmd_dec[1] / 4; - // cardAUTHKEY: 60 => Auth use Key A + // cardAUTHKEY: 60 => Auth use Key A // cardAUTHKEY: 61 => Auth use Key B cardAUTHKEY = receivedCmd_dec[0] & 0x01; - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY %c: %02X%02X", (cardAUTHKEY == 0) ? 'A' : 'B', emlGetKey(cardAUTHSC, cardAUTHKEY)); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] KEY %c: %012" PRIx64, (cardAUTHKEY == 0) ? 'A' : 'B', emlGetKey(cardAUTHSC, cardAUTHKEY)); // first authentication crypto1_destroy(pcs); @@ -814,10 +829,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t break; } - // if (!encrypted_data) { // all other commands must be encrypted (authenticated) - // if (MF_DBGLEVEL >= 0) Dbprintf("Commands must be encrypted (authenticated)"); + //if (!encrypted_data) { // all other commands must be encrypted (authenticated) + // if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Commands must be encrypted (authenticated)"); // break; - // } + //} // case MFEMUL_WORK => if Cmd is Read, Write, Inc, Dec, Restore, Transfert if (receivedCmd_dec[0] == ISO14443A_CMD_READBLOCK @@ -829,12 +844,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Check if Block num is not too far if (receivedCmd_dec[1] > MIFARE_4K_MAXBLOCK) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on out of range block: %d (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], receivedCmd_dec[1]); break; } if (receivedCmd_dec[1] / 4 != cardAUTHSC) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate (0x%02x) on block (0x%02x) not authenticated for (0x%02x), nacking", receivedCmd_dec[0], receivedCmd_dec[1], cardAUTHSC); break; } } @@ -921,7 +936,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t blockNo = receivedCmd_dec[1]; if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)", receivedCmd_dec[0], blockNo, blockNo); if (emlCheckValBl(blockNo)) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_WORK] Reader tried to operate on block, but emlCheckValBl failed, nacking"); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("[MFEMUL_WORK] Reader tried to operate on block, but emlCheckValBl failed, nacking"); EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } @@ -988,12 +1003,12 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t case MFEMUL_AUTH1: { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] Enter case"); - // if (receivedCmd_len != 4) { - // 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); - // if (MF_DBGLEVEL >= 0) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len); - // break; - // } + if (receivedCmd_len != 4) { + 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); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len); + break; + } nr = bytes_to_num(receivedCmd, 4); ar = bytes_to_num(&receivedCmd[4], 4); @@ -1075,8 +1090,8 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t } cardAUTHKEY = AUTHKEYNONE; // not authenticated // LogTrace(Uart.output, Uart.len, Uart.startTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime * 16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + EmSend4bit(CARD_NACK_NA); cardSTATE_TO_IDLE(); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } From 567ceb017b9d0162deb09231f2f178b55030553a Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 6 Apr 2019 00:39:27 +0200 Subject: [PATCH 19/19] Astyle --- armsrc/mifaresim.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/armsrc/mifaresim.c b/armsrc/mifaresim.c index a300e7b57..d4d998a1a 100644 --- a/armsrc/mifaresim.c +++ b/armsrc/mifaresim.c @@ -10,7 +10,7 @@ // Mifare Classic Card Simulation //----------------------------------------------------------------------------- -// Verbose Mode: +// Verbose Mode: // MF_DBG_NONE 0 // MF_DBG_ERROR 1 // MF_DBG_ALL 2 @@ -435,7 +435,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t uint8_t mM = 0; //moebius_modifier for collection storage // Authenticate response - nonce - uint32_t nonce = 0; + uint32_t nonce = 0; // = prng_successor(selTimer, 32) ; if ((flags & FLAG_MF_MINI) == FLAG_MF_MINI) { @@ -783,7 +783,7 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t // Example: 6X [00] cardAUTHSC = receivedCmd_dec[1] / 4; - // cardAUTHKEY: 60 => Auth use Key A + // cardAUTHKEY: 60 => Auth use Key A // cardAUTHKEY: 61 => Auth use Key B cardAUTHKEY = receivedCmd_dec[0] & 0x01; @@ -1004,10 +1004,10 @@ void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("[MFEMUL_AUTH1] Enter case"); if (receivedCmd_len != 4) { - 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); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len); - break; + 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); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("MFEMUL_AUTH1: receivedCmd_len != 8 (%d) => cardSTATE_TO_IDLE())", receivedCmd_len); + break; } nr = bytes_to_num(receivedCmd, 4);