From 64c3ae8b34fa9ffdd5d4fd98ce14ae960d185e86 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Mar 2019 21:04:25 +0100 Subject: [PATCH 001/141] 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 002/141] 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 003/141] 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 004/141] 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 005/141] 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 006/141] 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 007/141] 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 008/141] 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 009/141] 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 010/141] 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 011/141] 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 012/141] 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 013/141] 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 014/141] 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 015/141] 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 436b026b275bd4140257afca5728a65e5c6986ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 07:21:58 +0200 Subject: [PATCH 016/141] ADD: 'script run test_t55x7' - a script to do regression test for t55xx programming / proxmark3 capability to read/demodulate different t55x7 configurations --- client/scripts/test_t55x7.lua | 200 ++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 client/scripts/test_t55x7.lua diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua new file mode 100644 index 000000000..3b7ea2e02 --- /dev/null +++ b/client/scripts/test_t55x7.lua @@ -0,0 +1,200 @@ +local cmds = require('commands') +local getopt = require('getopt') +local bin = require('bin') +local utils = require('utils') + +local format=string.format +local floor=math.floor + +copyright = '' +author = "Iceman" +version = '' +desc =[[ +This script will program a T55x7 TAG with a configuration and four blocks of data. +It will then try to detect and read back those block data and compare if read data matches the expected data. + + +lf t55xx wipe +lf t55xx detect +lf t55xx write b 1 d 00000000 +lf t55xx write b 2 d ffffffff +lf t55xx write b 3 d 80000000 +lf t55xx write b 4 d 00000001 + +Loop: + +try write different configuration blocks, and read block1-4 and comparing the read values with the values used to write. + +testsuit for T55XX commands demodulation + +]] +example = [[ + 1. script run test_t55x7 +]] +usage = [[ + +script run test_t55x7 + +Arguments: + -h this help +]] + +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = true -- the debug flag + +local data_blocks_cmds = { + [1] = '00000000', + [2] = 'ffffffff', + [3] = '80000000', + [4] = '00000001', +} + +--- +-- A debug printout-function +local function dbg(args) + if not DEBUG then + return + end + + if type(args) == "table" then + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +local function oops(err) + print("ERROR: ",err) +end +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print("Example usage") + print(example) +end +--- +-- Exit message +local function exitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end + +local function WipeCard() + + local wipe_cmds = { + [1] = 'lf t55xx wipe', + [2] = 'lf t55xx detect', + } + for _ = 1, #wipe_cmds do + local c = wipe_cmds[_] + dbg(c); core.console(c) + end + + local wipe_data_cmd = "lf t55xx write b %s d %s" + for _ = 1, #data_blocks_cmds do + local val = data_blocks_cmds[_] + local c = string.format(wipe_data_cmd, _, val); + core.console(c) + end +end +--- +-- lf t55xx read +local function CheckReadBlock(block) + local data, msg + -- blockno, page1, override, pwd + data, msg = core.t55xx_readblock(block, "0", "0", "") + if not data then + return "" + end + return ('%08X'):format(data) +end + +local function test() + + -- PSK1 Modulations to test. (2blocks) + local process_block0_cmds = { + [1] = '00001040', + [2] = '00041040', + [3] = '00081040', + [4] = '000c1040', + [5] = '00101040', + [6] = '00141040', + [7] = '00181040', + [8] = '001c1040', + } + + local y + local block = "00" + + for _ = 1, #process_block0_cmds do + + local p_config_cmd = process_block0_cmds[_] + core.clearCommandBuffer() + + -- Write Config block + dbg(('lf t55xx write b 0 d %s'):format(p_config_cmd)) + local config = tonumber(p_config_cmd, 16) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = '00', data = '00'} + local err = core.SendCommand(writecmd:getBytes()) + if err then return oops(err) end + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + + -- Detect + local res, msg = core.t55xx_detect() + if not res then + print("can't detect modulation, skip to next config") + else + -- Loop block1-2 + for _ = 1, #data_blocks_cmds do + local val = data_blocks_cmds[_] + local blockdata, msg = CheckReadBlock(_) + if blockdata ~= val then + print( ('Test %s == %s Failed'):format(val, blockdata)) + core.console( format('rem -- block %d value %s failed', _, val)) + else + print( ('Test %s == %s OK'):format(val, blockdata)) + end + end + end + end +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end + + core.clearCommandBuffer() + + print('Starting test, wiping card') + WipeCard() + print('Detecting card') + local res, msg = core.t55xx_detect() + if res then + print('Starting test') + test() + else + print("can't detect modulation. Test failed. Ending.") + end + +-- test() + exitMsg('Tests finished') + +end +main(args) From 2fa31d33fcd6ad0c9f863636b517c93b58837315 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 07:23:18 +0200 Subject: [PATCH 017/141] style --- common/lfdemod.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 0d33091a6..93ae2266f 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1915,7 +1915,14 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s waveLenCnt = waveEnd - waveStart; if (waveLenCnt > fc) { //this wave is a phase shift - //prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); + /* + prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d" + , waveStart + , waveLenCnt + , lastClkBit + *clock - tol + , i + 1 + , fc); + */ if (i + 1 >= lastClkBit + *clock - tol) { //should be a clock bit curPhase ^= 1; dest[numBits++] = curPhase; From 116837e9a095b9e3cdcecc5dba19f7b8abb61c49 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 20:06:15 +0200 Subject: [PATCH 018/141] chg: 'lf t55xx info' - text layout --- client/cmdlft55xx.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index b25054b2d..dd02db95e 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1292,13 +1292,8 @@ static void printT5x7KnownBlock0(uint32_t b0) { snprintf(s + strlen(s), sizeof(s) - strlen(s), "T55x7 Raw "); break; case T55X7_EM_UNIQUE_CONFIG_BLOCK: - snprintf(s + strlen(s), sizeof(s) - strlen(s), "EM Unique "); + snprintf(s + strlen(s), sizeof(s) - strlen(s), "EM unique, Paxton "); break; - /* - case T55X7_EM_PAXTON_CONFIG_BLOCK: - snprintf(s + strlen(s), sizeof(s)-strlen(s), "EM Paxton "); - break; - */ case T55X7_FDXB_CONFIG_BLOCK: snprintf(s + strlen(s), sizeof(s) - strlen(s), "FDXB "); break; @@ -1339,10 +1334,8 @@ static void printT5x7KnownBlock0(uint32_t b0) { break; } - if (strlen(s) > 0) { - PrintAndLogEx(NORMAL, " Known T55x7 Config block found : " _YELLOW_("%s"), s); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - } + if (strlen(s) > 0) + PrintAndLogEx(NORMAL, "\n Config block match : " _YELLOW_("%s"), s); } int CmdT55xxInfo(const char *Cmd) { @@ -1476,9 +1469,12 @@ int CmdT55xxInfo(const char *Cmd) { PrintAndLogEx(NORMAL, " Block 0 : 0x%08X", block0); else PrintAndLogEx(NORMAL, " Block 0 : 0x%08X %s", block0, sprint_bin(DemodBuffer + config.offset, 32)); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + if (((!gotdata) && (!config.Q5)) || (gotdata && (!dataasq5))) printT5x7KnownBlock0(block0); + + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + return 0; } From cd78a0878bcf3a291a1f45352f3ba8706e0bc84e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:08:23 +0200 Subject: [PATCH 019/141] fix: duplicate breaks --- client/mifare/mifarehost.c | 1 - client/mifare/ndef.c | 1 - 2 files changed, 2 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 9c99f95a3..905fdcc82 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -960,7 +960,6 @@ int detect_classic_nackbug(bool verbose) { int gc = getchar(); (void)gc; return -1; - break; } if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) { diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index b888d8269..da03ecc8f 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -344,7 +344,6 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { case 0xfe: { PrintAndLogEx(INFO, "-- NDEF Terminator. Done."); return 0; - break; } default: { PrintAndLogEx(ERR, "unknown tag 0x%02x", ndef[indx]); From ff25fc700e1b083dd766ae4ac61cd872118e20ec Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:09:43 +0200 Subject: [PATCH 020/141] fix: duplicate break --- client/cliparser/argtable3.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index 0750ed601..f8e4c2387 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -3263,7 +3263,6 @@ static const TRexChar *trex_matchnode(TRex *exp, TRexNode *node, const TRexChar return asd; } return NULL; - break; } case OP_EXPR: case OP_NOCAPEXPR: { From 0dc0a96b3cd82fb1be71c49c45fa7649bd03dd33 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:10:46 +0200 Subject: [PATCH 021/141] fix: duplicate break --- client/cmdanalyse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 1813917aa..5ca75b79f 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -615,7 +615,7 @@ int CmdAnalyseA(const char *Cmd) { } */ - return 0; +// return 0; // 14443-A uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc From 7a152dc3832f9ae2cfdc454a0250bb7ba692ca49 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:11:30 +0200 Subject: [PATCH 022/141] fix: duplicate break --- client/cmdhficlass.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 39a25019c..edc15df74 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2194,7 +2194,6 @@ int CmdHFiClassLookUp(const char *Cmd) { } cmdp += 2; break; - break; case 'e': use_elite = true; cmdp++; From 419eef5a433ab87d5656aa6d41433e3b054c80c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:22:31 +0200 Subject: [PATCH 023/141] fix: duplicate break --- client/emv/crypto_polarssl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index e1f59ddf3..3b0a7d801 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -248,7 +248,6 @@ static size_t crypto_pk_polarssl_get_nbits(const struct crypto_pk *_cp) { struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; return cp->ctx.len * 8; - return 0; } static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_cp, unsigned param, size_t *plen) { @@ -270,7 +269,7 @@ static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_ mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen); break; default: - printf("Error get parameter. Param=%d", param); + printf("Error get parameter. Param = %u", param); break; } From d127c2294c9e3461d516880692740b730011f9dc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:35:38 +0200 Subject: [PATCH 024/141] fix: compare unsigned --- client/emv/emv_pki.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 33d4eeb16..cb2486bb4 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -332,7 +332,7 @@ unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { *sdatl_len = 0; const struct tlv *sda_tl = tlvdb_get(db, 0x9f4a, NULL); - if (!sda_tl || sda_tl->len <= 0) + if (!sda_tl || sda_tl->len == 0) return NULL; for (int i = 0; i < sda_tl->len; i++) { From 4d18b5a11c228fe178e43b00b51e8b03f6072d12 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 22:36:45 +0200 Subject: [PATCH 025/141] fix: compare unsigned --- client/jansson/utf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/jansson/utf.c b/client/jansson/utf.c index 003c422bd..61f0a381b 100644 --- a/client/jansson/utf.c +++ b/client/jansson/utf.c @@ -122,7 +122,7 @@ const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint) return buffer; count = utf8_check_first(buffer[0]); - if (count <= 0) + if (count == 0) return NULL; if (count == 1) From 463661869ad49ee8a797d5aff153b980bc2b6038 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 23:32:47 +0200 Subject: [PATCH 026/141] clean uo --- common/lfdemod.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 93ae2266f..bd51a29b4 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1614,16 +1614,14 @@ int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uin // by marshmellow - demodulate NRZ wave - requires a read with strong signal // peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) { + if (signalprop.isnoise) return -1; size_t clkStartIdx = 0; *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); if (*clk == 0) return -2; - size_t i, gLen = 4096; - if (gLen > *size) - gLen = *size - 20; - + size_t i; // just noise - no super good detection. good enough if (signalprop.isnoise) { @@ -1632,7 +1630,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId } int high, low; - //getHiLo(dest, gLen, &high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); getHiLo(&high, &low, 75, 75); From 287a9dd20466e402682898a696a89589075ee8d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 23:42:02 +0200 Subject: [PATCH 027/141] chg: 'data raw nr' - cleanup --- common/lfdemod.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index bd51a29b4..cfac0a0b5 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1615,20 +1615,16 @@ int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uin // peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) { - if (signalprop.isnoise) return -1; - + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); + return -1; + } + size_t clkStartIdx = 0; *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); if (*clk == 0) return -2; size_t i; - - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); - return -3; - } - int high, low; getHiLo(&high, &low, 75, 75); @@ -1673,7 +1669,7 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, size_t LastSample = 0; size_t currSample = 0; size_t last_transition = 0; - size_t idx = 1; + size_t idx; size_t numBits = 0; //find start of modulating data in trace From 444c12717cd70e1b337c1b171ce1099ae342166f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 23:45:58 +0200 Subject: [PATCH 028/141] clarify --- client/tinycbor/cbortojson.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/tinycbor/cbortojson.c b/client/tinycbor/cbortojson.c index 533e6a721..3ea90cee8 100644 --- a/client/tinycbor/cbortojson.c +++ b/client/tinycbor/cbortojson.c @@ -284,8 +284,7 @@ static CborError add_value_metadata(FILE *out, CborType type, const ConversionSt type = flags & FinalTypeMask; flags &= ~(FinalTypeMask | TypeWasTagged); - if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, - flags & ~TypeWasTagged ? "," : "") < 0) + if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, (flags & ~TypeWasTagged) ? "," : "") < 0) return CborErrorIO; } @@ -300,11 +299,10 @@ static CborError add_value_metadata(FILE *out, CborType type, const ConversionSt if (fprintf(out, ",\"v\":\"nan\"") < 0) return CborErrorIO; if (flags & NumberWasInfinite) - if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0) + if (fprintf(out, ",\"v\":\"%sinf\"", (flags & NumberWasNegative) ? "-" : "") < 0) return CborErrorIO; if (flags & NumberPrecisionWasLost) - if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+', - status->originalNumber) < 0) + if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", (flags & NumberWasNegative) ? '-' : '+', status->originalNumber) < 0) return CborErrorIO; if (type == CborSimpleType) if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0) From 4326d05674fa593d6ceb5d27c32c3bb1b87c33b6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 4 Apr 2019 23:48:00 +0200 Subject: [PATCH 029/141] clarify --- client/tinycbor/cborinternal_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/tinycbor/cborinternal_p.h b/client/tinycbor/cborinternal_p.h index 8609ce2ad..65c42cdf4 100644 --- a/client/tinycbor/cborinternal_p.h +++ b/client/tinycbor/cborinternal_p.h @@ -87,7 +87,7 @@ static inline double decode_half(unsigned short half) { if (exp == 0) val = ldexp(mant, -24); else if (exp != 31) val = ldexp(mant + 1024, exp - 25); else val = mant == 0 ? INFINITY : NAN; - return half & 0x8000 ? -val : val; + return (half & 0x8000) ? -val : val; } # endif #endif /* CBOR_NO_HALF_FLOAT_TYPE */ From ad97aa3d29178234f6a7da0bb28bfbe841db998d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 00:08:36 +0200 Subject: [PATCH 030/141] chg: 'hf iclass sim' - void*, should be uin8_t* --- client/cmdhficlass.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index edc15df74..c25bebdd3 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -405,7 +405,7 @@ int CmdHFiClassSim(const char *Cmd) { break; size_t datalen = NUM_CSNS * 24; - void *dump = calloc(datalen, sizeof(uint8_t)); + uint8_t *dump = calloc(datalen, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; @@ -458,7 +458,7 @@ int CmdHFiClassSim(const char *Cmd) { break; size_t datalen = NUM_CSNS * 24; - void *dump = calloc(datalen, sizeof(uint8_t)); + uint8_t *dump = calloc(datalen, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; From bc11ff88ea67d779b428a01386b4adca65b9132c Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 5 Apr 2019 03:58:15 +0200 Subject: [PATCH 031/141] 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 032/141] 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 1a565ae953583fe5a45149cee3a28174e9a52883 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 07:39:07 +0200 Subject: [PATCH 033/141] fix uninitialised --- client/scripting.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index f3afb18d4..cf9b5c590 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -785,8 +785,7 @@ static int l_T55xx_readblock(lua_State *L) { // arg 2 = use GB static int l_T55xx_detect(lua_State *L) { bool useGB = false, usepwd = false, isok; - uint32_t password; - uint32_t gb; + uint32_t gb, password = 0; size_t size; //Check number of arguments From a499e30608bc716f878674ee4fbee3e3e20eb6fe Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 08:21:10 +0200 Subject: [PATCH 034/141] chg: 'script run test_t55x7' - more modulations and better wipe card --- client/scripts/test_t55x7.lua | 185 +++++++++++++++++++++++++++------- 1 file changed, 146 insertions(+), 39 deletions(-) diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua index 3b7ea2e02..0d89147c6 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/test_t55x7.lua @@ -89,23 +89,134 @@ local function exitMsg(msg) print(msg) print() end +--- +-- ask/fsk/psk configuration blocks to test +local function GetConfigs( modulation ) + local t = {} + + t['ASK'] = { + [1] = '00008040', + [2] = '00048040', + [3] = '00088040', + [4] = '000c8040', + [5] = '00108040', + [6] = '00148040', + [7] = '00188040', + [8] = '001c8040', + } + + t['BI'] = { + [1] = '00010040', + [2] = '00050040', + [3] = '00090040', + [4] = '000d0040', + [5] = '00110040', + [6] = '00150040', + [7] = '00190040', + [8] = '001d0040', + } + + t['FSK2A'] = { + [1] = '00007040', + [2] = '00047040', + [3] = '00087040', + [4] = '000c7040', + [5] = '00107040', + [6] = '00147040', + [7] = '00187040', + [8] = '001c7040', + } + + t['FSK1A'] = { + [1] = '00006040', + [2] = '00046040', + [3] = '00086040', + [4] = '000c6040', + [5] = '00106040', + [6] = '00146040', + [7] = '00186040', + [8] = '001c6040', + } + + t['FSK2'] = { + [1] = '00005040', + [2] = '00045040', + [3] = '00085040', + [4] = '000c5040', + [5] = '00105040', + [6] = '00145040', + [7] = '00185040', + [8] = '001c5040', + } + + t['FSK1'] = { + [1] = '00004040', + [2] = '00004040', + [3] = '00044040', + [4] = '00084040', + [5] = '000c4040', + [6] = '00104040', + [7] = '00144040', + [8] = '00184040', + [9] = '001c4040', + } + + t['PSK1'] = { + [1] = '00001040', + [2] = '00041040', + [3] = '00081040', + [4] = '000c1040', + [5] = '00101040', + [6] = '00141040', + [7] = '00181040', + [8] = '001c1040', + } + + t['PSK2'] = { + [1] = '00002040', + [2] = '00042040', + [3] = '00082040', + [4] = '000c2040', + [5] = '00102040', + [6] = '00142040', + [7] = '00182040', + [8] = '001c2040', + } + + t['PSK3'] = { + [1] = '00003040', + [2] = '00043040', + [3] = '00083040', + [4] = '000c3040', + [5] = '00103040', + [6] = '00143040', + [7] = '00183040', + [8] = '001c3040', + } + return t[modulation] +end +--- +-- lf t55xx wipe local function WipeCard() - local wipe_cmds = { - [1] = 'lf t55xx wipe', - [2] = 'lf t55xx detect', - } - for _ = 1, #wipe_cmds do - local c = wipe_cmds[_] - dbg(c); core.console(c) - end + print('Wiping card') + core.console('lf t55xx wipe') - local wipe_data_cmd = "lf t55xx write b %s d %s" - for _ = 1, #data_blocks_cmds do - local val = data_blocks_cmds[_] - local c = string.format(wipe_data_cmd, _, val); - core.console(c) + print('Detecting card'); + local res, msg = core.t55xx_detect() + if not res then + oops("can't detect modulation. Test failed."); + core.console("rem Failed to detect"); + return false + else + local wipe_data_cmd = "lf t55xx write b %s d %s" + for _ = 1, #data_blocks_cmds do + local val = data_blocks_cmds[_] + local c = string.format(wipe_data_cmd, _, val); + core.console(c) + end + return true end end --- @@ -120,23 +231,18 @@ local function CheckReadBlock(block) return ('%08X'):format(data) end -local function test() +local function test(modulation) - -- PSK1 Modulations to test. (2blocks) - local process_block0_cmds = { - [1] = '00001040', - [2] = '00041040', - [3] = '00081040', - [4] = '000c1040', - [5] = '00101040', - [6] = '00141040', - [7] = '00181040', - [8] = '001c1040', - } - + local process_block0_cmds = {} local y local block = "00" - + + local s = ('Start test of %s'):format(modulation) + print(s) + core.console('rem '..s) + + process_block0_cmds = GetConfigs(modulation) + for _ = 1, #process_block0_cmds do local p_config_cmd = process_block0_cmds[_] @@ -181,19 +287,20 @@ local function main(args) end core.clearCommandBuffer() - - print('Starting test, wiping card') - WipeCard() - print('Detecting card') - local res, msg = core.t55xx_detect() - if res then - print('Starting test') - test() - else - print("can't detect modulation. Test failed. Ending.") - end + local res --- test() + res = WipeCard() + if res then test("ASK") end + +-- res = WipeCard() +-- if res then test("FSK1") end + +-- res = WipeCard() +-- if res then test("FSK2") end + +-- res = WipeCard() +-- if res then test("PSK1") end + exitMsg('Tests finished') end From 229452719a09753382ee3239c7611be3a11a1afd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 08:36:12 +0200 Subject: [PATCH 035/141] chg: compare with low case --- client/scripts/test_t55x7.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua index 0d89147c6..c1cbd214e 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/test_t55x7.lua @@ -265,7 +265,7 @@ local function test(modulation) for _ = 1, #data_blocks_cmds do local val = data_blocks_cmds[_] local blockdata, msg = CheckReadBlock(_) - if blockdata ~= val then + if blockdata:lower() ~= val:lower() then print( ('Test %s == %s Failed'):format(val, blockdata)) core.console( format('rem -- block %d value %s failed', _, val)) else From 774cbc5cb9f4e920988dc78aa1611d12e17532b0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 08:58:12 +0200 Subject: [PATCH 036/141] chg: 'script run test_t55x7' - better test loops --- client/scripts/test_t55x7.lua | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua index c1cbd214e..015b578c0 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/test_t55x7.lua @@ -194,7 +194,7 @@ local function GetConfigs( modulation ) [7] = '00183040', [8] = '001c3040', } - return t[modulation] + return t[modulation:upper()] end --- -- lf t55xx wipe @@ -243,6 +243,8 @@ local function test(modulation) process_block0_cmds = GetConfigs(modulation) + if process_block0_cmds == nil then return oops('Cant find modulation '..modulation) end + for _ = 1, #process_block0_cmds do local p_config_cmd = process_block0_cmds[_] @@ -289,17 +291,14 @@ local function main(args) core.clearCommandBuffer() local res - res = WipeCard() - if res then test("ASK") end - --- res = WipeCard() --- if res then test("FSK1") end - --- res = WipeCard() --- if res then test("FSK2") end - --- res = WipeCard() --- if res then test("PSK1") end + -- Adjust this table to set which configurations should be tested + local test_modes = { 'ASK', 'PSK1' } + + for _ = 1, #test_modes do + res = WipeCard() + print (test_modes[_]) + if res then test(test_modes[_]) end + end exitMsg('Tests finished') From 5b0eed26b58249a8566adfd0cdaac7099c4028e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 09:14:40 +0200 Subject: [PATCH 037/141] style --- client/emv/emv_tags.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 605707a65..ee6824b32 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -537,7 +537,7 @@ static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *ta static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { PRINT_INDENT(level); - fprintf(f, "\tDate: 20%02ld.%ld.%ld\n", + fprintf(f, "\tDate: 20%02lu.%lu.%lu\n", emv_value_numeric(tlv, 0, 2), emv_value_numeric(tlv, 2, 4), emv_value_numeric(tlv, 4, 6)); @@ -667,9 +667,9 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t Y = emv_get_binary(tlv->value + 4); PRINT_INDENT(level); - fprintf(f, "\tX: %d\n", X); + fprintf(f, "\tX: %u\n", X); PRINT_INDENT(level); - fprintf(f, "\tY: %d\n", Y); + fprintf(f, "\tY: %u\n", Y); for (i = 8; i < tlv->len; i += 2) { const char *method; From 632e80e9b142f9187b7e28c80be1204f9ee607d0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 09:16:01 +0200 Subject: [PATCH 038/141] style --- client/hid-flasher/flash.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/hid-flasher/flash.c b/client/hid-flasher/flash.c index 020be9e87..edfc6b776 100644 --- a/client/hid-flasher/flash.c +++ b/client/hid-flasher/flash.c @@ -413,7 +413,7 @@ int flash_write(flash_file_t *ctx) { uint32_t blocks = (length + BLOCK_SIZE - 1) / BLOCK_SIZE; uint32_t end = seg->start + length; - fprintf(stderr, " 0x%08x..0x%08x [0x%x / %d blocks]", + fprintf(stderr, " 0x%08x..0x%08x [0x%x / %u blocks]", seg->start, end - 1, length, blocks); int block = 0; @@ -427,7 +427,7 @@ int flash_write(flash_file_t *ctx) { if (write_block(baddr, data, block_size) < 0) { fprintf(stderr, " ERROR\n"); - fprintf(stderr, "Error writing block %d of %d\n", block, blocks); + fprintf(stderr, "Error writing block %d of %u\n", block, blocks); return -1; } From 647dcc596f40b63bd9f869af3930c51c7b5362a8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 09:18:52 +0200 Subject: [PATCH 039/141] style --- client/cmdhfmfu.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 956cc1a70..ac1391c47 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1134,8 +1134,6 @@ int CmdHF14AMfUInfo(const char *Cmd) { // hasAuthKey, if we was called with key, skip test. if (!authlim && !hasAuthKey) { PrintAndLogEx(NORMAL, "\n--- Known EV1/NTAG passwords."); - len = 0; - // test pwd gen A num_to_bytes(ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); From 6404c974b63bd730346e46f112eea6d3a441e7c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 09:20:37 +0200 Subject: [PATCH 040/141] style --- client/cmdlfem4x.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index e6da5da33..8d5ebb68b 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -1225,9 +1225,8 @@ int CmdEM4x05Write(const char *Cmd) { if (strlen(Cmd) == 0 || ctmp == 'h') return usage_lf_em4x05_write(); bool usePwd = false; - uint8_t addr = 50; // default to invalid address - uint32_t data = 0; // default to blank data - uint32_t pwd = 1; // default to blank password + uint8_t addr; + uint32_t data, pwd; addr = param_get8ex(Cmd, 0, 50, 10); data = param_get32ex(Cmd, 1, 0, 16); From 82f4388abed041270627b1eeaed8491447479921 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 09:22:12 +0200 Subject: [PATCH 041/141] style --- client/hid-flasher/flash.c | 2 +- client/hid-flasher/proxusb.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/hid-flasher/flash.c b/client/hid-flasher/flash.c index edfc6b776..967888e17 100644 --- a/client/hid-flasher/flash.c +++ b/client/hid-flasher/flash.c @@ -180,7 +180,7 @@ static int check_segs(flash_file_t *ctx, int can_write_bl) { // Load an ELF file and prepare it for flashing int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { - FILE *fd = NULL; + FILE *fd; Elf32_Ehdr ehdr; Elf32_Phdr *phdrs = NULL; int num_phdrs; diff --git a/client/hid-flasher/proxusb.c b/client/hid-flasher/proxusb.c index f7ff5d489..7563429d8 100644 --- a/client/hid-flasher/proxusb.c +++ b/client/hid-flasher/proxusb.c @@ -166,7 +166,7 @@ usb_dev_handle *findProxmark(int verbose, unsigned int *iface) { usb_dev_handle *OpenProxmark(int verbose) { int ret; - usb_dev_handle *handle = NULL; + usb_dev_handle *handle; unsigned int iface; handle = findProxmark(verbose, &iface); From ea5dddafef732107ec081097efed554109f94c72 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 18:47:36 +0200 Subject: [PATCH 042/141] fix: invalidPrintfArg --- client/emv/crypto_polarssl.c | 4 ++-- client/emv/emv_pk.c | 2 +- client/emv/emv_roca.c | 2 +- client/flasher.c | 10 +++++----- uart/uart_posix.c | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 3b0a7d801..ff5a867a9 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -208,7 +208,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co res = mbedtls_rsa_public(&cp->ctx, buf, result); if (res) { - printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); + printf("RSA encrypt failed. Error: %x data len: %zu key len: %zu\n", res * -1, len, keylen); free(result); return NULL; } @@ -234,7 +234,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co res = mbedtls_rsa_private(&cp->ctx, NULL, NULL, buf, result); // CHECK??? if (res) { - printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); + printf("RSA decrypt failed. Error: %x data len: %zu key len: %zu\n", res * -1, len, keylen); free(result); return NULL; } diff --git a/client/emv/emv_pk.c b/client/emv/emv_pk.c index 4c6afa88e..9b5f2e714 100644 --- a/client/emv/emv_pk.c +++ b/client/emv/emv_pk.c @@ -483,7 +483,7 @@ struct emv_pk *emv_pk_get_ca_pk(const unsigned char *rid, unsigned char idx) { if (!pk) return NULL; - printf("Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zd bits...", + printf("Verifying CA PK for %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx %zu bits...", pk->rid[0], pk->rid[1], pk->rid[2], diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 3a89020c7..c0d0d419d 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -84,7 +84,7 @@ void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { size_t len = 0; mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len); - printf("%s[%ld] %s\n", msg, len, Xchar); + printf("%s[%zu] %s\n", msg, len, Xchar); } bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { diff --git a/client/flasher.c b/client/flasher.c index bc744b339..cb77ce719 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -23,11 +23,11 @@ void cmd_debug(UsbCommand *c) { // Debug printf("UsbCommand length[len=%zd]\n", sizeof(UsbCommand)); - printf(" cmd[len=%zd]: %016" PRIx64"\n", sizeof(c->cmd), c->cmd); - printf(" arg0[len=%zd]: %016" PRIx64"\n", sizeof(c->arg[0]), c->arg[0]); - printf(" arg1[len=%zd]: %016" PRIx64"\n", sizeof(c->arg[1]), c->arg[1]); - printf(" arg2[len=%zd]: %016" PRIx64"\n", sizeof(c->arg[2]), c->arg[2]); - printf(" data[len=%zd]: ", sizeof(c->d.asBytes)); + printf(" cmd[len=%zu]: %016" PRIx64"\n", sizeof(c->cmd), c->cmd); + printf(" arg0[len=%zu]: %016" PRIx64"\n", sizeof(c->arg[0]), c->arg[0]); + printf(" arg1[len=%zu]: %016" PRIx64"\n", sizeof(c->arg[1]), c->arg[1]); + printf(" arg2[len=%zu]: %016" PRIx64"\n", sizeof(c->arg[2]), c->arg[2]); + printf(" data[len=%zu]: ", sizeof(c->d.asBytes)); for (size_t i = 0; i < 16; i++) printf("%02x", c->d.asBytes[i]); diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 92af6774a..4c9e8b990 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -206,7 +206,7 @@ serial_port uart_open(const char *pcPortName, uint32_t speed) { } } } - printf("[=] UART Setting serial baudrate %i\n", speed); + printf("[=] UART Setting serial baudrate %u\n", speed); return sp; } From 1773cfcf390bb7e7142f0a462f9d729df751694f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 18:51:19 +0200 Subject: [PATCH 043/141] style --- armsrc/Standalone/hf_young.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 4b7a87e99..866b13e0c 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -158,7 +158,7 @@ void RunMod() { Bytes 5-7 are reserved SAK and ATQA for mifare classic -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it */ - uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; + uint8_t oldBlock0[16] = {0}, newBlock0[16], testBlock0[16] = {0}; // arg0 = Flags, arg1=blockNo MifareCGetBlock(params, 0, oldBlock0); if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { From e7406de2191d8d508fccd6ee4cafcc35fd862137 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 18:53:17 +0200 Subject: [PATCH 044/141] redundant. --- client/cmdlfhid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index c0d55f977..b44a5e68a 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -459,8 +459,8 @@ int CmdHIDWiegand(const char *Cmd) { uint8_t *bs = bits; memset(bs, 0, sizeof(bits)); - uint8_t ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || strlen(Cmd) < 3 || ctmp == 'H' || ctmp == 'h') return usage_lf_hid_wiegand(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 3 || ctmp == 'h') return usage_lf_hid_wiegand(); oem = param_get8(Cmd, 0); fc = param_get32ex(Cmd, 1, 0, 10); From d42b779cbe484891c05cf02cfc31e841e6fbe6b5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 18:55:31 +0200 Subject: [PATCH 045/141] style --- client/crypto/asn1dump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index b62d83cbc..c55244286 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -323,7 +323,7 @@ bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { const struct asn1_tag *tag = asn1_get_tag(tlv); PRINT_INDENT(level); - fprintf(f, "--%2hx[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + fprintf(f, "--%2x[%02zx] '%s':", tlv->tag, tlv->len, tag->name); switch (tag->type) { case ASN1_TAG_GENERIC: From ffdfe09659a571b5e2d22531b4a3685ebf0a1355 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 18:57:05 +0200 Subject: [PATCH 046/141] style --- client/emv/emv_tags.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index ee6824b32..dc6503f4b 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -490,7 +490,7 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F doltag = emv_get_tag(&doltlv); PRINT_INDENT(level); - fprintf(f, "\tTag %4hx len %02zx ('%s')\n", doltlv.tag, doltlv.len, doltag->name); + fprintf(f, "\tTag %4x len %02zx ('%s')\n", doltlv.tag, doltlv.len, doltag->name); } } @@ -773,7 +773,7 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { const struct emv_tag *tag = emv_get_tag(tlv); PRINT_INDENT(level); - fprintf(f, "--%2hx[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + fprintf(f, "--%2x[%02zx] '%s':", tlv->tag, tlv->len, tag->name); switch (tag->type) { case EMV_TAG_GENERIC: From 4be92f129a0b8816b4ce11000c51b5f33a775327 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 19:13:03 +0200 Subject: [PATCH 047/141] style --- client/flasher.c | 2 +- client/fpga_compress.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/flasher.c b/client/flasher.c index cb77ce719..be74ef8e6 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -22,7 +22,7 @@ void cmd_debug(UsbCommand *c) { // Debug - printf("UsbCommand length[len=%zd]\n", sizeof(UsbCommand)); + printf("UsbCommand length[len=%zu]\n", sizeof(UsbCommand)); printf(" cmd[len=%zu]: %016" PRIx64"\n", sizeof(c->cmd), c->cmd); printf(" arg0[len=%zu]: %016" PRIx64"\n", sizeof(c->arg[0]), c->arg[0]); printf(" arg1[len=%zu]: %016" PRIx64"\n", sizeof(c->arg[1]), c->arg[1]); diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 0f4220632..3a06a62d3 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -98,12 +98,12 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn #if __WORDSIZE == 64 "Input file too big (> %" PRIu64 " bytes). This is probably not a hardnested bitflip state table.\n" #else - "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n" + "Input file too big (> %zu bytes). This is probably not a hardnested bitflip state table.\n" #endif , HARDNESTED_TABLE_SIZE); } else { - fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); + fprintf(stderr, "Input files too big (total > %zu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } for (uint16_t j = 0; j < num_infiles; j++) { fclose(infile[j]); From fa0a2914f657c60571a2f3ef23095f8f2a595651 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 19:29:16 +0200 Subject: [PATCH 048/141] style --- client/cmdsmartcard.c | 2 +- client/fpga_compress.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 2a0216aa7..b1c3c3797 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -1107,7 +1107,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { //Validations if (errors) return usage_sm_brute(); - const char *SELECT = "00a40400%02x%s"; + const char *SELECT = "00a40400%02zu%s"; // uint8_t GENERATE_AC[] = {0x80, 0xAE}; // uint8_t GET_CHALLENGE[] = {0x00, 0x84, 0x00}; diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 3a06a62d3..00e62d74b 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -98,12 +98,12 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn #if __WORDSIZE == 64 "Input file too big (> %" PRIu64 " bytes). This is probably not a hardnested bitflip state table.\n" #else - "Input file too big (> %zu bytes). This is probably not a hardnested bitflip state table.\n" + "Input file too big (> %li bytes). This is probably not a hardnested bitflip state table.\n" #endif , HARDNESTED_TABLE_SIZE); } else { - fprintf(stderr, "Input files too big (total > %zu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); + fprintf(stderr, "Input files too big (total > %li bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } for (uint16_t j = 0; j < num_infiles; j++) { fclose(infile[j]); From 841f20c5e5129a057970b3bf6594ae87f3bfb1b3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 19:34:05 +0200 Subject: [PATCH 049/141] test_t55x7 logs & stats --- client/scripts/test_t55x7.lua | 177 +++++++++++++++++++--------------- 1 file changed, 99 insertions(+), 78 deletions(-) diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua index 015b578c0..3d21cc9e5 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/test_t55x7.lua @@ -40,7 +40,9 @@ Arguments: ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds -local DEBUG = true -- the debug flag +local DEBUG = false -- the debug flag +local total_tests = 0 +local total_pass = 0 local data_blocks_cmds = { [1] = '00000000', @@ -95,73 +97,6 @@ local function GetConfigs( modulation ) local t = {} - t['ASK'] = { - [1] = '00008040', - [2] = '00048040', - [3] = '00088040', - [4] = '000c8040', - [5] = '00108040', - [6] = '00148040', - [7] = '00188040', - [8] = '001c8040', - } - - t['BI'] = { - [1] = '00010040', - [2] = '00050040', - [3] = '00090040', - [4] = '000d0040', - [5] = '00110040', - [6] = '00150040', - [7] = '00190040', - [8] = '001d0040', - } - - t['FSK2A'] = { - [1] = '00007040', - [2] = '00047040', - [3] = '00087040', - [4] = '000c7040', - [5] = '00107040', - [6] = '00147040', - [7] = '00187040', - [8] = '001c7040', - } - - t['FSK1A'] = { - [1] = '00006040', - [2] = '00046040', - [3] = '00086040', - [4] = '000c6040', - [5] = '00106040', - [6] = '00146040', - [7] = '00186040', - [8] = '001c6040', - } - - t['FSK2'] = { - [1] = '00005040', - [2] = '00045040', - [3] = '00085040', - [4] = '000c5040', - [5] = '00105040', - [6] = '00145040', - [7] = '00185040', - [8] = '001c5040', - } - - t['FSK1'] = { - [1] = '00004040', - [2] = '00004040', - [3] = '00044040', - [4] = '00084040', - [5] = '000c4040', - [6] = '00104040', - [7] = '00144040', - [8] = '00184040', - [9] = '001c4040', - } - t['PSK1'] = { [1] = '00001040', [2] = '00041040', @@ -193,7 +128,75 @@ local function GetConfigs( modulation ) [6] = '00143040', [7] = '00183040', [8] = '001c3040', - } + } + + t['FSK1'] = { + [1] = '00004040', + [2] = '00004040', + [3] = '00044040', + [4] = '00084040', + [5] = '000c4040', + [6] = '00104040', + [7] = '00144040', + [8] = '00184040', + [9] = '001c4040', + } + + t['FSK2'] = { + [1] = '00005040', + [2] = '00045040', + [3] = '00085040', + [4] = '000c5040', + [5] = '00105040', + [6] = '00145040', + [7] = '00185040', + [8] = '001c5040', + } + + t['FSK1A'] = { + [1] = '00006040', + [2] = '00046040', + [3] = '00086040', + [4] = '000c6040', + [5] = '00106040', + [6] = '00146040', + [7] = '00186040', + [8] = '001c6040', + } + + t['FSK2A'] = { + [1] = '00007040', + [2] = '00047040', + [3] = '00087040', + [4] = '000c7040', + [5] = '00107040', + [6] = '00147040', + [7] = '00187040', + [8] = '001c7040', + } + + t['ASK'] = { + [1] = '00008040', + [2] = '00048040', + [3] = '00088040', + [4] = '000c8040', + [5] = '00108040', + [6] = '00148040', + [7] = '00188040', + [8] = '001c8040', + } + + t['BI'] = { + [1] = '00010040', + [2] = '00050040', + [3] = '00090040', + [4] = '000d0040', + [5] = '00110040', + [6] = '00150040', + [7] = '00190040', + [8] = '001d0040', + } + return t[modulation:upper()] end --- @@ -203,17 +206,17 @@ local function WipeCard() print('Wiping card') core.console('lf t55xx wipe') - print('Detecting card'); + print('Detecting card') local res, msg = core.t55xx_detect() if not res then - oops("can't detect modulation. Test failed."); - core.console("rem Failed to detect"); + oops("Can't detect modulation. Test failed.") + core.console("rem [ERR:DETECT:WIPED] Failed to detect after wipe") return false else local wipe_data_cmd = "lf t55xx write b %s d %s" for _ = 1, #data_blocks_cmds do local val = data_blocks_cmds[_] - local c = string.format(wipe_data_cmd, _, val); + local c = string.format(wipe_data_cmd, _, val) core.console(c) end return true @@ -239,7 +242,6 @@ local function test(modulation) local s = ('Start test of %s'):format(modulation) print(s) - core.console('rem '..s) process_block0_cmds = GetConfigs(modulation) @@ -248,6 +250,7 @@ local function test(modulation) for _ = 1, #process_block0_cmds do local p_config_cmd = process_block0_cmds[_] + local errors = 0 core.clearCommandBuffer() -- Write Config block @@ -262,19 +265,30 @@ local function test(modulation) local res, msg = core.t55xx_detect() if not res then print("can't detect modulation, skip to next config") + core.console(format("rem [ERR:DETECT:%s] Failed to detect modulation", p_config_cmd)) + core.console(format('rem [SUMMARY:%s] FAIL detection', p_config_cmd)) + total_tests = total_tests + #data_blocks_cmds else -- Loop block1-2 for _ = 1, #data_blocks_cmds do + total_tests = total_tests + 1 local val = data_blocks_cmds[_] local blockdata, msg = CheckReadBlock(_) if blockdata:lower() ~= val:lower() then print( ('Test %s == %s Failed'):format(val, blockdata)) - core.console( format('rem -- block %d value %s failed', _, val)) + core.console( format('rem [ERR:READ:%s:%d] block %d: read %s instead of %s', p_config_cmd, _, _, blockdata, val)) + errors = errors+1 else print( ('Test %s == %s OK'):format(val, blockdata)) + total_pass = total_pass + 1 end end - end + if errors >0 then + core.console( format('rem [SUMMARY:%s] FAIL %d test%s', p_config_cmd, errors, errors > 1 and "s" or "")) + else + core.console( format('rem [SUMMARY:%s] PASS all tests', p_config_cmd)) + end + end end end @@ -292,15 +306,22 @@ local function main(args) local res -- Adjust this table to set which configurations should be tested +-- local test_modes = { 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2', 'FSK1A', 'FSK2A', 'ASK', 'BI' } local test_modes = { 'ASK', 'PSK1' } for _ = 1, #test_modes do res = WipeCard() - print (test_modes[_]) - if res then test(test_modes[_]) end + if res then + print (test_modes[_]) + test(test_modes[_]) + else + exitMsg('Abort!') + return + end end exitMsg('Tests finished') + core.console( format('rem [SUMMARY] Success rate: %d/%d tests passed%s', total_pass, total_tests, total_pass < total_tests and ", help me improving that number!" or " \\o/")) end main(args) From 8c017157d40958db8b5ef3a0c5183d0fa40ec236 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 5 Apr 2019 20:28:58 +0200 Subject: [PATCH 050/141] chg: better strong wave detection for biphase --- common/lfdemod.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index cfac0a0b5..a0dea9d9d 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -445,11 +445,11 @@ int ManchesterEncode(uint8_t *bits, size_t size) { // by marshmellow // to detect a wave that has heavily clipped (clean) samples -// loop 512 samples, if 250 of them is deemed maxed out, we assume the wave is clipped. +// loop 1024 samples, if 250 of them is deemed maxed out, we assume the wave is clipped. bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { bool allArePeaks = true; uint16_t cntPeaks = 0; - size_t loopEnd = 512 + 160; + size_t loopEnd = 1024 + 160; // sanity check if (loopEnd > size) loopEnd = size; @@ -463,7 +463,8 @@ bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { } if (!allArePeaks) { - if (cntPeaks > 250) return true; + if (g_debugMode == 2) prnt("DEBUG DetectCleanAskWave: peaks (200) %u", cntPeaks); + if (cntPeaks > 200) return true; } return allArePeaks; } From 84753b91c041643b02dbba15948982d0df38aeed Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 21:12:32 +0200 Subject: [PATCH 051/141] fix %u <> size_t compilation warning --- client/scripting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index cf9b5c590..d4efac99f 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -797,7 +797,7 @@ static int l_T55xx_detect(lua_State *L) { if (size != 1) return returnToLuaWithError(L, "Wrong size of useGB, got %d , expected 1", (int) size); sscanf(p_gb, "%u", &gb); useGB = ( gb ) ? true : false; - printf("p_gb size %u | %c \n", size, useGB ? 'Y':'N'); + printf("p_gb size %zu | %c \n", size, useGB ? 'Y':'N'); } case 1: { const char *p_pwd = luaL_checklstring(L, 1, &size); From 404e92a0b1808c4119fe36d74c0d93b22ad61884 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 22:37:41 +0200 Subject: [PATCH 052/141] utf8 Chinese... we might just translate it appropriately... --- common/i2c.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 80fb2690c..ad0f8964c 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -26,7 +26,7 @@ volatile unsigned long c; -// Ö±½ÓʹÓÃÑ­»·À´ÑÓʱ£¬Ò»¸öÑ­»· 6 ÌõÖ¸Á48M£¬ Delay=1 ´ó¸ÅΪ 200kbps +// 直接使用循环æ¥å»¶æ—¶ï¼Œä¸€ä¸ªå¾ªçޝ 6 æ¡æŒ‡ä»¤ï¼Œ48M, Delay=1 大概为 200kbps // timer. // I2CSpinDelayClk(4) = 12.31us // I2CSpinDelayClk(1) = 3.07us @@ -467,8 +467,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d *data = (uint8_t)tmp & 0xFF; len--; - - // ¶ÁÈ¡µÄµÚÒ»¸ö×Ö½ÚΪºóÐø³¤¶È + // 读å–的第一个字节为åŽç»­é•¿åº¦ // The first byte in response is the message length if (!readcount && (len > *data)) { len = *data; From a738cdcdb2bf59c081c041b1be4ac373bc1dd11d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 22:44:50 +0200 Subject: [PATCH 053/141] Detecting weird codepages --- Makefile | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2ad01ba5f..53bb2d559 100644 --- a/Makefile +++ b/Makefile @@ -56,7 +56,7 @@ recovery/%: FORCE $(MAKE) -C recovery $(patsubst recovery/%,%,$@) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) -.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style FORCE +.PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style checks FORCE help: @echo "Multi-OS Makefile" @@ -76,6 +76,8 @@ help: @echo "+ mfkey - Make tools/mfkey" @echo "+ nounce2key - Make tools/nounce2key" @echo + @echo "+ style - Apply some automated source code formatting rules" + @echo "+ checks - Detect various encoding issues in source code" @echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4" client: client/all @@ -138,5 +140,10 @@ style: --style=google --pad-oper --unpad-paren --pad-header \ --align-pointer=name {} \; +# Detecting weird codepages. +checks: + find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \ + -exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \; + # Dummy target to test for GNU make availability _test: From 7fa4b86df6868234728c30c3f4511688a8d46104 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 22:45:42 +0200 Subject: [PATCH 054/141] textual --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index 53bb2d559..77c205e68 100644 --- a/Makefile +++ b/Makefile @@ -78,6 +78,7 @@ help: @echo @echo "+ style - Apply some automated source code formatting rules" @echo "+ checks - Detect various encoding issues in source code" + @echo @echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4" client: client/all From 9ff5a4e2fa318c63ea0410f866db2fec4fc25903 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 23:17:16 +0200 Subject: [PATCH 055/141] style --- client/ui.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/client/ui.c b/client/ui.c index d0318dba5..216fbccff 100644 --- a/client/ui.c +++ b/client/ui.c @@ -21,6 +21,8 @@ bool showDemod = true; pthread_mutex_t print_lock = PTHREAD_MUTEX_INITIALIZER; static char *logfilename = "proxmark3.log"; +float complex cexpf(float complex Z); + void PrintAndLogOptions(char *str[][2], size_t size, size_t space) { char buff[2000] = "Options:\n"; char format[2000] = ""; @@ -53,7 +55,6 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { char buffer[MAX_PRINT_BUFFER] = {0}; char buffer2[MAX_PRINT_BUFFER + 20] = {0}; char *token = NULL; - int size = 0; // {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG} static char *prefixes[7] = { "", "[+] ", "[=] ", "[-] ", "[!] ", "[!!] ", "[#] "}; @@ -101,7 +102,7 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { while (token != NULL) { - size = strlen(buffer2); + size_t size = strlen(buffer2); if (strlen(token)) snprintf(buffer2 + size, sizeof(buffer2) - size, "%s%s\n", prefix, token); @@ -210,13 +211,11 @@ void iceIIR_Butterworth(int *data, const size_t len) { float b[3] = {0.003621681514929, 0.007243363029857, 0.003621681514929}; float a[3] = {1.000000000000000, -1.822694925196308, 0.837181651256023}; - float sample = 0; // input sample read from array - float complex x_prime = 1.0f; // save sample for estimating frequency - float complex x; - for (i = 0; i < adjustedLen; ++i) { - sample = data[i]; + float sample = data[i]; // input sample read from array + float complex x_prime = 1.0f; // save sample for estimating frequency + float complex x; // remove DC offset and mix to complex baseband x = (sample - 127.5f) * cexpf(_Complex_I * 2 * M_PI * fc * i); @@ -251,18 +250,14 @@ void iceSimple_Filter(int *data, const size_t len, uint8_t k) { #define FILTER_SHIFT 4 int32_t filter_reg = 0; - int16_t input, output; int8_t shift = (k <= 8) ? k : FILTER_SHIFT; for (int i = 0; i < len; ++i) { - - input = data[i]; // Update filter with current sample - filter_reg = filter_reg - (filter_reg >> shift) + input; + filter_reg = filter_reg - (filter_reg >> shift) + data[i]; // Scale output for unity gain - output = filter_reg >> shift; - data[i] = output; + data[i] = filter_reg >> shift; } } From 7effdfc2751cc8edee3039e111f93cad62ce1bf4 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 5 Apr 2019 23:29:19 +0200 Subject: [PATCH 056/141] style --- uart/uart_posix.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 4c9e8b990..fc5eced7f 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -231,7 +231,6 @@ void uart_close(const serial_port sp) { } bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size_t *pszRxLen) { - int res; int byteCount; fd_set rfds; struct timeval tv; @@ -244,7 +243,7 @@ bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size FD_ZERO(&rfds); FD_SET(((serial_port_unix *)sp)->fd, &rfds); tv = timeout; - res = select(((serial_port_unix *)sp)->fd + 1, &rfds, NULL, NULL, &tv); + int res = select(((serial_port_unix *)sp)->fd + 1, &rfds, NULL, NULL, &tv); // Read error if (res < 0) { @@ -290,7 +289,6 @@ bool uart_receive(const serial_port sp, uint8_t *pbtRx, size_t pszMaxRxLen, size } bool uart_send(const serial_port sp, const uint8_t *pbtTx, const size_t len) { - int32_t res; size_t pos = 0; fd_set rfds; struct timeval tv; @@ -300,7 +298,7 @@ bool uart_send(const serial_port sp, const uint8_t *pbtTx, const size_t len) { FD_ZERO(&rfds); FD_SET(((serial_port_unix *)sp)->fd, &rfds); tv = timeout; - res = select(((serial_port_unix *)sp)->fd + 1, NULL, &rfds, NULL, &tv); + int res = select(((serial_port_unix *)sp)->fd + 1, NULL, &rfds, NULL, &tv); // Write error if (res < 0) { From 366c1ec901a021b1c3ad10428406585aae0e6bf8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 00:07:48 +0200 Subject: [PATCH 057/141] style --- client/mifare/mifarehost.c | 53 ++++++++++++++------------------------ client/mifare/mifarehost.h | 2 +- tools/nonce2key/crapto1.c | 35 ++++++++++++------------- tools/nonce2key/crypto1.c | 2 +- 4 files changed, 37 insertions(+), 55 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 905fdcc82..de2ac2cfa 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -15,8 +15,6 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint32_t nt = 0, nr = 0, ar = 0; uint64_t par_list = 0, ks_list = 0; uint64_t *keylist = NULL, *last_keylist = NULL; - uint32_t keycount = 0; - int16_t isOK = 0; UsbCommand c = {CMD_READER_MIFARE, {true, blockno, key_type}}; @@ -49,7 +47,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - isOK = resp.arg[0]; + int16_t isOK = resp.arg[0]; if (isOK < 0) return isOK; @@ -69,7 +67,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } c.arg[0] = false; - keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); + uint32_t keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); if (keycount == 0) { PrintAndLogEx(FAILED, "key not found (lfsr_common_prefix list is null). Nt=%08x", nt); @@ -502,14 +500,13 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { - uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params, blockNo, 0}}; memcpy(c.d.asBytes, data, 16); clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; + uint8_t isOK = resp.arg[0] & 0xff; if (uid != NULL) memcpy(uid, resp.d.asBytes, 4); if (!isOK) @@ -522,13 +519,12 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { } int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { - uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; + uint8_t isOK = resp.arg[0] & 0xff; if (!isOK) return 2; memcpy(data, resp.d.asBytes, 16); @@ -555,15 +551,8 @@ static uint8_t traceCurKey = 0; struct Crypto1State *traceCrypto1 = NULL; struct Crypto1State *revstate = NULL; -uint64_t key = 0; -uint32_t ks2 = 0; -uint32_t ks3 = 0; uint32_t cuid = 0; // uid part used for crypto1. -uint32_t nt = 0; // tag challenge -uint32_t nr_enc = 0; // encrypted reader challenge -uint32_t ar_enc = 0; // encrypted reader response -uint32_t at_enc = 0; // encrypted tag response int isTraceCardEmpty(void) { return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0)); @@ -605,18 +594,14 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL) { PrintAndLogEx(FAILED, "No trace file found or reading error."); - if (f) { - fclose(f); - } + fclose(f); return 2; } if (strlen(buf) < 32) { if (feof(f)) break; PrintAndLogEx(FAILED, "File content error. Block data must include 32 HEX symbols"); - if (f) { - fclose(f); - } + fclose(f); return 2; } for (i = 0; i < 32; i += 2) { @@ -628,9 +613,7 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { blockNum++; } - if (f) { - fclose(f); - } + fclose(f); return 0; } @@ -677,14 +660,11 @@ int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool } void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted) { - uint8_t bt = 0; - int i; - if (len != 1) { - for (i = 0; i < len; i++) + for (int i = 0; i < len; i++) data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i]; } else { - bt = 0; + uint8_t bt = 0; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2; @@ -694,7 +674,10 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool i } int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { - + uint32_t nt = 0; // tag challenge + uint32_t nr_enc = 0; // encrypted reader challenge + uint32_t ar_enc = 0; // encrypted reader response + uint32_t at_enc = 0; // encrypted tag response if (traceState == TRACE_ERROR) return 1; @@ -813,11 +796,13 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { case TRACE_AUTH_OK: if (len == 4) { traceState = TRACE_IDLE; + // encrypted tag response at_enc = bytes_to_num(data, 4); // mfkey64 recover key. - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); + uint64_t key = 0; + uint32_t ks2 = ar_enc ^ prng_successor(nt, 64); + uint32_t ks3 = at_enc ^ prng_successor(nt, 96); revstate = lfsr_recovery64(ks2, ks3); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); @@ -865,8 +850,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len) { PrintAndLogEx(SUCCESS, "\nencrypted data: [%s]", sprint_hex(data, len)); struct Crypto1State *s; - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); + uint32_t ks2 = ar_enc ^ prng_successor(nt, 64); + uint32_t ks3 = at_enc ^ prng_successor(nt, 96); s = lfsr_recovery64(ks2, ks3); mf_crypto1_decrypt(s, data, len, false); PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len)); diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 626d2cd07..7481647ad 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -70,7 +70,7 @@ typedef struct { extern char logHexFileName[FILE_PATH_SIZE]; extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); -extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *ResultKeys, bool calibrate); +extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKeys, bool calibrate); extern int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); extern int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c index 559e12872..9026a57bb 100644 --- a/tools/nonce2key/crapto1.c +++ b/tools/nonce2key/crapto1.c @@ -77,10 +77,9 @@ static void bucket_sort_intersect(uint32_t *const estart, uint32_t *const estop, // write back intersecting buckets as sorted list. // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; for (uint32_t i = 0; i < 2; i++) { p1 = start[i]; - nonempty_bucket = 0; + uint32_t nonempty_bucket = 0; for (uint32_t j = 0x00; j <= 0xff; j++) { if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only bucket_info->bucket_info[i][nonempty_bucket].head = p1; @@ -146,13 +145,12 @@ static struct Crypto1State * recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) { - uint32_t *o, *e; bucket_info_t bucket_info; if (rem == -1) { - for (e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for (o = o_head; o <= o_tail; ++o, ++sl) { + for (uint32_t *e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ (!!(in & 4)); + for (uint32_t *o = o_head; o <= o_tail; ++o, ++sl) { sl->even = *o; sl->odd = *e ^ parity(*o & LF_POLY_ODD); sl[1].odd = sl[1].even = 0; @@ -193,12 +191,11 @@ struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { struct Crypto1State *statelist; uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; // split the keystream into an odd and even part - for (i = 31; i >= 0; i -= 2) + for (int i = 31; i >= 0; i -= 2) oks = oks << 1 | BEBIT(ks2, i); - for (i = 30; i >= 0; i -= 2) + for (int i = 30; i >= 0; i -= 2) eks = eks << 1 | BEBIT(ks2, i); odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); @@ -225,7 +222,7 @@ struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { } // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for (i = 1 << 20; i >= 0; --i) { + for (int i = 1 << 20; i >= 0; --i) { if (filter(i) == (oks & 1)) *++odd_tail = i; if (filter(i) == (eks & 1)) @@ -233,7 +230,7 @@ struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { } // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for (i = 0; i < 4; i++) { + for (uint8_t i = 0; i < 4; i++) { extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); } @@ -362,7 +359,7 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) { out ^= LF_POLY_EVEN & (s->even >>= 1); out ^= LF_POLY_ODD & s->odd; out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; + out ^= (ret = filter(s->odd)) & (!!fb); s->even |= parity(out) << 23; return ret; @@ -498,21 +495,21 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { * helper function which eliminates possible secret states using parity bits */ static struct Crypto1State *check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State *sl) { - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + uint32_t good = 1; - for (c = 0; good && c < 8; ++c) { + for (uint32_t c = 0; good && c < 8; ++c) { sl->odd = odd ^ fastfwd[1][c]; sl->even = even ^ fastfwd[0][c]; lfsr_rollback_bit(sl, 0, 0); lfsr_rollback_bit(sl, 0, 0); - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + uint32_t ks3 = lfsr_rollback_bit(sl, 0, 0); + uint32_t ks2 = lfsr_rollback_word(sl, 0, 0); + uint32_t ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; + uint32_t nr = ks1 ^ (prefix | c << 5); + uint32_t rr = ks2 ^ rresp; good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); diff --git a/tools/nonce2key/crypto1.c b/tools/nonce2key/crypto1.c index cdb0ffc14..0c3f97b88 100644 --- a/tools/nonce2key/crypto1.c +++ b/tools/nonce2key/crypto1.c @@ -49,7 +49,7 @@ uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) { uint32_t tmp; uint8_t ret = filter(s->odd); - feedin = ret & !!is_encrypted; + feedin = ret & (!!is_encrypted); feedin ^= !!in; feedin ^= LF_POLY_ODD & s->odd; feedin ^= LF_POLY_EVEN & s->even; From 38f6fd037f7246b6ba5828c1c83a98e8342b912f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 00:14:07 +0200 Subject: [PATCH 058/141] style --- common/wiegand.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/wiegand.c b/common/wiegand.c index 3e90c61b6..cd4fb3eb6 100644 --- a/common/wiegand.c +++ b/common/wiegand.c @@ -72,20 +72,20 @@ size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, // Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added /* * @brief addParity -* @param bits pointer to the source bitstream of binary values +* @param src pointer to the source bitstream of binary values * @param dest pointer to the destination where parities together with bits are added. * @param sourceLen number of * @param pLen length bits to be checked * @param pType EVEN|ODD|2 (always 1's)|3 (always 0's) * @return */ -size_t addParity(uint8_t *bits, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { +size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { uint32_t parityWd = 0; size_t j = 0, bitCnt = 0; for (int word = 0; word < sourceLen; word += pLen - 1) { for (int bit = 0; bit < pLen - 1; ++bit) { - parityWd = (parityWd << 1) | bits[word + bit]; - dest[j++] = (bits[word + bit]); + parityWd = (parityWd << 1) | src[word + bit]; + dest[j++] = (src[word + bit]); } // if parity fails then return 0 From 682f23440deae5306503de929b5549c116a4d1e6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 00:23:01 +0200 Subject: [PATCH 059/141] style --- common/lfdemod.c | 26 +++++++++++++------------- common/lfdemod.h | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index a0dea9d9d..17e38caa7 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -521,12 +521,12 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo int foo = getClosestClock(minClk); if (foo > 0) { - for (uint8_t i = 0; i < 10; i++) { - if (tmpclk[i][0] == foo) { - tmpclk[i][1]++; + for (uint8_t j = 0; j < 10; j++) { + if (tmpclk[j][0] == foo) { + tmpclk[j][1]++; - if (tmpclk[i][2] == 0) { - tmpclk[i][2] = shortestWaveIdx; + if (tmpclk[j][2] == 0) { + tmpclk[j][2] = shortestWaveIdx; } break; } @@ -536,18 +536,18 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo // find the clock with most hits and it the first index it was encountered. int max = 0; - for (uint8_t i = 0; i < 10; i++) { + for (uint8_t j = 0; j < 10; j++) { if (g_debugMode == 2) { prnt("DEBUG, ASK, clocks %u | hits %u | idx %u" - , tmpclk[i][0] - , tmpclk[i][1] - , tmpclk[i][2] + , tmpclk[j][0] + , tmpclk[j][1] + , tmpclk[j][2] ); } - if (max < tmpclk[i][1]) { - *clock = tmpclk[i][0]; - shortestWaveIdx = tmpclk[i][2]; - max = tmpclk[i][1]; + if (max < tmpclk[j][1]) { + *clock = tmpclk[j][0]; + shortestWaveIdx = tmpclk[j][2]; + max = tmpclk[j][1]; } } diff --git a/common/lfdemod.h b/common/lfdemod.h index 6256aa0bc..9a807a02c 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -79,7 +79,7 @@ extern size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8 //tag specific extern int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx); -extern int Em410xDecode(uint8_t *dest, size_t *size, size_t *startIdx, uint32_t *hi, uint64_t *lo); +extern int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, uint64_t *lo); extern int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); extern int detectIdteck(uint8_t *dest, size_t *size); extern int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); From e24a0cfe17274ae33e0dd6364eb15fa95dfc6739 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 6 Apr 2019 00:32:11 +0200 Subject: [PATCH 060/141] 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 59d40068e2919201cd8b436e5f6a4fba435aa3f3 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 00:38:22 +0200 Subject: [PATCH 061/141] style --- client/cmdcrc.h | 8 +-- client/cmddata.h | 2 +- client/cmdflashmem.h | 12 ++-- client/cmdhf.h | 12 ++-- client/cmdhf14a.h | 34 +++++------ client/cmdhf14b.h | 26 ++++---- client/cmdhf15.h | 56 ++++++++--------- client/cmdhfepa.h | 6 +- client/cmdhffelica.h | 22 +++---- client/cmdhffido.h | 2 +- client/cmdhficlass.h | 46 +++++++------- client/cmdhflegic.h | 26 ++++---- client/cmdhflist.h | 43 ++++++------- client/cmdhfmf.h | 68 ++++++++++----------- client/cmdhfmfdesfire.h | 1 - client/cmdhfmfhard.h | 4 +- client/cmdhfmfp.h | 2 +- client/cmdhfmfu.h | 50 +++++++-------- client/cmdhftopaz.h | 10 +-- client/cmdlf.h | 40 ++++++------ client/cmdlfawid.h | 22 +++---- client/cmdlfcotag.h | 8 +-- client/cmdlfem4x.h | 62 +++++++++---------- client/cmdlffdx.h | 18 +++--- client/cmdlfguard.h | 14 ++--- client/cmdlfhid.h | 26 ++++---- client/cmdlfhitag.h | 18 +++--- client/cmdlfindala.h | 24 ++++---- client/cmdlfio.h | 16 ++--- client/cmdlfjablotron.h | 22 +++---- client/cmdlfkeri.h | 16 ++--- client/cmdlfnedap.h | 20 +++--- client/cmdlfnexwatch.h | 8 +-- client/cmdlfnoralsy.h | 18 +++--- client/cmdlfpac.h | 8 +-- client/cmdlfparadox.h | 12 ++-- client/cmdlfpresco.h | 16 ++--- client/cmdlfpyramid.h | 16 ++--- client/cmdlfsecurakey.h | 10 +-- client/cmdlfviking.h | 16 ++--- client/cmdlfvisa2000.h | 20 +++--- client/cmdmain.h | 4 +- client/cmdscript.h | 6 +- client/cmdsmartcard.h | 22 +++---- client/cmdtrace.h | 14 ++--- client/comms.h | 2 +- client/crypto/asn1utils.h | 4 +- client/proxgui.h | 8 +-- client/scandir.h | 4 +- client/ui.h | 8 +-- client/util.h | 124 +++++++++++++++++++------------------- 51 files changed, 528 insertions(+), 528 deletions(-) diff --git a/client/cmdcrc.h b/client/cmdcrc.h index ba9540c45..f52727c2c 100644 --- a/client/cmdcrc.h +++ b/client/cmdcrc.h @@ -28,9 +28,9 @@ #include "ui.h" #include "util.h" -extern int CmdCrc(const char *Cmd); +int CmdCrc(const char *Cmd); -extern int CmdrevengSearch(const char *Cmd); -extern int GetModels(char *Models[], int *count, uint8_t *width); -extern int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result); +int CmdrevengSearch(const char *Cmd); +int GetModels(char *Models[], int *count, uint8_t *width); +int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result); #endif diff --git a/client/cmddata.h b/client/cmddata.h index 1091c48c2..5f0fe80e0 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -84,7 +84,7 @@ int NRZrawDemod(const char *Cmd, bool verbose); int getSamples(int n, bool silent); void setClockGrid(int clk, int offset); int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); -extern int AskEdgeDetect(const int *in, int *out, int len, int threshold); +int AskEdgeDetect(const int *in, int *out, int len, int threshold); int CmdDataIIR(const char *Cmd); diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 9f946908c..1cf06c1bc 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -33,13 +33,13 @@ typedef enum { DICTIONARY_ICLASS } Dictionary_t; -extern int CmdFlashMem(const char *Cmd); +int CmdFlashMem(const char *Cmd); -extern int CmdFlashMemRead(const char *Cmd); -extern int CmdFlashMemLoad(const char *Cmd); -extern int CmdFlashMemSave(const char *Cmd); -extern int CmdFlashMemWipe(const char *Cmd); -extern int CmdFlashMemInfo(const char *Cmd); +int CmdFlashMemRead(const char *Cmd); +int CmdFlashMemLoad(const char *Cmd); +int CmdFlashMemSave(const char *Cmd); +int CmdFlashMemWipe(const char *Cmd); +int CmdFlashMemInfo(const char *Cmd); #endif #endif diff --git a/client/cmdhf.h b/client/cmdhf.h index 9e41f2138..3237e1df6 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -33,11 +33,11 @@ #include "cmdhffido.h" // FIDO authenticators #include "cmdtrace.h" // trace list -extern int CmdHF(const char *Cmd); -extern int CmdHFTune(const char *Cmd); -extern int CmdHFSearch(const char *Cmd); -extern int CmdHFSniff(const char *Cmd); +int CmdHF(const char *Cmd); +int CmdHFTune(const char *Cmd); +int CmdHFSearch(const char *Cmd); +int CmdHFSniff(const char *Cmd); -extern int usage_hf_search(); -extern int usage_hf_sniff(); +int usage_hf_search(); +int usage_hf_sniff(); #endif diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 6020b6f8b..e218a398f 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -39,23 +39,23 @@ typedef struct { char *desc; } manufactureName; -extern int CmdHF14A(const char *Cmd); -extern int CmdHF14AList(const char *Cmd); -extern int CmdHF14AReader(const char *Cmd); -extern int CmdHF14AInfo(const char *Cmd); -extern int CmdHF14ASim(const char *Cmd); -extern int CmdHF14ASniff(const char *Cmd); -extern int CmdHF14ACmdRaw(const char *Cmd); -extern int CmdHF14ACUIDs(const char *Cmd); -extern int CmdHF14AAntiFuzz(const char *Cmd); +int CmdHF14A(const char *Cmd); +int CmdHF14AList(const char *Cmd); +int CmdHF14AReader(const char *Cmd); +int CmdHF14AInfo(const char *Cmd); +int CmdHF14ASim(const char *Cmd); +int CmdHF14ASniff(const char *Cmd); +int CmdHF14ACmdRaw(const char *Cmd); +int CmdHF14ACUIDs(const char *Cmd); +int CmdHF14AAntiFuzz(const char *Cmd); -extern char *getTagInfo(uint8_t uid); -extern int Hf14443_4aGetCardData(iso14a_card_select_t *card); -extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -extern int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +char *getTagInfo(uint8_t uid); +int Hf14443_4aGetCardData(iso14a_card_select_t *card); +int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -extern int usage_hf_14a_sim(void); -extern int usage_hf_14a_sniff(void); -extern int usage_hf_14a_raw(void); -extern int usage_hf_14a_antifuzz(void); +int usage_hf_14a_sim(void); +int usage_hf_14a_sniff(void); +int usage_hf_14a_raw(void); +int usage_hf_14a_antifuzz(void); #endif diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 56114af94..f2d78778c 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -37,23 +37,23 @@ int usage_hf_14b_sim(void); int usage_hf_14b_read_srx(void); int usage_hf_14b_write_srx(void); -extern int CmdHF14B(const char *Cmd); -extern int CmdHF14BList(const char *Cmd); -extern int CmdHF14BInfo(const char *Cmd); -extern int CmdHF14BSim(const char *Cmd); -extern int CmdHF14BSniff(const char *Cmd); -extern int CmdHF14BWrite(const char *cmd); -extern int CmdHF14BReader(const char *Cmd); +int CmdHF14B(const char *Cmd); +int CmdHF14BList(const char *Cmd); +int CmdHF14BInfo(const char *Cmd); +int CmdHF14BSim(const char *Cmd); +int CmdHF14BSniff(const char *Cmd); +int CmdHF14BWrite(const char *cmd); +int CmdHF14BReader(const char *Cmd); -extern int CmdHF14BDump(const char *Cmd); +int CmdHF14BDump(const char *Cmd); -extern bool HF14BInfo(bool verbose); -extern bool HF14BReader(bool verbose); -extern int CmdHF14BCmdRaw(const char *Cmd); +bool HF14BInfo(bool verbose); +bool HF14BReader(bool verbose); +int CmdHF14BCmdRaw(const char *Cmd); // SRi ST Microelectronics read/write -extern int CmdHF14BReadSri(const char *Cmd); -extern int CmdHF14BWriteSri(const char *Cmd); +int CmdHF14BReadSri(const char *Cmd); +int CmdHF14BWriteSri(const char *Cmd); bool waitCmd14b(bool verbose); #endif diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 942fd2952..141163547 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -28,38 +28,38 @@ int CmdHF15(const char *Cmd); -extern int HF15Reader(const char *Cmd, bool verbose); +int HF15Reader(const char *Cmd, bool verbose); -extern int CmdHF15Demod(const char *Cmd); -extern int CmdHF15Samples(const char *Cmd); -extern int CmdHF15Info(const char *Cmd); -extern int CmdHF15Record(const char *Cmd); -extern int CmdHF15Reader(const char *Cmd); -extern int CmdHF15Sim(const char *Cmd); -extern int CmdHF15Afi(const char *Cmd); -extern int CmdHF15Dump(const char *Cmd); -extern int CmdHF15Raw(const char *cmd); -extern int CmdHF15Readmulti(const char *Cmd); -extern int CmdHF15Read(const char *Cmd); -extern int CmdHF15Write(const char *Cmd); +int CmdHF15Demod(const char *Cmd); +int CmdHF15Samples(const char *Cmd); +int CmdHF15Info(const char *Cmd); +int CmdHF15Record(const char *Cmd); +int CmdHF15Reader(const char *Cmd); +int CmdHF15Sim(const char *Cmd); +int CmdHF15Afi(const char *Cmd); +int CmdHF15Dump(const char *Cmd); +int CmdHF15Raw(const char *cmd); +int CmdHF15Readmulti(const char *Cmd); +int CmdHF15Read(const char *Cmd); +int CmdHF15Write(const char *Cmd); -extern int CmdHF15Help(const char *Cmd); +int CmdHF15Help(const char *Cmd); // usages -extern int usage_15_demod(void); -extern int usage_15_samples(void); -extern int usage_15_info(void); -extern int usage_15_record(void); -extern int usage_15_reader(void); -extern int usage_15_sim(void); -extern int usage_15_findafi(void); -extern int usage_15_dump(void); -extern int usage_15_restore(void); -extern int usage_15_raw(void); +int usage_15_demod(void); +int usage_15_samples(void); +int usage_15_info(void); +int usage_15_record(void); +int usage_15_reader(void); +int usage_15_sim(void); +int usage_15_findafi(void); +int usage_15_dump(void); +int usage_15_restore(void); +int usage_15_raw(void); -extern int usage_15_read(void); -extern int usage_15_write(void); -extern int usage_15_readmulti(void); +int usage_15_read(void); +int usage_15_write(void); +int usage_15_readmulti(void); -extern int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd); +int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd); #endif diff --git a/client/cmdhfepa.h b/client/cmdhfepa.h index 914ce4c5d..c526c6eb0 100644 --- a/client/cmdhfepa.h +++ b/client/cmdhfepa.h @@ -25,8 +25,8 @@ #include "util_posix.h" -extern int CmdHFEPA(const char *Cmd); -extern int CmdHFEPACollectPACENonces(const char *Cmd); -extern int CmdHFEPAPACEReplay(const char *Cmd); +int CmdHFEPA(const char *Cmd); +int CmdHFEPACollectPACENonces(const char *Cmd); +int CmdHFEPAPACEReplay(const char *Cmd); #endif // CMDHFEPA_H__ diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index 80a09f7d3..6eeb5b44f 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -26,21 +26,21 @@ #include "cmdhf.h" // list cmd #include "mifare.h" // felica_card_select_t struct -extern int CmdHFFelica(const char *Cmd); -extern int CmdHFFelicaList(const char *Cmd); -extern int CmdHFFelicaReader(const char *Cmd); -extern int CmdHFFelicaSim(const char *Cmd); -extern int CmdHFFelicaSniff(const char *Cmd); -extern int CmdHFFelicaCmdRaw(const char *Cmd); +int CmdHFFelica(const char *Cmd); +int CmdHFFelicaList(const char *Cmd); +int CmdHFFelicaReader(const char *Cmd); +int CmdHFFelicaSim(const char *Cmd); +int CmdHFFelicaSniff(const char *Cmd); +int CmdHFFelicaCmdRaw(const char *Cmd); -extern int usage_hf_felica_sim(void); -extern int usage_hf_felica_sniff(void); -extern int usage_hf_fFelica_raw(void); +int usage_hf_felica_sim(void); +int usage_hf_felica_sniff(void); +int usage_hf_fFelica_raw(void); void waitCmdFelica(uint8_t iSelect); //temp -extern int CmdHFFelicaSimLite(const char *Cmd); -extern int CmdHFFelicaDumpLite(const char *Cmd); +int CmdHFFelicaSimLite(const char *Cmd); +int CmdHFFelicaDumpLite(const char *Cmd); #endif diff --git a/client/cmdhffido.h b/client/cmdhffido.h index 96f9153ed..b54f53118 100644 --- a/client/cmdhffido.h +++ b/client/cmdhffido.h @@ -21,7 +21,7 @@ #ifndef CMDHFFIDO_H__ #define CMDHFFIDO_H__ -extern int CmdHFFido(const char *Cmd); +int CmdHFFido(const char *Cmd); #endif diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index dff0d0b24..01dfd0076 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -52,29 +52,29 @@ typedef struct iclass_prekey { int CmdHFiClass(const char *Cmd); -extern int CmdHFiClassCalcNewKey(const char *Cmd); -extern int CmdHFiClassCloneTag(const char *Cmd); -extern int CmdHFiClassDecrypt(const char *Cmd); -extern int CmdHFiClassEncryptBlk(const char *Cmd); -extern int CmdHFiClassELoad(const char *Cmd); -extern int CmdHFiClassList(const char *Cmd); -extern int HFiClassReader(const char *Cmd, bool loop, bool verbose); -extern int CmdHFiClassReader(const char *Cmd); -extern int CmdHFiClassReader_Dump(const char *Cmd); -extern int CmdHFiClassReader_Replay(const char *Cmd); -extern int CmdHFiClassReadKeyFile(const char *filename); -extern int CmdHFiClassReadTagFile(const char *Cmd); -extern int CmdHFiClass_ReadBlock(const char *Cmd); -extern int CmdHFiClass_TestMac(const char *Cmd); -extern int CmdHFiClassManageKeys(const char *Cmd); -extern int CmdHFiClass_loclass(const char *Cmd); -extern int CmdHFiClassSniff(const char *Cmd); -extern int CmdHFiClassSim(const char *Cmd); -extern int CmdHFiClassWriteKeyFile(const char *Cmd); -extern int CmdHFiClass_WriteBlock(const char *Cmd); -extern int CmdHFiClassCheckKeys(const char *Cmd); -extern int CmdHFiClassLookUp(const char *Cmd); -extern int CmdHFiClassPermuteKey(const char *Cmd); +int CmdHFiClassCalcNewKey(const char *Cmd); +int CmdHFiClassCloneTag(const char *Cmd); +int CmdHFiClassDecrypt(const char *Cmd); +int CmdHFiClassEncryptBlk(const char *Cmd); +int CmdHFiClassELoad(const char *Cmd); +int CmdHFiClassList(const char *Cmd); +int HFiClassReader(const char *Cmd, bool loop, bool verbose); +int CmdHFiClassReader(const char *Cmd); +int CmdHFiClassReader_Dump(const char *Cmd); +int CmdHFiClassReader_Replay(const char *Cmd); +int CmdHFiClassReadKeyFile(const char *filename); +int CmdHFiClassReadTagFile(const char *Cmd); +int CmdHFiClass_ReadBlock(const char *Cmd); +int CmdHFiClass_TestMac(const char *Cmd); +int CmdHFiClassManageKeys(const char *Cmd); +int CmdHFiClass_loclass(const char *Cmd); +int CmdHFiClassSniff(const char *Cmd); +int CmdHFiClassSim(const char *Cmd); +int CmdHFiClassWriteKeyFile(const char *Cmd); +int CmdHFiClass_WriteBlock(const char *Cmd); +int CmdHFiClassCheckKeys(const char *Cmd); +int CmdHFiClassLookUp(const char *Cmd); +int CmdHFiClassPermuteKey(const char *Cmd); void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t endblock, size_t filesize); void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite); diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h index 6ee08253c..9bd8d98ac 100644 --- a/client/cmdhflegic.h +++ b/client/cmdhflegic.h @@ -26,19 +26,19 @@ int CmdHFLegic(const char *Cmd); -extern int CmdLegicInfo(const char *Cmd); -extern int CmdLegicRdmem(const char *Cmd); -extern int CmdLegicLoad(const char *Cmd); -extern int CmdLegicRfSim(const char *Cmd); -extern int CmdLegicRfWrite(const char *Cmd); -extern int CmdLegicCalcCrc(const char *Cmd); -extern int CmdLegicDump(const char *Cmd); -extern int CmdLegicRestore(const char *Cmd); -extern int CmdLegicReader(const char *Cmd); -extern int CmdLegicELoad(const char *Cmd); -extern int CmdLegicESave(const char *Cmd); -extern int CmdLegicList(const char *Cmd); -extern int CmdLegicWipe(const char *Cmd); +int CmdLegicInfo(const char *Cmd); +int CmdLegicRdmem(const char *Cmd); +int CmdLegicLoad(const char *Cmd); +int CmdLegicRfSim(const char *Cmd); +int CmdLegicRfWrite(const char *Cmd); +int CmdLegicCalcCrc(const char *Cmd); +int CmdLegicDump(const char *Cmd); +int CmdLegicRestore(const char *Cmd); +int CmdLegicReader(const char *Cmd); +int CmdLegicELoad(const char *Cmd); +int CmdLegicESave(const char *Cmd); +int CmdLegicList(const char *Cmd); +int CmdLegicWipe(const char *Cmd); int HFLegicReader(const char *Cmd, bool verbose); int legic_print_type(uint32_t tagtype, uint8_t spaces); diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 105328b9b..35a5493ff 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -51,31 +51,32 @@ typedef struct { uint32_t ks2; // ar ^ ar_enc uint32_t ks3; // at ^ at_enc } TAuthData; -extern void ClearAuthData(); -extern uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n); -extern uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n); -extern uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len); -extern uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n); -extern uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n); +void ClearAuthData(); + +uint8_t iso14443A_CRC_check(bool isResponse, uint8_t *d, uint8_t n); +uint8_t iso14443B_CRC_check(uint8_t *d, uint8_t n); +uint8_t mifare_CRC_check(bool isResponse, uint8_t *data, uint8_t len); +uint8_t iso15693_CRC_check(uint8_t *d, uint8_t n); +uint8_t iclass_CRC_check(bool isResponse, uint8_t *d, uint8_t n); int applyIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); -extern void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse); +void annotateIclass(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateIso15693(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateTopaz(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateLegic(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateFelica(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateIso7816(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateIso14443b(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateIso14443a(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateMfDesfire(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateMifare(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, uint8_t paritysize, bool isResponse); -extern bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); -extern bool NTParityChk(TAuthData *ad, uint32_t ntx); -extern bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); -extern bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc); -extern uint64_t GetCrypto1ProbableKey(TAuthData *ad); +bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen); +bool NTParityChk(TAuthData *ad, uint32_t ntx); +bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity); +bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t *parity_enc); +uint64_t GetCrypto1ProbableKey(TAuthData *ad); #endif // CMDHFLIST diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 699aaa33e..0e471580b 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -33,41 +33,41 @@ #include "cliparser/cliparser.h" // argtable #include "hardnested/hardnested_bf_core.h" // SetSIMDInstr -extern int CmdHFMF(const char *Cmd); +int CmdHFMF(const char *Cmd); -extern int CmdHF14AMfList(const char *Cmd); -extern int CmdHF14AMfDbg(const char *Cmd); -extern int CmdHF14AMfRdBl(const char *Cmd); -extern int CmdHF14AMfURdBl(const char *Cmd); -extern int CmdHF14AMfRdSc(const char *Cmd); -extern int CmdHF14SMfURdCard(const char *Cmd); -extern int CmdHF14AMfDump(const char *Cmd); -extern int CmdHF14AMfRestore(const char *Cmd); -extern int CmdHF14AMfWrBl(const char *Cmd); -extern int CmdHF14AMfUWrBl(const char *Cmd); -extern int CmdHF14AMfChk(const char *Cmd); -extern int CmdHF14AMfDarkside(const char *Cmd); -extern int CmdHF14AMfNested(const char *Cmd); -extern int CmdHF14AMfNestedHard(const char *Cmd); -//extern int CmdHF14AMfSniff(const char* Cmd); -extern int CmdHF14AMf1kSim(const char *Cmd); -extern int CmdHF14AMfKeyBrute(const char *Cmd); -extern int CmdHF14AMfEClear(const char *Cmd); -extern int CmdHF14AMfEGet(const char *Cmd); -extern int CmdHF14AMfESet(const char *Cmd); -extern int CmdHF14AMfELoad(const char *Cmd); -extern int CmdHF14AMfESave(const char *Cmd); -extern int CmdHF14AMfECFill(const char *Cmd); -extern int CmdHF14AMfEKeyPrn(const char *Cmd); -extern int CmdHF14AMfCSetUID(const char *Cmd); -extern int CmdHF14AMfCSetBlk(const char *Cmd); -extern int CmdHF14AMfCGetBlk(const char *Cmd); -extern int CmdHF14AMfCGetSc(const char *Cmd); -extern int CmdHF14AMfCLoad(const char *Cmd); -extern int CmdHF14AMfCSave(const char *Cmd); -extern int CmdHf14MfDecryptBytes(const char *Cmd); -extern int CmdHf14AMfSetMod(const char *Cmd); -extern int CmdHf14AMfNack(const char *Cmd); +int CmdHF14AMfList(const char *Cmd); +int CmdHF14AMfDbg(const char *Cmd); +int CmdHF14AMfRdBl(const char *Cmd); +int CmdHF14AMfURdBl(const char *Cmd); +int CmdHF14AMfRdSc(const char *Cmd); +int CmdHF14SMfURdCard(const char *Cmd); +int CmdHF14AMfDump(const char *Cmd); +int CmdHF14AMfRestore(const char *Cmd); +int CmdHF14AMfWrBl(const char *Cmd); +int CmdHF14AMfUWrBl(const char *Cmd); +int CmdHF14AMfChk(const char *Cmd); +int CmdHF14AMfDarkside(const char *Cmd); +int CmdHF14AMfNested(const char *Cmd); +int CmdHF14AMfNestedHard(const char *Cmd); +//int CmdHF14AMfSniff(const char* Cmd); +int CmdHF14AMf1kSim(const char *Cmd); +int CmdHF14AMfKeyBrute(const char *Cmd); +int CmdHF14AMfEClear(const char *Cmd); +int CmdHF14AMfEGet(const char *Cmd); +int CmdHF14AMfESet(const char *Cmd); +int CmdHF14AMfELoad(const char *Cmd); +int CmdHF14AMfESave(const char *Cmd); +int CmdHF14AMfECFill(const char *Cmd); +int CmdHF14AMfEKeyPrn(const char *Cmd); +int CmdHF14AMfCSetUID(const char *Cmd); +int CmdHF14AMfCSetBlk(const char *Cmd); +int CmdHF14AMfCGetBlk(const char *Cmd); +int CmdHF14AMfCGetSc(const char *Cmd); +int CmdHF14AMfCLoad(const char *Cmd); +int CmdHF14AMfCSave(const char *Cmd); +int CmdHf14MfDecryptBytes(const char *Cmd); +int CmdHf14AMfSetMod(const char *Cmd); +int CmdHf14AMfNack(const char *Cmd); void showSectorTable(void); void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); diff --git a/client/cmdhfmfdesfire.h b/client/cmdhfmfdesfire.h index cc5481b0e..46737c684 100644 --- a/client/cmdhfmfdesfire.h +++ b/client/cmdhfmfdesfire.h @@ -1,5 +1,4 @@ -static int CmdHelp(const char *Cmd); int CmdHF14AMfDESAuth(const char *Cmd); int CmdHFMFDesfire(const char *Cmd); int CmdHelp(const char *Cmd); diff --git a/client/cmdhfmfhard.h b/client/cmdhfmfhard.h index e39358c7f..7d3e4fa0b 100644 --- a/client/cmdhfmfhard.h +++ b/client/cmdhfmfhard.h @@ -41,8 +41,8 @@ typedef struct noncelist { noncelistentry_t *first; } noncelist_t; -extern int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename); -extern void hardnested_print_progress(uint32_t nonces, char *activity, float brute_force, uint64_t min_diff_print_time); +int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename); +void hardnested_print_progress(uint32_t nonces, char *activity, float brute_force, uint64_t min_diff_print_time); #endif diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index ed9d36b79..76917315b 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -12,7 +12,7 @@ #include "mifare/mifaredefault.h" -extern int CmdHFMFP(const char *Cmd); +int CmdHFMFP(const char *Cmd); #endif diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 6be4beb6c..315b4b542 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -25,40 +25,40 @@ typedef struct { uint8_t data[1024]; } mfu_dump_t; -extern int CmdHF14AMfUWrBl(const char *Cmd); -extern int CmdHF14AMfURdBl(const char *Cmd); +int CmdHF14AMfUWrBl(const char *Cmd); +int CmdHF14AMfURdBl(const char *Cmd); //Crypto Cards -extern int CmdHF14AMfucAuth(const char *Cmd); -extern int CmdHF14AMfucSetPwd(const char *Cmd); -extern int CmdHF14AMfucSetUid(const char *Cmd); -extern int CmdHF14AMfuGenDiverseKeys(const char *Cmd); -extern int CmdHF14AMfuPwdGen(const char *Cmd); +int CmdHF14AMfucAuth(const char *Cmd); +int CmdHF14AMfucSetPwd(const char *Cmd); +int CmdHF14AMfucSetUid(const char *Cmd); +int CmdHF14AMfuGenDiverseKeys(const char *Cmd); +int CmdHF14AMfuPwdGen(const char *Cmd); //general stuff -extern int CmdHF14AMfUDump(const char *Cmd); -extern int CmdHF14AMfURestore(const char *Cmd); -extern int CmdHF14AMfUInfo(const char *Cmd); -extern int CmdHF14AMfUeLoad(const char *Cmd); -extern int CmdHF14AMfUSim(const char *Cmd); +int CmdHF14AMfUDump(const char *Cmd); +int CmdHF14AMfURestore(const char *Cmd); +int CmdHF14AMfUInfo(const char *Cmd); +int CmdHF14AMfUeLoad(const char *Cmd); +int CmdHF14AMfUSim(const char *Cmd); -extern uint32_t GetHF14AMfU_Type(void); -extern int ul_print_type(uint32_t tagtype, uint8_t spacer); +uint32_t GetHF14AMfU_Type(void); +int ul_print_type(uint32_t tagtype, uint8_t spacer); void printMFUdump(mfu_dump_t *card); void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage); -extern int usage_hf_mfu_info(void); -extern int usage_hf_mfu_dump(void); -extern int usage_hf_mfu_rdbl(void); -extern int usage_hf_mfu_wrbl(void); -extern int usage_hf_mfu_eload(void); -extern int usage_hf_mfu_sim(void); -extern int usage_hf_mfu_ucauth(void); -extern int usage_hf_mfu_ucsetpwd(void); -extern int usage_hf_mfu_ucsetuid(void); -extern int usage_hf_mfu_gendiverse(void); -extern int usage_hf_mfu_pwdgen(void); +int usage_hf_mfu_info(void); +int usage_hf_mfu_dump(void); +int usage_hf_mfu_rdbl(void); +int usage_hf_mfu_wrbl(void); +int usage_hf_mfu_eload(void); +int usage_hf_mfu_sim(void); +int usage_hf_mfu_ucauth(void); +int usage_hf_mfu_ucsetpwd(void); +int usage_hf_mfu_ucsetuid(void); +int usage_hf_mfu_gendiverse(void); +int usage_hf_mfu_pwdgen(void); int CmdHFMFUltra(const char *Cmd); diff --git a/client/cmdhftopaz.h b/client/cmdhftopaz.h index e6ba1bdcb..551031778 100644 --- a/client/cmdhftopaz.h +++ b/client/cmdhftopaz.h @@ -25,10 +25,10 @@ #include "protocols.h" #include "cmdhf.h" -extern int CmdHFTopaz(const char *Cmd); -extern int CmdHFTopazReader(const char *Cmd); -extern int CmdHFTopazSim(const char *Cmd); -extern int CmdHFTopazCmdRaw(const char *Cmd); -extern int CmdHFTopazList(const char *Cmd); +int CmdHFTopaz(const char *Cmd); +int CmdHFTopazReader(const char *Cmd); +int CmdHFTopazSim(const char *Cmd); +int CmdHFTopazCmdRaw(const char *Cmd); +int CmdHFTopazList(const char *Cmd); #endif diff --git a/client/cmdlf.h b/client/cmdlf.h index ca3de7eb4..bf914d21a 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -55,28 +55,28 @@ int CmdLF(const char *Cmd); -extern int CmdLFSetConfig(const char *Cmd); +int CmdLFSetConfig(const char *Cmd); -extern int CmdLFCommandRead(const char *Cmd); -extern int CmdFlexdemod(const char *Cmd); -extern int CmdLFRead(const char *Cmd); -extern int CmdLFSim(const char *Cmd); -extern int CmdLFaskSim(const char *Cmd); -extern int CmdLFfskSim(const char *Cmd); -extern int CmdLFpskSim(const char *Cmd); -extern int CmdLFSimBidir(const char *Cmd); -extern int CmdLFSniff(const char *Cmd); -extern int CmdVchDemod(const char *Cmd); -extern int CmdLFfind(const char *Cmd); +int CmdLFCommandRead(const char *Cmd); +int CmdFlexdemod(const char *Cmd); +int CmdLFRead(const char *Cmd); +int CmdLFSim(const char *Cmd); +int CmdLFaskSim(const char *Cmd); +int CmdLFfskSim(const char *Cmd); +int CmdLFpskSim(const char *Cmd); +int CmdLFSimBidir(const char *Cmd); +int CmdLFSniff(const char *Cmd); +int CmdVchDemod(const char *Cmd); +int CmdLFfind(const char *Cmd); -extern bool lf_read(bool silent, uint32_t samples); +bool lf_read(bool silent, uint32_t samples); // usages helptext -extern int usage_lf_cmdread(void); -extern int usage_lf_read(void); -extern int usage_lf_sniff(void); -extern int usage_lf_config(void); -extern int usage_lf_simfsk(void); -extern int usage_lf_simask(void); -extern int usage_lf_simpsk(void); +int usage_lf_cmdread(void); +int usage_lf_read(void); +int usage_lf_sniff(void); +int usage_lf_config(void); +int usage_lf_simfsk(void); +int usage_lf_simask(void); +int usage_lf_simpsk(void); #endif diff --git a/client/cmdlfawid.h b/client/cmdlfawid.h index edee0473c..e971225e2 100644 --- a/client/cmdlfawid.h +++ b/client/cmdlfawid.h @@ -24,17 +24,17 @@ #include "util_posix.h" -extern int CmdLFAWID(const char *Cmd); -extern int CmdAWIDDemod(const char *Cmd); -extern int CmdAWIDRead(const char *Cmd); -extern int CmdAWIDSim(const char *Cmd); -extern int CmdAWIDClone(const char *Cmd); -extern int CmdAWIDBrute(const char *Cmd); -extern int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits); +int CmdLFAWID(const char *Cmd); +int CmdAWIDDemod(const char *Cmd); +int CmdAWIDRead(const char *Cmd); +int CmdAWIDSim(const char *Cmd); +int CmdAWIDClone(const char *Cmd); +int CmdAWIDBrute(const char *Cmd); +int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits); -extern int usage_lf_awid_read(void); -extern int usage_lf_awid_sim(void); -extern int usage_lf_awid_clone(void); -extern int usage_lf_awid_brute(void); +int usage_lf_awid_read(void); +int usage_lf_awid_sim(void); +int usage_lf_awid_clone(void); +int usage_lf_awid_brute(void); #endif diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index b774b12a8..7b0922019 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -23,9 +23,9 @@ #define COTAG_BITS 264 #endif -extern int CmdLFCOTAG(const char *Cmd); -extern int CmdCOTAGRead(const char *Cmd); -extern int CmdCOTAGDemod(const char *Cmd); +int CmdLFCOTAG(const char *Cmd); +int CmdCOTAGRead(const char *Cmd); +int CmdCOTAGDemod(const char *Cmd); -extern int usage_lf_cotag_read(void); +int usage_lf_cotag_read(void); #endif diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index d01dedc57..08670a4b3 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -25,44 +25,44 @@ #include "cmdlf.h" #include "lfdemod.h" -extern int CmdLFEM4X(const char *Cmd); +int CmdLFEM4X(const char *Cmd); -extern int CmdEM410xDemod(const char *Cmd); -extern int CmdEM410xRead(const char *Cmd); -extern int CmdEM410xSim(const char *Cmd); -extern int CmdEM410xBrute(const char *Cmd); -extern int CmdEM410xWatch(const char *Cmd); -extern int CmdEM410xWatchnSpoof(const char *Cmd); -extern int CmdEM410xWrite(const char *Cmd); -extern int CmdEM4x05Dump(const char *Cmd); -extern int CmdEM4x05Info(const char *Cmd); -extern int CmdEM4x05Read(const char *Cmd); -extern int CmdEM4x05Write(const char *Cmd); -extern int CmdEM4x50Read(const char *Cmd); -extern int CmdEM4x50Write(const char *Cmd); -extern int CmdEM4x50Dump(const char *Cmd); +int CmdEM410xDemod(const char *Cmd); +int CmdEM410xRead(const char *Cmd); +int CmdEM410xSim(const char *Cmd); +int CmdEM410xBrute(const char *Cmd); +int CmdEM410xWatch(const char *Cmd); +int CmdEM410xWatchnSpoof(const char *Cmd); +int CmdEM410xWrite(const char *Cmd); +int CmdEM4x05Dump(const char *Cmd); +int CmdEM4x05Info(const char *Cmd); +int CmdEM4x05Read(const char *Cmd); +int CmdEM4x05Write(const char *Cmd); +int CmdEM4x50Read(const char *Cmd); +int CmdEM4x50Write(const char *Cmd); +int CmdEM4x50Dump(const char *Cmd); -extern int EM4x50Read(const char *Cmd, bool verbose); +int EM4x50Read(const char *Cmd, bool verbose); bool EM4x05IsBlock0(uint32_t *word); -extern void printEM410x(uint32_t hi, uint64_t id); -extern int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo); -extern int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); +void printEM410x(uint32_t hi, uint64_t id); +int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo); +int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); -extern int usage_lf_em410x_sim(void); -extern int usage_lf_em410x_ws(void); -extern int usage_lf_em410x_clone(void); -extern int usage_lf_em410x_sim(void); -extern int usage_lf_em410x_brute(void); +int usage_lf_em410x_sim(void); +int usage_lf_em410x_ws(void); +int usage_lf_em410x_clone(void); +int usage_lf_em410x_sim(void); +int usage_lf_em410x_brute(void); -extern int usage_lf_em4x50_dump(void); -extern int usage_lf_em4x50_read(void); -extern int usage_lf_em4x50_write(void); +int usage_lf_em4x50_dump(void); +int usage_lf_em4x50_read(void); +int usage_lf_em4x50_write(void); -extern int usage_lf_em4x05_dump(void); -extern int usage_lf_em4x05_read(void); -extern int usage_lf_em4x05_write(void); -extern int usage_lf_em4x05_info(void); +int usage_lf_em4x05_dump(void); +int usage_lf_em4x05_read(void); +int usage_lf_em4x05_write(void); +int usage_lf_em4x05_info(void); #endif diff --git a/client/cmdlffdx.h b/client/cmdlffdx.h index 1ae12633a..1bc2428fc 100644 --- a/client/cmdlffdx.h +++ b/client/cmdlffdx.h @@ -19,17 +19,17 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -extern int CmdLFFdx(const char *Cmd); -extern int CmdFdxClone(const char *Cmd); -extern int CmdFdxSim(const char *Cmd); -extern int CmdFdxRead(const char *Cmd); -extern int CmdFdxDemod(const char *Cmd); +int CmdLFFdx(const char *Cmd); +int CmdFdxClone(const char *Cmd); +int CmdFdxSim(const char *Cmd); +int CmdFdxRead(const char *Cmd); +int CmdFdxDemod(const char *Cmd); int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits); -extern int usage_lf_fdx_clone(void); -extern int usage_lf_fdx_sim(void); -extern int usage_lf_fdx_read(void); -extern int usage_lf_fdx_demod(void); +int usage_lf_fdx_clone(void); +int usage_lf_fdx_sim(void); +int usage_lf_fdx_read(void); +int usage_lf_fdx_demod(void); #endif diff --git a/client/cmdlfguard.h b/client/cmdlfguard.h index b01a99aff..749307bea 100644 --- a/client/cmdlfguard.h +++ b/client/cmdlfguard.h @@ -22,12 +22,12 @@ #include "lfdemod.h" // parityTest #include "crc.h" -extern int CmdLFGuard(const char *Cmd); -extern int CmdGuardDemod(const char *Cmd); -extern int CmdGuardRead(const char *Cmd); -extern int CmdGuardClone(const char *Cmd); -extern int CmdGuardSim(const char *Cmd); +int CmdLFGuard(const char *Cmd); +int CmdGuardDemod(const char *Cmd); +int CmdGuardRead(const char *Cmd); +int CmdGuardClone(const char *Cmd); +int CmdGuardSim(const char *Cmd); -extern int usage_lf_guard_clone(void); -extern int usage_lf_quard_sim(void); +int usage_lf_guard_clone(void); +int usage_lf_quard_sim(void); #endif diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index 48d6f63a2..422658822 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -24,20 +24,20 @@ #include "util_posix.h" #include "lfdemod.h" -extern int CmdLFHID(const char *Cmd); -extern int CmdHIDDemod(const char *Cmd); -extern int CmdHIDRead(const char *Cmd); -extern int CmdHIDSim(const char *Cmd); -extern int CmdHIDClone(const char *Cmd); -extern int CmdHIDWiegand(const char *Cmd); -extern int CmdHIDBrute(const char *Cmd); +int CmdLFHID(const char *Cmd); +int CmdHIDDemod(const char *Cmd); +int CmdHIDRead(const char *Cmd); +int CmdHIDSim(const char *Cmd); +int CmdHIDClone(const char *Cmd); +int CmdHIDWiegand(const char *Cmd); +int CmdHIDBrute(const char *Cmd); -extern int usage_lf_hid_read(void); -extern int usage_lf_hid_wiegand(void); -extern int usage_lf_hid_sim(void); -extern int usage_lf_hid_clone(void); -extern int usage_lf_hid_brute(void); +int usage_lf_hid_read(void); +int usage_lf_hid_wiegand(void); +int usage_lf_hid_sim(void); +int usage_lf_hid_clone(void); +int usage_lf_hid_brute(void); //void calc26(uint16_t fc, uint32_t cardno, uint8_t *out); -extern void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits); +void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits); #endif diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index eb5bb2dd0..6728d00e0 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -11,15 +11,15 @@ #ifndef CMDLFHITAG_H__ #define CMDLFHITAG_H__ -extern int CmdLFHitag(const char *Cmd); +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 CmdLFHitagCheckChallenges(const char *Cmd); -extern int CmdLFHitagWriter(const char *Cmd); -extern int CmdLFHitagDump(const char *cmd); +int CmdLFHitagList(const char *Cmd); +int CmdLFHitagSniff(const char *Cmd); +int CmdLFHitagSim(const char *Cmd); +int CmdLFHitagInfo(const char *Cmd); +int CmdLFHitagReader(const char *Cmd); +int CmdLFHitagCheckChallenges(const char *Cmd); +int CmdLFHitagWriter(const char *Cmd); +int CmdLFHitagDump(const char *cmd); #endif diff --git a/client/cmdlfindala.h b/client/cmdlfindala.h index 8352421cc..7bfdd1eae 100644 --- a/client/cmdlfindala.h +++ b/client/cmdlfindala.h @@ -23,19 +23,19 @@ #include "cmddata.h" #include "cmdlf.h" // lf_read -extern int CmdLFINDALA(const char *Cmd); +int CmdLFINDALA(const char *Cmd); -extern int CmdIndalaDemod(const char *Cmd); -extern int CmdIndalaDemodAlt(const char *Cmd); -extern int CmdIndalaRead(const char *Cmd); -extern int CmdIndalaClone(const char *Cmd); -extern int CmdIndalaSim(const char *Cmd); +int CmdIndalaDemod(const char *Cmd); +int CmdIndalaDemodAlt(const char *Cmd); +int CmdIndalaRead(const char *Cmd); +int CmdIndalaClone(const char *Cmd); +int CmdIndalaSim(const char *Cmd); -extern int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); -extern int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert); -extern int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert); +int detectIndala26(uint8_t *bitStream, size_t *size, uint8_t *invert); +int detectIndala64(uint8_t *bitStream, size_t *size, uint8_t *invert); +int detectIndala224(uint8_t *bitStream, size_t *size, uint8_t *invert); -extern int usage_lf_indala_demod(void); -extern int usage_lf_indala_clone(void); -extern int usage_lf_indala_sim(void); +int usage_lf_indala_demod(void); +int usage_lf_indala_clone(void); +int usage_lf_indala_sim(void); #endif diff --git a/client/cmdlfio.h b/client/cmdlfio.h index 6bdb4b88f..5066fee87 100644 --- a/client/cmdlfio.h +++ b/client/cmdlfio.h @@ -16,15 +16,15 @@ #include "cmdmain.h" #include "cmddata.h" -extern int CmdLFIO(const char *Cmd); -extern int CmdIOProxDemod(const char *Cmd); -extern int CmdIOProxRead(const char *Cmd); -extern int CmdIOProxSim(const char *Cmd); -extern int CmdIOProxClone(const char *Cmd); +int CmdLFIO(const char *Cmd); +int CmdIOProxDemod(const char *Cmd); +int CmdIOProxRead(const char *Cmd); +int CmdIOProxSim(const char *Cmd); +int CmdIOProxClone(const char *Cmd); int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits); -extern int usage_lf_io_read(void); -extern int usage_lf_io_clone(void); -extern int usage_lf_io_sim(void); +int usage_lf_io_read(void); +int usage_lf_io_clone(void); +int usage_lf_io_sim(void); #endif diff --git a/client/cmdlfjablotron.h b/client/cmdlfjablotron.h index 127157e67..5079a6f76 100644 --- a/client/cmdlfjablotron.h +++ b/client/cmdlfjablotron.h @@ -22,20 +22,20 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -extern int CmdLFJablotron(const char *Cmd); +int CmdLFJablotron(const char *Cmd); -extern int CmdJablotronDemod(const char *Cmd); -extern int CmdJablotronRead(const char *Cmd); -extern int CmdJablotronClone(const char *Cmd); -extern int CmdJablotronSim(const char *Cmd); +int CmdJablotronDemod(const char *Cmd); +int CmdJablotronRead(const char *Cmd); +int CmdJablotronClone(const char *Cmd); +int CmdJablotronSim(const char *Cmd); -extern int detectJablotron(uint8_t *bits, size_t *size); -extern int getJablotronBits(uint64_t fullcode, uint8_t *bits); +int detectJablotron(uint8_t *bits, size_t *size); +int getJablotronBits(uint64_t fullcode, uint8_t *bits); -//extern int usage_lf_jablotron_demod(void); -//extern int usage_lf_jablotron_read(void); -extern int usage_lf_jablotron_clone(void); -extern int usage_lf_jablotron_sim(void); +//int usage_lf_jablotron_demod(void); +//int usage_lf_jablotron_read(void); +int usage_lf_jablotron_clone(void); +int usage_lf_jablotron_sim(void); #endif diff --git a/client/cmdlfkeri.h b/client/cmdlfkeri.h index ed0629b37..b2e1c89ad 100644 --- a/client/cmdlfkeri.h +++ b/client/cmdlfkeri.h @@ -22,15 +22,15 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // preamble test -extern int CmdLFKeri(const char *Cmd); -extern int CmdKeriRead(const char *Cmd); -extern int CmdKeriDemod(const char *Cmd); -extern int CmdKeriClone(const char *Cmd); -extern int CmdKeriSim(const char *Cmd); +int CmdLFKeri(const char *Cmd); +int CmdKeriRead(const char *Cmd); +int CmdKeriDemod(const char *Cmd); +int CmdKeriClone(const char *Cmd); +int CmdKeriSim(const char *Cmd); -extern int detectKeri(uint8_t *dest, size_t *size, bool *invert); +int detectKeri(uint8_t *dest, size_t *size, bool *invert); -extern int usage_lf_keri_clone(void); -extern int usage_lf_keri_sim(void); +int usage_lf_keri_clone(void); +int usage_lf_keri_sim(void); #endif diff --git a/client/cmdlfnedap.h b/client/cmdlfnedap.h index fd10c5e76..6cacfd638 100644 --- a/client/cmdlfnedap.h +++ b/client/cmdlfnedap.h @@ -22,17 +22,17 @@ #include "lfdemod.h" // parityTest #include "crc.h" -extern int CmdLFNedap(const char *Cmd); -extern int CmdLFNedapDemod(const char *Cmd); -extern int CmdLFNedapRead(const char *Cmd); -//extern int CmdLFNedapClone(const char *Cmd); -extern int CmdLFNedapSim(const char *Cmd); -extern int CmdLFNedapChk(const char *Cmd); +int CmdLFNedap(const char *Cmd); +int CmdLFNedapDemod(const char *Cmd); +int CmdLFNedapRead(const char *Cmd); +//int CmdLFNedapClone(const char *Cmd); +int CmdLFNedapSim(const char *Cmd); +int CmdLFNedapChk(const char *Cmd); -extern int detectNedap(uint8_t *dest, size_t *size); +int detectNedap(uint8_t *dest, size_t *size); -extern int usage_lf_nedap_read(void); -//extern int usage_lf_nedap_clone(void); -extern int usage_lf_nedap_sim(void); +int usage_lf_nedap_read(void); +//int usage_lf_nedap_clone(void); +int usage_lf_nedap_sim(void); #endif diff --git a/client/cmdlfnexwatch.h b/client/cmdlfnexwatch.h index 82782926a..7b08c1294 100644 --- a/client/cmdlfnexwatch.h +++ b/client/cmdlfnexwatch.h @@ -22,9 +22,9 @@ #include "cmdlf.h" #include "lfdemod.h" -extern int CmdLFNEXWATCH(const char *Cmd); -extern int CmdNexWatchDemod(const char *Cmd); -extern int CmdNexWatchRead(const char *Cmd); +int CmdLFNEXWATCH(const char *Cmd); +int CmdNexWatchDemod(const char *Cmd); +int CmdNexWatchRead(const char *Cmd); -extern int detectNexWatch(uint8_t *dest, size_t *size, bool *invert); +int detectNexWatch(uint8_t *dest, size_t *size, bool *invert); #endif diff --git a/client/cmdlfnoralsy.h b/client/cmdlfnoralsy.h index 63065a0d6..c9986d0ea 100644 --- a/client/cmdlfnoralsy.h +++ b/client/cmdlfnoralsy.h @@ -22,17 +22,17 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -extern int CmdLFNoralsy(const char *Cmd); -extern int CmdNoralsyDemod(const char *Cmd); -extern int CmdNoralsyRead(const char *Cmd); -extern int CmdNoralsyClone(const char *Cmd); -extern int CmdNoralsySim(const char *Cmd); +int CmdLFNoralsy(const char *Cmd); +int CmdNoralsyDemod(const char *Cmd); +int CmdNoralsyRead(const char *Cmd); +int CmdNoralsyClone(const char *Cmd); +int CmdNoralsySim(const char *Cmd); int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits); -extern int usage_lf_noralsy_clone(void); -extern int usage_lf_noralsy_sim(void); -//extern int usage_lf_noralsy_read(void); -//extern int usage_lf_noralsy_demod(void); +int usage_lf_noralsy_clone(void); +int usage_lf_noralsy_sim(void); +//int usage_lf_noralsy_read(void); +//int usage_lf_noralsy_demod(void); #endif diff --git a/client/cmdlfpac.h b/client/cmdlfpac.h index 88e97a42e..54b2b3366 100644 --- a/client/cmdlfpac.h +++ b/client/cmdlfpac.h @@ -21,10 +21,10 @@ #include "cmdlf.h" #include "lfdemod.h" // preamble test -extern int CmdLFPac(const char *Cmd); -extern int CmdPacRead(const char *Cmd); -extern int CmdPacDemod(const char *Cmd); +int CmdLFPac(const char *Cmd); +int CmdPacRead(const char *Cmd); +int CmdPacDemod(const char *Cmd); -extern int detectPac(uint8_t *dest, size_t *size); +int detectPac(uint8_t *dest, size_t *size); #endif diff --git a/client/cmdlfparadox.h b/client/cmdlfparadox.h index 44045f114..1b6211716 100644 --- a/client/cmdlfparadox.h +++ b/client/cmdlfparadox.h @@ -8,12 +8,12 @@ //----------------------------------------------------------------------------- #ifndef CMDLFPARADOX_H__ #define CMDLFPARADOX_H__ -extern int CmdLFParadox(const char *Cmd); -extern int CmdParadoxDemod(const char *Cmd); -extern int CmdParadoxRead(const char *Cmd); +int CmdLFParadox(const char *Cmd); +int CmdParadoxDemod(const char *Cmd); +int CmdParadoxRead(const char *Cmd); -//extern int CmdParadoxClone(const char *Cmd); -extern int CmdParadoxSim(const char *Cmd); +//int CmdParadoxClone(const char *Cmd); +int CmdParadoxSim(const char *Cmd); -extern int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); +int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); #endif diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 563f0ac98..5ae74a11f 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -21,16 +21,16 @@ #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -extern int CmdLFPresco(const char *Cmd); -extern int CmdPrescoRead(const char *Cmd); -extern int CmdPrescoDemod(const char *Cmd); -extern int CmdPrescoClone(const char *Cmd); -extern int CmdPrescoSim(const char *Cmd); +int CmdLFPresco(const char *Cmd); +int CmdPrescoRead(const char *Cmd); +int CmdPrescoDemod(const char *Cmd); +int CmdPrescoClone(const char *Cmd); +int CmdPrescoSim(const char *Cmd); -extern int detectPresco(uint8_t *dest, size_t *size); +int detectPresco(uint8_t *dest, size_t *size); int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5); -extern int usage_lf_presco_clone(void); -extern int usage_lf_presco_sim(void); +int usage_lf_presco_clone(void); +int usage_lf_presco_sim(void); #endif diff --git a/client/cmdlfpyramid.h b/client/cmdlfpyramid.h index 425914bbb..fe2b62ef9 100644 --- a/client/cmdlfpyramid.h +++ b/client/cmdlfpyramid.h @@ -22,15 +22,15 @@ #include "lfdemod.h" // parityTest #include "crc.h" -extern int CmdLFPyramid(const char *Cmd); -extern int CmdPyramidDemod(const char *Cmd); -extern int CmdPyramidRead(const char *Cmd); -extern int CmdPyramidClone(const char *Cmd); -extern int CmdPyramidSim(const char *Cmd); +int CmdLFPyramid(const char *Cmd); +int CmdPyramidDemod(const char *Cmd); +int CmdPyramidRead(const char *Cmd); +int CmdPyramidClone(const char *Cmd); +int CmdPyramidSim(const char *Cmd); -extern int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx); +int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx); -extern int usage_lf_pyramid_clone(void); -extern int usage_lf_pyramid_sim(void); +int usage_lf_pyramid_clone(void); +int usage_lf_pyramid_sim(void); #endif diff --git a/client/cmdlfsecurakey.h b/client/cmdlfsecurakey.h index 5155c2ada..bdeae02b7 100644 --- a/client/cmdlfsecurakey.h +++ b/client/cmdlfsecurakey.h @@ -24,11 +24,11 @@ #include "lfdemod.h" // preamble test #include "parity.h" // for wiegand parity test -extern int CmdLFSecurakey(const char *Cmd); -//extern int CmdSecurakeyClone(const char *Cmd); -//extern int CmdSecurakeySim(const char *Cmd); -extern int CmdSecurakeyRead(const char *Cmd); -extern int CmdSecurakeyDemod(const char *Cmd); +int CmdLFSecurakey(const char *Cmd); +//int CmdSecurakeyClone(const char *Cmd); +//int CmdSecurakeySim(const char *Cmd); +int CmdSecurakeyRead(const char *Cmd); +int CmdSecurakeyDemod(const char *Cmd); #endif diff --git a/client/cmdlfviking.h b/client/cmdlfviking.h index 503534eaf..96b4e9ac4 100644 --- a/client/cmdlfviking.h +++ b/client/cmdlfviking.h @@ -21,16 +21,16 @@ #include "cmdlf.h" #include "lfdemod.h" -extern int CmdLFViking(const char *Cmd); +int CmdLFViking(const char *Cmd); -extern int CmdVikingDemod(const char *Cmd); -extern int CmdVikingRead(const char *Cmd); -extern int CmdVikingClone(const char *Cmd); -extern int CmdVikingSim(const char *Cmd); +int CmdVikingDemod(const char *Cmd); +int CmdVikingRead(const char *Cmd); +int CmdVikingClone(const char *Cmd); +int CmdVikingSim(const char *Cmd); -extern int detectViking(uint8_t *dest, size_t *size); +int detectViking(uint8_t *dest, size_t *size); -extern int usage_lf_viking_clone(void); -extern int usage_lf_viking_sim(void); +int usage_lf_viking_clone(void); +int usage_lf_viking_sim(void); #endif diff --git a/client/cmdlfvisa2000.h b/client/cmdlfvisa2000.h index a266fa76e..cb0b102de 100644 --- a/client/cmdlfvisa2000.h +++ b/client/cmdlfvisa2000.h @@ -21,19 +21,19 @@ #include "cmdlf.h" #include "protocols.h" // for T55xx config register definitions #include "lfdemod.h" // parityTest -extern int CmdLFVisa2k(const char *Cmd); +int CmdLFVisa2k(const char *Cmd); -extern int CmdVisa2kDemod(const char *Cmd); -extern int CmdVisa2kRead(const char *Cmd); -extern int CmdVisa2kClone(const char *Cmd); -extern int CmdVisa2kSim(const char *Cmd); +int CmdVisa2kDemod(const char *Cmd); +int CmdVisa2kRead(const char *Cmd); +int CmdVisa2kClone(const char *Cmd); +int CmdVisa2kSim(const char *Cmd); int getvisa2kBits(uint64_t fullcode, uint8_t *bits); -extern int detectVisa2k(uint8_t *dest, size_t *size); +int detectVisa2k(uint8_t *dest, size_t *size); -extern int usage_lf_visa2k_clone(void); -extern int usage_lf_visa2k_sim(void); -//extern int usage_lf_visa2k_read(void); -//extern int usage_lf_visa2k_demod(void); +int usage_lf_visa2k_clone(void); +int usage_lf_visa2k_sim(void); +//int usage_lf_visa2k_read(void); +//int usage_lf_visa2k_demod(void); #endif diff --git a/client/cmdmain.h b/client/cmdmain.h index d5ac8e5a4..c729f8d77 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -41,7 +41,7 @@ #include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands #endif -extern int CommandReceived(char *Cmd); -extern command_t *getTopLevelCommandTable(); +int CommandReceived(char *Cmd); +command_t *getTopLevelCommandTable(); #endif diff --git a/client/cmdscript.h b/client/cmdscript.h index fb915d950..55d735c0a 100644 --- a/client/cmdscript.h +++ b/client/cmdscript.h @@ -11,8 +11,8 @@ #ifndef CMDSCRIPT_H__ #define CMDSCRIPT_H__ -extern int CmdScript(const char *Cmd); +int CmdScript(const char *Cmd); -extern int CmdScriptList(const char *Cmd); -extern int CmdScriptRun(const char *Cmd); +int CmdScriptList(const char *Cmd); +int CmdScriptRun(const char *Cmd); #endif diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 251859761..f7adb7690 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -27,18 +27,18 @@ #include "emv/dump.h" // dump_buffer #include "crypto/libpcrypto.h" // sha512hash -extern int CmdSmartcard(const char *Cmd); +int CmdSmartcard(const char *Cmd); -extern int CmdSmartRaw(const char *cmd); -extern int CmdSmartUpgrade(const char *cmd); -extern int CmdSmartInfo(const char *cmd); -extern int CmdSmartReader(const char *Cmd); +int CmdSmartRaw(const char *cmd); +int CmdSmartUpgrade(const char *cmd); +int CmdSmartInfo(const char *cmd); +int CmdSmartReader(const char *Cmd); -extern bool smart_select(bool silent, smart_card_atr_t *atr); -extern int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +bool smart_select(bool silent, smart_card_atr_t *atr); +int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -extern int usage_sm_raw(void); -extern int usage_sm_reader(void); -extern int usage_sm_info(void); -extern int usage_sm_upgrade(void); +int usage_sm_raw(void); +int usage_sm_reader(void); +int usage_sm_info(void); +int usage_sm_upgrade(void); #endif diff --git a/client/cmdtrace.h b/client/cmdtrace.h index 0d370123d..0191bf0e1 100644 --- a/client/cmdtrace.h +++ b/client/cmdtrace.h @@ -27,14 +27,14 @@ #include "comms.h" // for sending cmds to device. GetFromBigBuf #include "loclass/fileutils.h" // for saveFile -extern int CmdTrace(const char *Cmd); +int CmdTrace(const char *Cmd); -extern int CmdTraceList(const char *Cmd); -extern int CmdTraceLoad(const char *Cmd); -extern int CmdTraceSave(const char *Cmd); +int CmdTraceList(const char *Cmd); +int CmdTraceLoad(const char *Cmd); +int CmdTraceSave(const char *Cmd); // usages helptext -extern int usage_trace_list(void); -extern int usage_trace_load(void); -extern int usage_trace_save(void); +int usage_trace_list(void); +int usage_trace_load(void); +int usage_trace_save(void); #endif diff --git a/client/comms.h b/client/comms.h index b0687ac60..b8e33beee 100644 --- a/client/comms.h +++ b/client/comms.h @@ -62,7 +62,7 @@ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand *response, size_t ms_timeo bool WaitForResponseTimeout(uint32_t cmd, UsbCommand *response, size_t ms_timeout); bool WaitForResponse(uint32_t cmd, UsbCommand *response); -extern bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning); +bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning); #endif diff --git a/client/crypto/asn1utils.h b/client/crypto/asn1utils.h index 19f8ded70..60c94e34a 100644 --- a/client/crypto/asn1utils.h +++ b/client/crypto/asn1utils.h @@ -15,7 +15,7 @@ #include #include -extern int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent); -extern int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval); +int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent); +int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval); #endif /* asn1utils.h */ diff --git a/client/proxgui.h b/client/proxgui.h index 5f6d8bd2a..ada09d838 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -36,10 +36,10 @@ extern bool GridLocked; //Operations defined in data_operations //extern int autoCorr(const int* in, int *out, size_t len, int window); -extern int AskEdgeDetect(const int *in, int *out, int len, int threshold); -extern int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose); -extern int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); -extern void save_restoreGB(uint8_t saveOpt); +int AskEdgeDetect(const int *in, int *out, int len, int threshold); +int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose); +int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); +void save_restoreGB(uint8_t saveOpt); #define GRAPH_SAVE 1 #define GRAPH_RESTORE 0 diff --git a/client/scandir.h b/client/scandir.h index 7155c5a79..905431cbe 100644 --- a/client/scandir.h +++ b/client/scandir.h @@ -15,8 +15,8 @@ #include #ifdef _WIN32 -extern int scandir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)); -extern int alphasort(const struct dirent **a, const struct dirent **b); +int scandir(const char *dir, struct dirent ***namelist, int (*select)(const struct dirent *), int (*compar)(const struct dirent **, const struct dirent **)); +int alphasort(const struct dirent **a, const struct dirent **b); #endif // _WIN32 #endif // SCANDIR_H__ diff --git a/client/ui.h b/client/ui.h index 827c3828e..7df965976 100644 --- a/client/ui.h +++ b/client/ui.h @@ -33,10 +33,10 @@ void ShowGui(void); void HideGraphWindow(void); void ShowGraphWindow(void); void RepaintGraphWindow(void); -extern void PrintAndLog(char *fmt, ...); +void PrintAndLog(char *fmt, ...); void PrintAndLogOptions(char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, char *fmt, ...); -extern void SetLogFilename(char *fn); +void SetLogFilename(char *fn); void SetFlushAfterWrite(bool value); extern double CursorScaleFactor; @@ -48,6 +48,6 @@ extern bool showDemod; extern pthread_mutex_t print_lock; -extern void iceIIR_Butterworth(int *data, const size_t len); -extern void iceSimple_Filter(int *data, const size_t len, uint8_t k); +void iceIIR_Butterworth(int *data, const size_t len); +void iceSimple_Filter(int *data, const size_t len, uint8_t k); #endif diff --git a/client/util.h b/client/util.h index cf5f97360..208ae61f0 100644 --- a/client/util.h +++ b/client/util.h @@ -186,81 +186,81 @@ } #endif -extern uint8_t g_debugMode; +uint8_t g_debugMode; -extern int ukbhit(void); -extern void AddLogLine(char *fn, char *data, char *c); -extern void AddLogHex(char *fn, char *extData, const uint8_t *data, const size_t len); -extern void AddLogUint64(char *fn, char *data, const uint64_t value); -extern void AddLogCurrentDT(char *fn); -extern void FillFileNameByUID(char *filenamePrefix, uint8_t *uid, const char *ext, int uidlen); +int ukbhit(void); +void AddLogLine(char *fn, char *data, char *c); +void AddLogHex(char *fn, char *extData, const uint8_t *data, const size_t len); +void AddLogUint64(char *fn, char *data, const uint64_t value); +void AddLogCurrentDT(char *fn); +void FillFileNameByUID(char *filenamePrefix, uint8_t *uid, const char *ext, int uidlen); // fill buffer from structure [{uint8_t data, size_t length},...] -extern int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); +int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); -extern bool CheckStringIsHEXValue(const char *value); -extern void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, +bool CheckStringIsHEXValue(const char *value); +void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase); -extern void print_hex(const uint8_t *data, const size_t len); -extern void print_hex_break(const uint8_t *data, const size_t len, const uint8_t breaks); -extern char *sprint_hex(const uint8_t *data, const size_t len); -extern char *sprint_hex_inrow(const uint8_t *data, const size_t len); -extern char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len); -extern char *sprint_hex_inrow_spaces(const uint8_t *data, const size_t len, size_t spaces_between); -extern char *sprint_bin(const uint8_t *data, const size_t len); -extern char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks); -extern char *sprint_hex_ascii(const uint8_t *data, const size_t len); -extern char *sprint_ascii(const uint8_t *data, const size_t len); -extern char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_str_len); +void print_hex(const uint8_t *data, const size_t len); +void print_hex_break(const uint8_t *data, const size_t len, const uint8_t breaks); +char *sprint_hex(const uint8_t *data, const size_t len); +char *sprint_hex_inrow(const uint8_t *data, const size_t len); +char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len); +char *sprint_hex_inrow_spaces(const uint8_t *data, const size_t len, size_t spaces_between); +char *sprint_bin(const uint8_t *data, const size_t len); +char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks); +char *sprint_hex_ascii(const uint8_t *data, const size_t len); +char *sprint_ascii(const uint8_t *data, const size_t len); +char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_str_len); -extern void print_blocks(uint32_t *data, size_t len); +void print_blocks(uint32_t *data, size_t len); -extern void num_to_bytes(uint64_t n, size_t len, uint8_t *dest); -extern uint64_t bytes_to_num(uint8_t *src, size_t len); -extern void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest); -extern void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest); -extern uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); -extern void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); +void num_to_bytes(uint64_t n, size_t len, uint8_t *dest); +uint64_t bytes_to_num(uint8_t *src, size_t len); +void num_to_bytebits(uint64_t n, size_t len, uint8_t *dest); +void num_to_bytebitsLSBF(uint64_t n, size_t len, uint8_t *dest); +uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockSize); +void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest); -extern int param_getlength(const char *line, int paramnum); -extern char param_getchar(const char *line, int paramnum); -extern char param_getchar_indx(const char *line, int indx, int paramnum); -extern int param_getptr(const char *line, int *bg, int *en, int paramnum); -extern uint8_t param_get8(const char *line, int paramnum); -extern uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); -extern uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); -extern uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base); -extern uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination); -extern uint8_t param_isdec(const char *line, int paramnum); -extern int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt); -extern int param_gethex_ex(const char *line, int paramnum, uint8_t *data, int *hexcnt); -extern int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen); -extern int param_getstr(const char *line, int paramnum, char *str, size_t buffersize); +int param_getlength(const char *line, int paramnum); +char param_getchar(const char *line, int paramnum); +char param_getchar_indx(const char *line, int indx, int paramnum); +int param_getptr(const char *line, int *bg, int *en, int paramnum); +uint8_t param_get8(const char *line, int paramnum); +uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base); +uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base); +uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base); +uint8_t param_getdec(const char *line, int paramnum, uint8_t *destination); +uint8_t param_isdec(const char *line, int paramnum); +int param_gethex(const char *line, int paramnum, uint8_t *data, int hexcnt); +int param_gethex_ex(const char *line, int paramnum, uint8_t *data, int *hexcnt); +int param_gethex_to_eol(const char *line, int paramnum, uint8_t *data, int maxdatalen, int *datalen); +int param_getstr(const char *line, int paramnum, char *str, size_t buffersize); -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 void binarraytobinstring(char *target, char *source, int length); -extern uint8_t GetParity(uint8_t *bits, uint8_t type, int length); -extern void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); +int hextobinarray(char *target, char *source); +int hextobinstring(char *target, char *source); +int binarraytohex(char *target, const size_t targetlen, char *source, size_t srclen); +void binarraytobinstring(char *target, char *source, int length); +uint8_t GetParity(uint8_t *bits, uint8_t type, int length); +void wiegand_add_parity(uint8_t *target, uint8_t *source, uint8_t length); -extern void xor(unsigned char *dst, unsigned char *src, size_t len); -extern int32_t le24toh(uint8_t data[3]); +void xor(unsigned char *dst, unsigned char *src, size_t len); +int32_t le24toh(uint8_t data[3]); -extern uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bits); -extern void rol(uint8_t *data, const size_t len); -extern uint32_t reflect(uint32_t v, int b); -extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal -extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal -extern uint64_t HornerScheme(uint64_t num, uint64_t divider, uint64_t factor); +uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bits); +void rol(uint8_t *data, const size_t len); +uint32_t reflect(uint32_t v, int b); +uint8_t reflect8(uint8_t b); // dedicated 8bit reversal +uint16_t reflect16(uint16_t b); // dedicated 16bit reversal +uint64_t HornerScheme(uint64_t num, uint64_t divider, uint64_t factor); -extern int num_CPUs(void); // number of logical CPUs +int num_CPUs(void); // number of logical CPUs -extern void str_lower(char *s); // converts string to lower case -extern bool str_startswith(const char *s, const char *pre); // check for prefix in string -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); +void str_lower(char *s); // converts string to lower case +bool str_startswith(const char *s, const char *pre); // check for prefix in string +void strcleanrn(char *buf, size_t len); +void strcreplace(char *buf, size_t len, char from, char to); +char *strmcopy(char *buf); #endif From 567ceb017b9d0162deb09231f2f178b55030553a Mon Sep 17 00:00:00 2001 From: vratiskol Date: Sat, 6 Apr 2019 00:39:27 +0200 Subject: [PATCH 062/141] 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); From 98d940874625b246803d790985520afccb377ec2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 00:52:55 +0200 Subject: [PATCH 063/141] make style --- client/cliparser/cliparser.h | 14 +-- client/cmdlft55xx.h | 30 +++--- client/crypto/asn1dump.h | 2 +- client/crypto/libpcrypto.h | 24 ++--- client/emv/apduinfo.h | 4 +- client/emv/cmdemv.h | 14 +-- client/emv/emv_pki.h | 2 +- client/emv/emv_roca.h | 4 +- client/emv/emvcore.h | 48 ++++----- client/emv/emvjson.h | 28 ++--- client/emv/test/cda_test.h | 2 +- client/emv/test/crypto_test.h | 2 +- client/emv/test/cryptotest.h | 2 +- client/emv/test/dda_test.h | 2 +- client/emv/test/sda_test.h | 2 +- client/fido/cbortools.h | 22 ++-- client/fido/cose.h | 10 +- client/fido/fidocore.h | 30 +++--- client/hardnested/hardnested_bf_core.h | 8 +- client/hardnested/hardnested_bitarray_core.h | 26 ++--- client/hardnested/hardnested_bruteforce.h | 10 +- client/loclass/fileutils.h | 14 +-- client/loclass/hash1_brute.h | 2 +- client/mifare/mad.h | 8 +- client/mifare/mfkey.h | 12 +-- client/mifare/mifare4.h | 30 +++--- client/mifare/mifarehost.h | 50 ++++----- client/mifare/ndef.h | 2 +- client/proxgui.h | 2 +- client/reveng/reveng.h | 108 +++++++++---------- 30 files changed, 257 insertions(+), 257 deletions(-) diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h index d42cd50b6..7dd3584bc 100644 --- a/client/cliparser/cliparser.h +++ b/client/cliparser/cliparser.h @@ -31,11 +31,11 @@ #define CLIGetHexWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} #define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} -extern int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp); -extern int CLIParserParseString(const char *str, void *argtable[], size_t vargtableLen, bool allowEmptyExec); -extern int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); -extern int CLIParserParseArg(int argc, char **argv, void *argtable[], size_t vargtableLen, bool allowEmptyExec); -extern void CLIParserFree(); +int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp); +int CLIParserParseString(const char *str, void *argtable[], size_t vargtableLen, bool allowEmptyExec); +int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); +int CLIParserParseArg(int argc, char **argv, void *argtable[], size_t vargtableLen, bool allowEmptyExec); +void CLIParserFree(); -extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); -extern int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index ce990bebd..dca8c6f39 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -137,17 +137,17 @@ typedef struct { t55xx_conf_block_t Get_t55xx_Config(void); void Set_t55xx_Config(t55xx_conf_block_t conf); -extern int CmdLFT55XX(const char *Cmd); -extern int CmdT55xxChk(const char *Cmd); -extern int CmdT55xxBruteForce(const char *Cmd); -extern int CmdT55xxSetConfig(const char *Cmd); -extern int CmdT55xxReadBlock(const char *Cmd); -extern int CmdT55xxWriteBlock(const char *Cmd); -extern int CmdT55xxReadTrace(const char *Cmd); -extern int CmdT55xxInfo(const char *Cmd); -extern int CmdT55xxDetect(const char *Cmd); -extern int CmdResetRead(const char *Cmd); -extern int CmdT55xxWipe(const char *Cmd); +int CmdLFT55XX(const char *Cmd); +int CmdT55xxChk(const char *Cmd); +int CmdT55xxBruteForce(const char *Cmd); +int CmdT55xxSetConfig(const char *Cmd); +int CmdT55xxReadBlock(const char *Cmd); +int CmdT55xxWriteBlock(const char *Cmd); +int CmdT55xxReadTrace(const char *Cmd); +int CmdT55xxInfo(const char *Cmd); +int CmdT55xxDetect(const char *Cmd); +int CmdResetRead(const char *Cmd); +int CmdT55xxWipe(const char *Cmd); char *GetPskCfStr(uint32_t id, bool q5); char *GetBitRateStr(uint32_t id, bool xmode); @@ -160,16 +160,16 @@ void printT5xxHeader(uint8_t page); void printT55xxBlock(const char *demodStr); int printConfiguration(t55xx_conf_block_t b); -extern int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password); +int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password); bool GetT55xxBlockData(uint32_t *blockdata); bool DecodeT55xxBlock(void); -extern bool tryDetectModulation(void); +bool tryDetectModulation(void); bool testKnownConfigBlock(uint32_t block0); -extern bool tryDetectP1(bool getData); +bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); -extern bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password); +bool AquireData(uint8_t page, uint8_t block, bool pwdmode, uint32_t password); int tryOnePassword(uint32_t password); void printT55x7Trace(t55x7_tracedata_t data, uint8_t repeat); diff --git a/client/crypto/asn1dump.h b/client/crypto/asn1dump.h index 1aadf487c..c7aef7e39 100644 --- a/client/crypto/asn1dump.h +++ b/client/crypto/asn1dump.h @@ -16,6 +16,6 @@ #include #include "emv/tlv.h" -extern bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump); +bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump); #endif /* asn1utils.h */ diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h index 2cb4644a8..38d37b66a 100644 --- a/client/crypto/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -16,20 +16,20 @@ #include #include -extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); -extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); -extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); -extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); +int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); +int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); +int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); +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); +int sha256hash(uint8_t *input, int length, uint8_t *hash); +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); -extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen); -extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen); -extern char *ecdsa_get_error(int ret); +int ecdsa_key_create(uint8_t *key_d, uint8_t *key_xy); +int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); +int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen); +int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen); +char *ecdsa_get_error(int ret); -extern int ecdsa_nist_test(bool verbose); +int ecdsa_nist_test(bool verbose); #endif /* libpcrypto.h */ diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h index 054aeec91..d7811dbc6 100644 --- a/client/emv/apduinfo.h +++ b/client/emv/apduinfo.h @@ -28,7 +28,7 @@ typedef struct { const char *Description; } APDUCode; -extern const APDUCode *const GetAPDUCode(uint8_t sw1, uint8_t sw2); -extern const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2); +const APDUCode *const GetAPDUCode(uint8_t sw1, uint8_t sw2); +const char *GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2); #endif diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index c91f75606..739909215 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -29,12 +29,12 @@ int CmdEMV(const char *Cmd); -extern int CmdEMVSelect(const char *cmd); -extern int CmdEMVSearch(const char *cmd); -extern int CmdEMVPPSE(const char *cmd); -extern int CmdEMVExec(const char *cmd); -extern int CmdEMVGetrng(const char *Cmd); -extern int CmdEMVList(const char *Cmd); -extern int CmdEMVRoca(const char *Cmd); +int CmdEMVSelect(const char *cmd); +int CmdEMVSearch(const char *cmd); +int CmdEMVPPSE(const char *cmd); +int CmdEMVExec(const char *cmd); +int CmdEMVGetrng(const char *Cmd); +int CmdEMVList(const char *Cmd); +int CmdEMVRoca(const char *Cmd); #endif diff --git a/client/emv/emv_pki.h b/client/emv/emv_pki.h index 6cc4a97d1..0b80f2665 100644 --- a/client/emv/emv_pki.h +++ b/client/emv/emv_pki.h @@ -21,7 +21,7 @@ #include -extern void PKISetStrictExecution(bool se); +void PKISetStrictExecution(bool se); unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len); struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db); diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index 2830ce9c5..6663ce710 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -31,8 +31,8 @@ #define ROCA_PRINTS_LENGTH 17 -extern bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose); -extern int roca_self_test(void); +bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose); +int roca_self_test(void); #endif diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 7e9afabf7..806a9366f 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -63,46 +63,46 @@ enum CardPSVendor { CV_CB, CV_OTHER, }; -extern enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen); +enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen); -extern bool TLVPrintFromBuffer(uint8_t *data, int datalen); -extern void TLVPrintFromTLV(struct tlvdb *tlv); -extern void TLVPrintFromTLVLev(struct tlvdb *tlv, int level); -extern void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv); +bool TLVPrintFromBuffer(uint8_t *data, int datalen); +void TLVPrintFromTLV(struct tlvdb *tlv); +void TLVPrintFromTLVLev(struct tlvdb *tlv, int level); +void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv); -extern struct tlvdb *GetPANFromTrack2(const struct tlv *track2); -extern struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); +struct tlvdb *GetPANFromTrack2(const struct tlv *track2); +struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); -extern void SetAPDULogging(bool logging); +void SetAPDULogging(bool logging); // exchange -extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // search application -extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); -extern int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); -extern int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); +int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // select application -extern int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen); +int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen); // Get Processing Options -extern int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); -extern int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // AC -extern int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); -extern int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // DDA -extern int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // Mastercard int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // Auth -extern int trSDA(struct tlvdb *tlv); -extern int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv); -extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv); +int trSDA(struct tlvdb *tlv); +int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv); +int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv); -extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); +int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); -extern struct emv_pk *get_ca_pk(struct tlvdb *db); +struct emv_pk *get_ca_pk(struct tlvdb *db); #endif diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 18326083f..23cfba545 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -18,24 +18,24 @@ typedef struct { char *Name; } ApplicationDataElm; -extern char *GetApplicationDataName(tlv_tag_t tag); +char *GetApplicationDataName(tlv_tag_t tag); -extern int JsonSaveJsonObject(json_t *root, char *path, json_t *value); -extern int JsonSaveStr(json_t *root, char *path, char *value); -extern int JsonSaveInt(json_t *root, char *path, int value); -extern int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen); -extern int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen); -extern int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen); +int JsonSaveJsonObject(json_t *root, char *path, json_t *value); +int JsonSaveStr(json_t *root, char *path, char *value); +int JsonSaveInt(json_t *root, char *path, int value); +int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen); +int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen); +int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen); -extern int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm); -extern int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink); -extern int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, bool saveName, bool saveValue, bool saveAppDataLink); +int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm); +int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink); +int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, bool saveName, bool saveValue, bool saveAppDataLink); -extern int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm); +int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm); -extern int JsonLoadStr(json_t *root, char *path, char *value); -extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen); +int JsonLoadStr(json_t *root, char *path, char *value); +int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen); -extern bool ParamLoadFromJson(struct tlvdb *tlv); +bool ParamLoadFromJson(struct tlvdb *tlv); #endif diff --git a/client/emv/test/cda_test.h b/client/emv/test/cda_test.h index 8d80043cd..e535c2eee 100644 --- a/client/emv/test/cda_test.h +++ b/client/emv/test/cda_test.h @@ -15,4 +15,4 @@ #include -extern int exec_cda_test(bool verbose); +int exec_cda_test(bool verbose); diff --git a/client/emv/test/crypto_test.h b/client/emv/test/crypto_test.h index 04159c4f0..afc8a1515 100644 --- a/client/emv/test/crypto_test.h +++ b/client/emv/test/crypto_test.h @@ -15,4 +15,4 @@ #include -extern int exec_crypto_test(bool verbose); +int exec_crypto_test(bool verbose); diff --git a/client/emv/test/cryptotest.h b/client/emv/test/cryptotest.h index 5c6aaae2d..671de244e 100644 --- a/client/emv/test/cryptotest.h +++ b/client/emv/test/cryptotest.h @@ -10,4 +10,4 @@ #include -extern int ExecuteCryptoTests(bool verbose); +int ExecuteCryptoTests(bool verbose); diff --git a/client/emv/test/dda_test.h b/client/emv/test/dda_test.h index 1ae1a0660..34381938a 100644 --- a/client/emv/test/dda_test.h +++ b/client/emv/test/dda_test.h @@ -15,4 +15,4 @@ #include -extern int exec_dda_test(bool verbose); +int exec_dda_test(bool verbose); diff --git a/client/emv/test/sda_test.h b/client/emv/test/sda_test.h index 8d47aa9b3..696a17f9b 100644 --- a/client/emv/test/sda_test.h +++ b/client/emv/test/sda_test.h @@ -13,4 +13,4 @@ * Lesser General Public License for more details. */ -extern int exec_sda_test(bool verbose); +int exec_sda_test(bool verbose); diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 1e3fa8c0f..d42506658 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -21,18 +21,18 @@ #define cbor_check_if(r) if ((r) != CborNoError) {return r;} else #define cbor_check(r) if ((r) != CborNoError) return r; -extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, size_t length); -extern int JsonToCbor(json_t *elm, CborEncoder *encoder); +int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, size_t length); +int JsonToCbor(json_t *elm, CborEncoder *encoder); -extern int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key); -extern CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); -extern CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter, size_t delimeterlen); -extern CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); -extern CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimeter); -extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); -extern CborError CborGetStringValueBuf(CborValue *elm); +int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key); +CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); +CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter, size_t delimeterlen); +CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); +CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimeter); +CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); +CborError CborGetStringValueBuf(CborValue *elm); -extern int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder); -extern CborError CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder); +int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder); +CborError CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder); #endif /* __CBORTOOLS_H__ */ diff --git a/client/fido/cose.h b/client/fido/cose.h index 850652fc4..f8f28aabf 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -17,11 +17,11 @@ #include #include -extern const char *GetCOSEAlgName(int id); -extern const char *GetCOSEAlgDescription(int id); -extern const char *GetCOSEktyDescription(int id); -extern const char *GetCOSECurveDescription(int id); +const char *GetCOSEAlgName(int id); +const char *GetCOSEAlgDescription(int id); +const char *GetCOSEktyDescription(int id); +const char *GetCOSECurveDescription(int id); -extern int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key); +int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key); #endif /* __COSE_H__ */ diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 60923a44b..676dd2646 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -35,23 +35,23 @@ typedef enum { ptResponse, } fido2PacketType; -extern int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen); +int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen); -extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum); -extern char *fido2GetCmdErrorDescription(uint8_t errorCode); +char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum); +char *fido2GetCmdErrorDescription(uint8_t errorCode); -extern bool CheckrpIdHash(json_t *json, uint8_t *hash); -extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); -extern int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); -extern int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen, bool createAllowList); -extern int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR); +bool CheckrpIdHash(json_t *json, uint8_t *hash); +int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); +int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); +int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen, bool createAllowList); +int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR); #endif /* __FIDOCORE_H__ */ diff --git a/client/hardnested/hardnested_bf_core.h b/client/hardnested/hardnested_bf_core.h index bd0e83c68..4f481cbc8 100644 --- a/client/hardnested/hardnested_bf_core.h +++ b/client/hardnested/hardnested_bf_core.h @@ -61,10 +61,10 @@ typedef enum { SIMD_MMX, SIMD_NONE, } SIMDExecInstr; -extern void SetSIMDInstr(SIMDExecInstr instr); -extern SIMDExecInstr GetSIMDInstrAuto(); +void SetSIMDInstr(SIMDExecInstr instr); +SIMDExecInstr GetSIMDInstrAuto(); -extern const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces); -extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par); +const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces); +void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par); #endif diff --git a/client/hardnested/hardnested_bitarray_core.h b/client/hardnested/hardnested_bitarray_core.h index b12fcf89d..91515b57f 100644 --- a/client/hardnested/hardnested_bitarray_core.h +++ b/client/hardnested/hardnested_bitarray_core.h @@ -52,18 +52,18 @@ THE SOFTWARE. #include -extern uint32_t *malloc_bitarray(uint32_t x); -extern void free_bitarray(uint32_t *x); -extern uint32_t bitcount(uint32_t a); -extern uint32_t count_states(uint32_t *A); -extern void bitarray_AND(uint32_t *A, uint32_t *B); -extern void bitarray_low20_AND(uint32_t *A, uint32_t *B); -extern uint32_t count_bitarray_AND(uint32_t *A, uint32_t *B); -extern uint32_t count_bitarray_low20_AND(uint32_t *A, uint32_t *B); -extern void bitarray_AND4(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D); -extern void bitarray_OR(uint32_t *A, uint32_t *B); -extern uint32_t count_bitarray_AND2(uint32_t *A, uint32_t *B); -extern uint32_t count_bitarray_AND3(uint32_t *A, uint32_t *B, uint32_t *C); -extern uint32_t count_bitarray_AND4(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D); +uint32_t *malloc_bitarray(uint32_t x); +void free_bitarray(uint32_t *x); +uint32_t bitcount(uint32_t a); +uint32_t count_states(uint32_t *A); +void bitarray_AND(uint32_t *A, uint32_t *B); +void bitarray_low20_AND(uint32_t *A, uint32_t *B); +uint32_t count_bitarray_AND(uint32_t *A, uint32_t *B); +uint32_t count_bitarray_low20_AND(uint32_t *A, uint32_t *B); +void bitarray_AND4(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D); +void bitarray_OR(uint32_t *A, uint32_t *B); +uint32_t count_bitarray_AND2(uint32_t *A, uint32_t *B); +uint32_t count_bitarray_AND3(uint32_t *A, uint32_t *B, uint32_t *C); +uint32_t count_bitarray_AND4(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D); #endif diff --git a/client/hardnested/hardnested_bruteforce.h b/client/hardnested/hardnested_bruteforce.h index c104e69ac..180e537d8 100644 --- a/client/hardnested/hardnested_bruteforce.h +++ b/client/hardnested/hardnested_bruteforce.h @@ -27,10 +27,10 @@ typedef struct { void *next; } statelist_t; -extern void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte); -extern bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key); -extern float brute_force_benchmark(); -extern uint8_t trailing_zeros(uint8_t byte); -extern bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, uint32_t odd, uint32_t even); +void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte); +bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key); +float brute_force_benchmark(); +uint8_t trailing_zeros(uint8_t byte); +bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, uint32_t odd, uint32_t even); #endif diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 7b358331a..ddc906725 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -75,7 +75,7 @@ int fileExists(const char *filename); * @param datalen the length of the data * @return 0 for ok, 1 for failz */ -extern int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen); +int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen); /** * @brief Utility function to save data to a textfile (EML). This method takes a preferred name, but if that @@ -89,7 +89,7 @@ extern int saveFile(const char *preferredName, const char *suffix, const void *d * @param blocksize the length of one row * @return 0 for ok, 1 for failz */ -extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize); +int saveFileEML(const char *preferredName, const char *suffix, uint8_t *data, size_t datalen, size_t blocksize); /** STUB * @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that @@ -103,7 +103,7 @@ extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t *d * @param datalen the length of the data * @return 0 for ok, 1 for failz */ -extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen); +int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t *data, size_t datalen); /** STUB * @brief Utility function to load data from a binary file. This method takes a preferred name. @@ -116,7 +116,7 @@ extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileT * @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); +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. @@ -128,7 +128,7 @@ extern int loadFile(const char *preferredName, const char *suffix, void *data, s * @param datalen the number of bytes loaded from file * @return 0 for ok, 1 for failz */ -extern int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen); +int loadFileEML(const char *preferredName, const char *suffix, void *data, size_t *datalen); /** * @brief Utility function to load data from a JSON textfile. This method takes a preferred name. @@ -141,7 +141,7 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void *data * @param datalen the number of bytes loaded from file * @return 0 for ok, 1 for failz */ -extern int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); +int loadFileJSON(const char *preferredName, const char *suffix, void *data, size_t maxdatalen, size_t *datalen); /** @@ -156,7 +156,7 @@ extern int loadFileJSON(const char *preferredName, const char *suffix, void *dat * @param keylen the number of bytes a key per row is * @return 0 for ok, 1 for failz */ -extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); +int loadFileDICTIONARY(const char *preferredName, const char *suffix, void *data, size_t *datalen, uint8_t keylen, uint16_t *keycnt); #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #else diff --git a/client/loclass/hash1_brute.h b/client/loclass/hash1_brute.h index 4debebd0d..b26ad96d1 100644 --- a/client/loclass/hash1_brute.h +++ b/client/loclass/hash1_brute.h @@ -1,5 +1,5 @@ #ifndef HASH1_BRUTE_H #define HASH1_BRUTE_H -extern void brute_hash1(); +void brute_hash1(); #endif // HASH1_BRUTE_H diff --git a/client/mifare/mad.h b/client/mifare/mad.h index 89fcd795c..d1028e06a 100644 --- a/client/mifare/mad.h +++ b/client/mifare/mad.h @@ -20,10 +20,10 @@ typedef struct { const char *Description; } madAIDDescr; -extern int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2); -extern int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen); -extern int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); -extern int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); +int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2); +int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen); +int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); +int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); #endif // _MAD_H_ diff --git a/client/mifare/mfkey.h b/client/mifare/mfkey.h index 0f8ba8069..4af5175a1 100644 --- a/client/mifare/mfkey.h +++ b/client/mifare/mfkey.h @@ -19,12 +19,12 @@ #include "mifare.h" #include "crapto1/crapto1.h" -extern uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys); -extern bool mfkey32(nonces_t data, uint64_t *outputkey); -extern bool mfkey32_moebius(nonces_t data, uint64_t *outputkey); -extern int mfkey64(nonces_t data, uint64_t *outputkey); +uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t par_info, uint64_t ks_info, uint64_t **keys); +bool mfkey32(nonces_t data, uint64_t *outputkey); +bool mfkey32_moebius(nonces_t data, uint64_t *outputkey); +int mfkey64(nonces_t data, uint64_t *outputkey); -extern int compare_uint64(const void *a, const void *b); -extern uint32_t intersection(uint64_t *listA, uint64_t *listB); +int compare_uint64(const void *a, const void *b); +uint32_t intersection(uint64_t *listA, uint64_t *listB); #endif diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index e33e69fd2..d403bdd94 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -43,25 +43,25 @@ typedef struct { char *description; } AccessConditions_t; -extern void mfpSetVerboseMode(bool verbose); -extern const char *mfpGetErrorDescription(uint8_t errorCode); +void mfpSetVerboseMode(bool verbose); +const char *mfpGetErrorDescription(uint8_t errorCode); -extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); -extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); +int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); -extern int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -extern int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); -extern int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); -extern int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); -extern int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose); +int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose); -extern char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); +char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); -extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); -extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo); -extern uint8_t mfSectorTrailer(uint8_t blockNo); -extern bool mfIsSectorTrailer(uint8_t blockNo); -extern uint8_t mfSectorNum(uint8_t blockNo); +uint8_t mfNumBlocksPerSector(uint8_t sectorNo); +uint8_t mfFirstBlockOfSector(uint8_t sectorNo); +uint8_t mfSectorTrailer(uint8_t blockNo); +bool mfIsSectorTrailer(uint8_t blockNo); +uint8_t mfSectorNum(uint8_t blockNo); #endif // mifare4.h diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 7481647ad..81e0e8f03 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -69,35 +69,35 @@ typedef struct { extern char logHexFileName[FILE_PATH_SIZE]; -extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); -extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKeys, bool calibrate); -extern int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); -extern int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, - uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); -extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); +int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); +int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKeys, bool calibrate); +int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); +int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, + uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); +int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); -extern int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); +int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); -extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); -extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); -extern int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); +int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); +int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); +int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); -extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); -extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); -extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); +int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); +int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); +int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); -extern int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); -extern int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); +int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); +int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); -extern int isTraceCardEmpty(void); -extern int isBlockEmpty(int blockN); -extern int isBlockTrailer(int blockN); -extern int loadTraceCard(uint8_t *tuid, uint8_t uidlen); -extern int saveTraceCard(void); -extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); +int isTraceCardEmpty(void); +int isBlockEmpty(int blockN); +int isBlockTrailer(int blockN); +int loadTraceCard(uint8_t *tuid, uint8_t uidlen); +int saveTraceCard(void); +int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); -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); +int detect_classic_prng(void); +int detect_classic_nackbug(bool verbose); +void detect_classic_magic(void); +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); #endif diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 1130ebba7..1737a6082 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -57,6 +57,6 @@ typedef struct { uint8_t *ID; } NDEFHeader_t; -extern int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); +int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); #endif // _NDEF_H_ diff --git a/client/proxgui.h b/client/proxgui.h index ada09d838..0d43e7823 100644 --- a/client/proxgui.h +++ b/client/proxgui.h @@ -35,7 +35,7 @@ extern int offline; extern bool GridLocked; //Operations defined in data_operations -//extern int autoCorr(const int* in, int *out, size_t len, int window); +//int autoCorr(const int* in, int *out, size_t len, int window); int AskEdgeDetect(const int *in, int *out, int len, int threshold); int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose); int directionalThreshold(const int *in, int *out, size_t len, int8_t up, int8_t down); diff --git a/client/reveng/reveng.h b/client/reveng/reveng.h index 110b3f620..59a5f901a 100644 --- a/client/reveng/reveng.h +++ b/client/reveng/reveng.h @@ -99,7 +99,7 @@ typedef BMP_T bmp_t; extern int bmpbit, bmpsub; -extern void setbmp(void); +void setbmp(void); /* poly.c */ #define P_REFIN 1 @@ -139,41 +139,41 @@ typedef struct { /* left-justified in each word */ } poly_t; -extern poly_t filtop(FILE *input, unsigned long length, int flags, int bperhx); -extern poly_t strtop(const char *string, int flags, int bperhx); -extern char *ptostr(const poly_t poly, int flags, int bperhx); -extern char *pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned long end); -extern poly_t pclone(const poly_t poly); -extern void pcpy(poly_t *dest, const poly_t src); -extern void pcanon(poly_t *poly); -extern void pnorm(poly_t *poly); -extern void psnorm(poly_t *poly); -extern void pchop(poly_t *poly); -extern void pkchop(poly_t *poly); -extern unsigned long plen(const poly_t poly); -extern int pcmp(const poly_t *a, const poly_t *b); -extern int psncmp(const poly_t *a, const poly_t *b); -extern int ptst(const poly_t poly); -extern unsigned long pfirst(const poly_t poly); -extern unsigned long plast(const poly_t poly); -extern poly_t psubs(const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); -extern void pright(poly_t *poly, unsigned long length); -extern void pshift(poly_t *dest, const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); -extern void ppaste(poly_t *dest, const poly_t src, unsigned long skip, unsigned long seek, unsigned long end, unsigned long fulllength); -extern void pdiff(poly_t *dest, const poly_t src, unsigned long ofs); -extern void psum(poly_t *dest, const poly_t src, unsigned long ofs); -extern void prev(poly_t *poly); -extern void prevch(poly_t *poly, int bperhx); -extern void prcp(poly_t *poly); -extern void pinv(poly_t *poly); -extern poly_t pmod(const poly_t dividend, const poly_t divisor); -extern poly_t pcrc(const poly_t message, const poly_t divisor, const poly_t init, const poly_t xorout, int flags); -extern int piter(poly_t *poly); -extern void palloc(poly_t *poly, unsigned long length); -extern void pfree(poly_t *poly); -extern void praloc(poly_t *poly, unsigned long length); -extern int pmpar(const poly_t poly, const poly_t mask); -extern int pident(const poly_t a, const poly_t b); +poly_t filtop(FILE *input, unsigned long length, int flags, int bperhx); +poly_t strtop(const char *string, int flags, int bperhx); +char *ptostr(const poly_t poly, int flags, int bperhx); +char *pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned long end); +poly_t pclone(const poly_t poly); +void pcpy(poly_t *dest, const poly_t src); +void pcanon(poly_t *poly); +void pnorm(poly_t *poly); +void psnorm(poly_t *poly); +void pchop(poly_t *poly); +void pkchop(poly_t *poly); +unsigned long plen(const poly_t poly); +int pcmp(const poly_t *a, const poly_t *b); +int psncmp(const poly_t *a, const poly_t *b); +int ptst(const poly_t poly); +unsigned long pfirst(const poly_t poly); +unsigned long plast(const poly_t poly); +poly_t psubs(const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); +void pright(poly_t *poly, unsigned long length); +void pshift(poly_t *dest, const poly_t src, unsigned long head, unsigned long start, unsigned long end, unsigned long tail); +void ppaste(poly_t *dest, const poly_t src, unsigned long skip, unsigned long seek, unsigned long end, unsigned long fulllength); +void pdiff(poly_t *dest, const poly_t src, unsigned long ofs); +void psum(poly_t *dest, const poly_t src, unsigned long ofs); +void prev(poly_t *poly); +void prevch(poly_t *poly, int bperhx); +void prcp(poly_t *poly); +void pinv(poly_t *poly); +poly_t pmod(const poly_t dividend, const poly_t divisor); +poly_t pcrc(const poly_t message, const poly_t divisor, const poly_t init, const poly_t xorout, int flags); +int piter(poly_t *poly); +void palloc(poly_t *poly, unsigned long length); +void pfree(poly_t *poly); +void praloc(poly_t *poly, unsigned long length); +int pmpar(const poly_t poly, const poly_t mask); +int pident(const poly_t a, const poly_t b); /* model.c */ @@ -190,23 +190,23 @@ typedef struct { const char *name; /* optional canonical name of the model */ } model_t; -extern void mcpy(model_t *dest, const model_t *src); -extern void mfree(model_t *model); -extern int mcmp(const model_t *a, const model_t *b); -extern char *mtostr(const model_t *model); -extern void mcanon(model_t *model); -extern void mcheck(model_t *model); -extern void mrev(model_t *model); -extern void mnovel(model_t *model); +void mcpy(model_t *dest, const model_t *src); +void mfree(model_t *model); +int mcmp(const model_t *a, const model_t *b); +char *mtostr(const model_t *model); +void mcanon(model_t *model); +void mcheck(model_t *model); +void mrev(model_t *model); +void mnovel(model_t *model); /* preset.c */ #define M_OVERWR 1 -extern int mbynam(model_t *dest, const char *key); -extern void mbynum(model_t *dest, int num); -extern int mcount(void); -extern char *mnames(void); -extern void mmatch(model_t *model, int flags); +int mbynam(model_t *dest, const char *key); +void mbynum(model_t *dest, int num); +int mcount(void); +char *mnames(void); +void mmatch(model_t *model, int flags); /* reveng.c */ #define R_HAVEP 1 @@ -218,7 +218,7 @@ extern void mmatch(model_t *model, int flags); #define R_SPMASK 0x7FFFFFFUL -extern model_t *reveng(const model_t *guess, const poly_t qpoly, int rflags, int args, const poly_t *argpolys); +model_t *reveng(const model_t *guess, const poly_t qpoly, int rflags, int args, const poly_t *argpolys); /* cli.c */ #define C_INFILE 1 @@ -228,9 +228,9 @@ extern model_t *reveng(const model_t *guess, const poly_t qpoly, int rflags, int #define BUFFER 32768 -extern int reveng_main(int argc, char *argv[]); -extern void ufound(const model_t *model); -extern void uerror(const char *msg); -extern void uprog(const poly_t gpoly, int flags, unsigned long seq); +int reveng_main(int argc, char *argv[]); +void ufound(const model_t *model); +void uerror(const char *msg); +void uprog(const poly_t gpoly, int flags, unsigned long seq); #endif /* REVENG_H */ From 26eb54b965056f718d115c3d48add52f73dd22a5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 01:00:54 +0200 Subject: [PATCH 064/141] style --- armsrc/BigBuf.h | 36 ++++++++--------- armsrc/Standalone/standalone.h | 2 +- armsrc/apps.h | 12 +++--- armsrc/buzzer.h | 10 ++--- armsrc/flashmem.h | 2 +- armsrc/fpgaloader.h | 2 +- armsrc/hitag2_crypto.h | 14 +++---- armsrc/iso14443a.h | 62 ++++++++++++++--------------- armsrc/iso14443b.h | 14 +++---- armsrc/legicrf.h | 6 +-- armsrc/legicrfsim.h | 2 +- armsrc/ticks.h | 12 +++--- armsrc/util.h | 6 +-- common/crapto1/crapto1.h | 2 +- common/crc.h | 26 ++++++------ common/lfdemod.c | 2 +- common/lfdemod.h | 72 +++++++++++++++++----------------- common/usb_cdc.h | 30 +++++++------- include/legic_prng.h | 8 ++-- 19 files changed, 160 insertions(+), 160 deletions(-) diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index bdd2003be..12f2521c6 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -25,22 +25,22 @@ #define CARD_MEMORY_SIZE 4096 #define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? -extern uint8_t *BigBuf_get_addr(void); -extern uint8_t *BigBuf_get_EM_addr(void); -extern uint16_t BigBuf_max_traceLen(void); -extern void BigBuf_Clear(void); -extern void BigBuf_Clear_ext(bool verbose); -extern void BigBuf_Clear_keep_EM(void); -extern void BigBuf_Clear_EM(void); -extern uint8_t *BigBuf_malloc(uint16_t); -extern void BigBuf_free(void); -extern void BigBuf_free_keep_EM(void); -extern void BigBuf_print_status(void); -extern uint32_t BigBuf_get_traceLen(void); -extern void clear_trace(void); -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 uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); +uint8_t *BigBuf_get_addr(void); +uint8_t *BigBuf_get_EM_addr(void); +uint16_t BigBuf_max_traceLen(void); +void BigBuf_Clear(void); +void BigBuf_Clear_ext(bool verbose); +void BigBuf_Clear_keep_EM(void); +void BigBuf_Clear_EM(void); +uint8_t *BigBuf_malloc(uint16_t); +void BigBuf_free(void); +void BigBuf_free_keep_EM(void); +void BigBuf_print_status(void); +uint32_t BigBuf_get_traceLen(void); +void clear_trace(void); +void set_tracing(bool enable); +void set_tracelen(uint32_t value); +bool get_tracing(void); +bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); +uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length); #endif /* __BIGBUF_H */ diff --git a/armsrc/Standalone/standalone.h b/armsrc/Standalone/standalone.h index 980bcbf46..334bbc2b4 100644 --- a/armsrc/Standalone/standalone.h +++ b/armsrc/Standalone/standalone.h @@ -14,6 +14,6 @@ #include // for bool #include // PRIu64 -extern void RunMod(); +void RunMod(); #endif /* __STANDALONE_H */ diff --git a/armsrc/apps.h b/armsrc/apps.h index b1a0969f3..5838c4d8e 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -65,8 +65,8 @@ void ListenReaderField(int limit); extern int ToSendMax; extern uint8_t ToSend[]; -extern void StandAloneMode(void); -extern void printStandAloneModes(void); +void StandAloneMode(void); +void printStandAloneModes(void); /// lfops.h extern uint8_t decimation; @@ -230,10 +230,10 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void void HfSniff(int, int); //felica.c -extern void felica_sendraw(UsbCommand *c); -extern void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); -extern void felica_sim_lite(uint64_t uid); -extern void felica_dump_lite_s(); +void felica_sendraw(UsbCommand *c); +void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip); +void felica_sim_lite(uint64_t uid); +void felica_dump_lite_s(); #ifdef __cplusplus diff --git a/armsrc/buzzer.h b/armsrc/buzzer.h index 801b35a21..082450f04 100644 --- a/armsrc/buzzer.h +++ b/armsrc/buzzer.h @@ -20,11 +20,11 @@ #define note_7 506 #define note_8 0 -extern void Ring_BEE_ONCE(uint16_t music_note); -extern void Ring_BEE_TIME(uint16_t music_note, uint16_t count); -extern void ring_2_7khz(uint16_t count); -extern void Ring_ALL(uint16_t count); -extern void Ring_Little_Star(uint16_t count); +void Ring_BEE_ONCE(uint16_t music_note); +void Ring_BEE_TIME(uint16_t music_note, uint16_t count); +void ring_2_7khz(uint16_t count); +void Ring_ALL(uint16_t count); +void Ring_Little_Star(uint16_t count); #endif diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index f4258a11b..012d6ae7f 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -115,7 +115,7 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -extern void Dbprintf(const char *fmt, ...); +void Dbprintf(const char *fmt, ...); void FlashmemSetSpiBaudrate(uint32_t baudrate); bool FlashInit(); diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index ef278cc3e..f9b0e44b0 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -37,7 +37,7 @@ int FpgaGetCurrent(void); void SetAdcMuxFor(uint32_t whichGpio); // extern and generel turn off the antenna method -extern void switch_off(void); +void switch_off(void); // definitions for multiple FPGA config files support #define FPGA_BITSTREAM_LF 1 diff --git a/armsrc/hitag2_crypto.h b/armsrc/hitag2_crypto.h index 8af1af412..d874955e0 100644 --- a/armsrc/hitag2_crypto.h +++ b/armsrc/hitag2_crypto.h @@ -22,13 +22,13 @@ struct hitag2_tag { 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) ; +uint32_t _f20(const uint64_t x); +uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV); +uint64_t _hitag2_round(uint64_t *state); +uint32_t _hitag2_byte(uint64_t *x); +void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv); +int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is); +int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ; #ifdef __cplusplus } #endif diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 777932540..baebe4fc5 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -97,45 +97,45 @@ typedef struct { # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) #endif -extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); +void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); -extern tDemod *GetDemod(void); -extern void DemodReset(void); -extern void DemodInit(uint8_t *data, uint8_t *parity); -extern tUart *GetUart(void); -extern void UartReset(void); -extern void UartInit(uint8_t *data, uint8_t *parity); -extern RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); -extern RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time); +tDemod *GetDemod(void); +void DemodReset(void); +void DemodInit(uint8_t *data, uint8_t *parity); +tUart *GetUart(void); +void UartReset(void); +void UartInit(uint8_t *data, uint8_t *parity); +RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); +RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time); -extern void RAMFUNC SniffIso14443a(uint8_t param); -extern void SimulateIso14443aTag(int tagType, int flags, uint8_t *data); -extern void iso14443a_antifuzz(uint32_t flags); -extern void ReaderIso14443a(UsbCommand *c); -extern void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing); -extern void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing); -extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing); -extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); +void RAMFUNC SniffIso14443a(uint8_t param); +void SimulateIso14443aTag(int tagType, int flags, uint8_t *data); +void iso14443a_antifuzz(uint32_t flags); +void ReaderIso14443a(UsbCommand *c); +void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing); +void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing); +void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing); +int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); -extern void iso14443a_setup(uint8_t fpga_minor_mode); -extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res); -extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); -extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); -extern void iso14a_set_trigger(bool enable); +void iso14443a_setup(uint8_t fpga_minor_mode); +int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res); +int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); +int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); +void iso14a_set_trigger(bool enable); -extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); -extern int EmSend4bit(uint8_t resp); -extern int EmSendCmd(uint8_t *resp, uint16_t respLen); -extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision); -extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); -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); +int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); +int EmSend4bit(uint8_t resp); +int EmSendCmd(uint8_t *resp, uint16_t respLen); +int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision); +int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); +int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); +int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision); +int EmSendPrecompiledCmd(tag_response_info_t *response_info); 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); +//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(); diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h index e3c6c1dc8..cf16d48aa 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -34,15 +34,15 @@ extern "C" { # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) #endif -extern void SendRawCommand14443B_Ex(UsbCommand *c); -extern void iso14443b_setup(); -extern uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); -extern uint8_t iso14443b_select_card(iso14b_card_select_t *card); -extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card); +void SendRawCommand14443B_Ex(UsbCommand *c); +void iso14443b_setup(); +uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); +uint8_t iso14443b_select_card(iso14b_card_select_t *card); +uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card); // testfunctions -extern void WaitForFpgaDelayQueueIsEmpty(uint16_t delay); -extern void ClearFpgaShiftingRegisters(void); +void WaitForFpgaDelayQueueIsEmpty(uint16_t delay); +void ClearFpgaShiftingRegisters(void); // States for 14B SIM command #define SIM_NOFIELD 0 diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 1c275a1ed..9deb445bd 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -14,8 +14,8 @@ #include "proxmark3.h" -extern void LegicRfInfo(void); -extern void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); -extern void LegicRfWriter(uint16_t offset, uint16_t byte, uint8_t iv, uint8_t *data); +void LegicRfInfo(void); +void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); +void LegicRfWriter(uint16_t offset, uint16_t byte, uint8_t iv, uint8_t *data); #endif /* __LEGICRF_H */ diff --git a/armsrc/legicrfsim.h b/armsrc/legicrfsim.h index da70bff0c..27fce129b 100644 --- a/armsrc/legicrfsim.h +++ b/armsrc/legicrfsim.h @@ -14,6 +14,6 @@ #include "proxmark3.h" -extern void LegicRfSimulate(uint8_t tagtype); +void LegicRfSimulate(uint8_t tagtype); #endif /* __LEGICRFSIM_H */ diff --git a/armsrc/ticks.h b/armsrc/ticks.h index d24d2aac5..c6715e177 100644 --- a/armsrc/ticks.h +++ b/armsrc/ticks.h @@ -37,11 +37,11 @@ void StartCountSspClk(); void ResetSspClk(void); uint32_t RAMFUNC GetCountSspClk(); -extern void StartTicks(void); -extern uint32_t GetTicks(void); -extern void WaitTicks(uint32_t ticks); -extern void WaitUS(uint16_t us); -extern void WaitMS(uint16_t ms); +void StartTicks(void); +uint32_t GetTicks(void); +void WaitTicks(uint32_t ticks); +void WaitUS(uint16_t us); +void WaitMS(uint16_t ms); -extern void StopTicks(void); +void StopTicks(void); #endif diff --git a/armsrc/util.h b/armsrc/util.h index 15f93d1f9..fc519fe43 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -84,9 +84,9 @@ size_t nbytes(size_t nbits); -extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... -extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal -extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal +uint32_t reflect(uint32_t v, int b); // used in crc.c ... +uint8_t reflect8(uint8_t b); // dedicated 8bit reversal +uint16_t reflect16(uint16_t b); // dedicated 16bit reversal void num_to_bytes(uint64_t n, size_t len, uint8_t *dest); uint64_t bytes_to_num(uint8_t *src, size_t len); diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index 251a25089..49a784cf9 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -51,7 +51,7 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb); uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb); uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); -extern bool validate_prng_nonce(uint32_t nonce); +bool validate_prng_nonce(uint32_t nonce); #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ uint32_t __n = 0,__M = 0, N = 0;\ int __i;\ diff --git a/common/crc.h b/common/crc.h index 368758f40..dee8403c9 100644 --- a/common/crc.h +++ b/common/crc.h @@ -30,25 +30,25 @@ typedef struct crc { * refin is the setting for reversing (bitwise) the bytes during crc * refot is the setting for reversing (bitwise) the crc byte before returning it. */ -extern void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout); +void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout); /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 * polynom is the CRC polynom. initial_value is the initial value of a clean state. * final_xor is XORed onto the state before returning it from crc_result(). */ -extern void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor); +void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor); /* Update the crc state. data is the data of length data_width bits (only the * data_width lower-most bits are used). */ -extern void crc_update(crc_t *crc, uint32_t data, int data_width); -extern void crc_update2(crc_t *crc, uint32_t data, int data_width); +void crc_update(crc_t *crc, uint32_t data, int data_width); +void crc_update2(crc_t *crc, uint32_t data, int data_width); /* Clean the crc state, e.g. reset it to initial_value */ -extern void crc_clear(crc_t *crc); +void crc_clear(crc_t *crc); /* Get the result of the crc calculation */ -extern uint32_t crc_finish(crc_t *crc); +uint32_t crc_finish(crc_t *crc); // Calculate CRC-8/Maxim checksum uint32_t CRC8Maxim(uint8_t *buff, size_t size); @@ -65,13 +65,13 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size); /* Static initialization of a crc structure */ #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) \ - .refin = false, \ - .refout = false \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) \ + .refin = false, \ + .refout = false \ } #endif /* __CRC_H */ diff --git a/common/lfdemod.c b/common/lfdemod.c index 17e38caa7..8c4a6b855 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -51,7 +51,7 @@ //to allow debug print calls when used not on dev //void dummy(char *fmt, ...){} -extern void Dbprintf(const char *fmt, ...); +void Dbprintf(const char *fmt, ...); #ifndef ON_DEVICE #include "ui.h" diff --git a/common/lfdemod.h b/common/lfdemod.h index 9a807a02c..32421dea0 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -45,42 +45,42 @@ void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i); bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low); size_t pskFindFirstPhaseShift(uint8_t *samples, size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen); -extern size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType); -extern int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType); -extern int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx); -extern void askAmp(uint8_t *bits, size_t size); -extern int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert); -extern uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); -extern uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); -extern uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); -extern uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj); -extern int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr); -extern bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); -extern uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); -extern int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx); -extern int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); -extern int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clock); -extern bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, size_t *stend); -extern size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *start_idx); -//extern void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); -extern void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); -extern uint32_t manchesterEncode2Bytes(uint16_t datain); -extern int ManchesterEncode(uint8_t *bits, size_t size); -extern int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos); -extern int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx); -extern bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); -extern bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); -extern bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); -extern int pskRawDemod(uint8_t *dest, size_t *size, int *clock, int *invert); -extern int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx); -extern void psk2TOpsk1(uint8_t *bits, size_t size); -extern void psk1TOpsk2(uint8_t *bits, size_t size); -extern size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); +size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType); +int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType); +int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx); +void askAmp(uint8_t *bits, size_t size); +int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert); +uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); +uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); +uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); +uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj); +int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr); +bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); +uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); +int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx); +int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); +int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clock); +bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, size_t *stend); +size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *start_idx); +//void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +uint32_t manchesterEncode2Bytes(uint16_t datain); +int ManchesterEncode(uint8_t *bits, size_t size); +int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos); +int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx); +bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); +bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); +bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); +int pskRawDemod(uint8_t *dest, size_t *size, int *clock, int *invert); +int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx); +void psk2TOpsk1(uint8_t *bits, size_t size); +void psk1TOpsk2(uint8_t *bits, size_t size); +size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen); //tag specific -extern int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx); -extern int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, uint64_t *lo); -extern int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); -extern int detectIdteck(uint8_t *dest, size_t *size); -extern int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); +int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx); +int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, uint64_t *lo); +int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx); +int detectIdteck(uint8_t *dest, size_t *size); +int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx); #endif diff --git a/common/usb_cdc.h b/common/usb_cdc.h index 1e735faa6..3b95a11c1 100644 --- a/common/usb_cdc.h +++ b/common/usb_cdc.h @@ -41,23 +41,23 @@ #include "proxmark3.h" // USB_CONNECT() #include "common.h" -extern void usb_disable(); -extern void usb_enable(); -extern bool usb_check(); -extern bool usb_poll(); -extern bool usb_poll_validate_length(); -extern uint32_t usb_read(uint8_t *data, size_t len); -extern uint32_t usb_write(const uint8_t *data, const size_t len); +void usb_disable(); +void usb_enable(); +bool usb_check(); +bool usb_poll(); +bool usb_poll_validate_length(); +uint32_t usb_read(uint8_t *data, size_t len); +uint32_t usb_write(const uint8_t *data, const size_t len); -extern void SetUSBreconnect(int value); -extern int GetUSBreconnect(void); -extern void SetUSBconfigured(int value); -extern int GetUSBconfigured(void); +void SetUSBreconnect(int value); +int GetUSBreconnect(void); +void SetUSBconfigured(int value); +int GetUSBconfigured(void); -extern void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length); -extern void AT91F_USB_SendZlp(AT91PS_UDP pUdp); -extern void AT91F_USB_SendStall(AT91PS_UDP pUdp); -extern void AT91F_CDC_Enumerate(); +void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length); +void AT91F_USB_SendZlp(AT91PS_UDP pUdp); +void AT91F_USB_SendStall(AT91PS_UDP pUdp); +void AT91F_CDC_Enumerate(); #endif // _USB_CDC_H_ diff --git a/include/legic_prng.h b/include/legic_prng.h index 16855ab90..8f37e04a1 100644 --- a/include/legic_prng.h +++ b/include/legic_prng.h @@ -10,9 +10,9 @@ #define __LEGIC_PRNG_H #include -extern void legic_prng_init(uint8_t iv); -extern void legic_prng_forward(int count); -extern uint8_t legic_prng_get_bit(); -extern uint32_t legic_prng_get_bits(uint8_t len); +void legic_prng_init(uint8_t iv); +void legic_prng_forward(int count); +uint8_t legic_prng_get_bit(); +uint32_t legic_prng_get_bits(uint8_t len); #endif From 127dc746744ec57f7c21602c6f502fc75471ead0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 6 Apr 2019 15:50:45 +0200 Subject: [PATCH 065/141] chg: only english --- armsrc/mifaredesfire.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 3bbf667b5..050de439e 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -195,11 +195,11 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain LED_B_OFF(); LED_C_OFF(); - // 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) - // 4 olika crypto algo DES, 3DES, 3K3DES, AES - // 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO + // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) + // 4 different crypto algo DES, 3DES, 3K3DES, AES + // 3 different communication modes, PLAIN,MAC,CRYPTO - // des, nyckel 0, + // des, key 0, switch (mode) { case 1: { uint8_t keybytes[16]; @@ -495,7 +495,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain cmd_send(CMD_ACK, 1, len, 0, resp, len); } -// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) +// 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO) // cmd = cmd bytes to send // cmd_len = length of cmd // dataout = pointer to response data array @@ -540,7 +540,7 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) { uint8_t cmd[cmdlen]; memset(cmd, 0, cmdlen); - cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar // + cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid. cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards From 41f36ca20b339246848e512a039c2cf18943bed8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 19:09:01 +0200 Subject: [PATCH 066/141] make style --- armsrc/iso14443a.c | 36 ++++++++++++------------ armsrc/iso14443a.h | 2 +- armsrc/mifaredesfire.c | 2 +- armsrc/mifaresim.h | 2 +- client/cmdhf15.c | 2 +- client/cmdhfmf.c | 2 +- client/cmdhfmfu.c | 2 +- client/cmdlft55xx.c | 6 ++-- client/scripting.c | 52 +++++++++++++++++------------------ client/scripts/test_t55x7.lua | 48 ++++++++++++++++---------------- client/util.h | 4 +-- common/crc.h | 14 +++++----- common/lfdemod.c | 6 ++-- 13 files changed, 89 insertions(+), 89 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 0f8d61888..13af0cfb4 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1140,24 +1140,24 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) { AddCrc14A(emdata, len); EmSendCmd(emdata, len + 2); p_response = NULL; - } else if ((receivedCmd[0] == MIFARE_ULC_WRITE || receivedCmd[0] == MIFARE_ULC_COMP_WRITE) && (tagType == 2 || tagType == 7)) { // Received a WRITE - // cmd + block + 4/16 bytes data + 2 bytes crc - if (len == 8 || len == 20) { - bool isCrcCorrect = CheckCrc14A(receivedCmd, len); - if (isCrcCorrect) { - int block = receivedCmd[1] + 12; // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] - emlSetMem_xt(&receivedCmd[2], block, 1, 4); - // send ACK - EmSend4bit(CARD_ACK); - } else { - // send NACK 0x1 == crc/parity error - EmSend4bit(CARD_NACK_PA); - } - } else { - // send NACK 0x0 == invalid argument - EmSend4bit(CARD_NACK_IV); - } - p_response = NULL; + } else if ((receivedCmd[0] == MIFARE_ULC_WRITE || receivedCmd[0] == MIFARE_ULC_COMP_WRITE) && (tagType == 2 || tagType == 7)) { // Received a WRITE + // cmd + block + 4/16 bytes data + 2 bytes crc + if (len == 8 || len == 20) { + bool isCrcCorrect = CheckCrc14A(receivedCmd, len); + if (isCrcCorrect) { + int block = receivedCmd[1] + 12; // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + emlSetMem_xt(&receivedCmd[2], block, 1, 4); + // send ACK + EmSend4bit(CARD_ACK); + } else { + // send NACK 0x1 == crc/parity error + EmSend4bit(CARD_NACK_PA); + } + } else { + // send NACK 0x0 == invalid argument + EmSend4bit(CARD_NACK_IV); + } + p_response = NULL; } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint16_t start = 4 * 4; diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 2fba30ce4..d43ba6565 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -106,7 +106,7 @@ typedef struct { #ifndef CheckCrc14A # define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len)) -#endif +#endif void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 050de439e..1bddf3374 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -540,7 +540,7 @@ size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) { uint8_t cmd[cmdlen]; memset(cmd, 0, cmdlen); - cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid. + cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid. cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index c7dab05c5..c735cc1dd 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -41,4 +41,4 @@ extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, u // 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 +#endif diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 55e4aa478..31d266d6d 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -848,7 +848,7 @@ int CmdHF15Restore(const char *Cmd) { } PrintAndLogEx(INFO, "Restoring data blocks."); - + while (1) { tried = 0; hex[0] = 0x00; diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index fdbaa7563..f00093acb 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1060,7 +1060,7 @@ int CmdHF14AMfRestore(const char *Cmd) { } } fclose(fdump); - PrintAndLogEx(INFO, "Finish restore"); + PrintAndLogEx(INFO, "Finish restore"); return 0; } diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index ac1391c47..f20665df6 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2221,7 +2221,7 @@ int CmdHF14AMfURestore(const char *Cmd) { DropField(); free(dump); - PrintAndLogEx(INFO, "Finish restore"); + PrintAndLogEx(INFO, "Finish restore"); return 0; } // diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index dd02db95e..61507cea4 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -547,7 +547,7 @@ int CmdT55xxDetect(const char *Cmd) { } if (!tryDetectModulation()) - PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'") ); + PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with " _YELLOW_("\'lf t55xx config\'")); return 0; } @@ -767,7 +767,7 @@ bool GetT55xxBlockData(uint32_t *blockdata) { return false; uint8_t idx = config.offset; - + if (idx + 32 > DemodBufferLen) { PrintAndLogEx(WARNING, "The configured offset %d is too big. Possible offset: %d)", idx, DemodBufferLen - 32); return false; @@ -1472,7 +1472,7 @@ int CmdT55xxInfo(const char *Cmd) { if (((!gotdata) && (!config.Q5)) || (gotdata && (!dataasq5))) printT5x7KnownBlock0(block0); - + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); return 0; diff --git a/client/scripting.c b/client/scripting.c index d4efac99f..4d8aa5fe8 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -702,46 +702,46 @@ static int l_keygen_algoD(lua_State *L) { } /* -Read T55Xx block. +Read T55Xx block. param1 uint8_t block param2 bool page1 param3 bool override param4 uint32_t password */ static int l_T55xx_readblock(lua_State *L) { - + //Check number of arguments int n = lua_gettop(L); - if ( n != 4 ) { - return returnToLuaWithError(L, "Wrong number of arguments, got %d bytes, expected 4", n); + if (n != 4) { + return returnToLuaWithError(L, "Wrong number of arguments, got %d bytes, expected 4", n); } - + uint32_t block, usepage1, override, password; bool usepwd; size_t size; - + const char *p_blockno = luaL_checklstring(L, 1, &size); if (size < 1 || size > 2) return returnToLuaWithError(L, "Wrong size of blockNo, got %d, expected 1 or 2", (int) size); sscanf(p_blockno, "%x", &block); - + const char *p_usepage1 = luaL_checklstring(L, 2, &size); if (size != 1) return returnToLuaWithError(L, "Wrong size of usePage1, got %d, expected 1", (int) size); sscanf(p_usepage1, "%x", &usepage1); - + const char *p_override = luaL_checklstring(L, 3, &size); if (size != 1) return returnToLuaWithError(L, "Wrong size of override, got %d, expected 1", (int) size); sscanf(p_override, "%x", &override); - + const char *p_pwd = luaL_checklstring(L, 4, &size); - if ( size == 0 ) { + if (size == 0) { usepwd = false; } else { if (size != 8) return returnToLuaWithError(L, "Wrong size of pwd, got %d , expected 8", (int) size); sscanf(p_pwd, "%08x", &password); usepwd = true; - } - + } + //Password mode if (usepwd) { // try reading the config block and verify that PWD bit is set before doing this! @@ -767,16 +767,16 @@ static int l_T55xx_readblock(lua_State *L) { if (!AquireData(usepage1, block, usepwd, password)) { return returnToLuaWithError(L, "Failed to aquire data from card"); } - + if (!DecodeT55xxBlock()) { return returnToLuaWithError(L, "Failed to decode signal"); } - + uint32_t blockData = 0; if (GetT55xxBlockData(&blockData) == false) { return returnToLuaWithError(L, "Failed to get actual data"); } - + lua_pushunsigned(L, blockData); return 1; } @@ -787,7 +787,7 @@ static int l_T55xx_detect(lua_State *L) { bool useGB = false, usepwd = false, isok; uint32_t gb, password = 0; size_t size; - + //Check number of arguments int n = lua_gettop(L); @@ -796,15 +796,15 @@ static int l_T55xx_detect(lua_State *L) { const char *p_gb = luaL_checklstring(L, 2, &size); if (size != 1) return returnToLuaWithError(L, "Wrong size of useGB, got %d , expected 1", (int) size); sscanf(p_gb, "%u", &gb); - useGB = ( gb ) ? true : false; - printf("p_gb size %zu | %c \n", size, useGB ? 'Y':'N'); + useGB = (gb) ? true : false; + printf("p_gb size %zu | %c \n", size, useGB ? 'Y' : 'N'); } case 1: { const char *p_pwd = luaL_checklstring(L, 1, &size); - if ( size == 0 ) { + if (size == 0) { usepwd = false; } else { - + if (size != 8) return returnToLuaWithError(L, "Wrong size of pwd, got %d , expected 8", (int) size); sscanf(p_pwd, "%08x", &password); usepwd = true; @@ -814,24 +814,24 @@ static int l_T55xx_detect(lua_State *L) { default : break; } - + if (!useGB) { - + isok = AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password); - if ( isok == false ) { + if (isok == false) { // signal error by returning Nil, errorstring lua_pushnil(L); lua_pushstring(L, "Failed to aquire LF signal data"); return 2; } } - + isok = tryDetectModulation(); - if ( isok == false ) { + if (isok == false) { // signal error by returning Nil, errorstring lua_pushnil(L); lua_pushstring(L, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - return 2; + return 2; } lua_pushinteger(L, isok); diff --git a/client/scripts/test_t55x7.lua b/client/scripts/test_t55x7.lua index 3d21cc9e5..710df0c3f 100644 --- a/client/scripts/test_t55x7.lua +++ b/client/scripts/test_t55x7.lua @@ -44,7 +44,7 @@ local DEBUG = false -- the debug flag local total_tests = 0 local total_pass = 0 -local data_blocks_cmds = { +local data_blocks_cmds = { [1] = '00000000', [2] = 'ffffffff', [3] = '80000000', @@ -96,10 +96,10 @@ end local function GetConfigs( modulation ) local t = {} - + t['PSK1'] = { [1] = '00001040', - [2] = '00041040', + [2] = '00041040', [3] = '00081040', [4] = '000c1040', [5] = '00101040', @@ -118,7 +118,7 @@ local function GetConfigs( modulation ) [7] = '00182040', [8] = '001c2040', } - + t['PSK3'] = { [1] = '00003040', [2] = '00043040', @@ -141,7 +141,7 @@ local function GetConfigs( modulation ) [8] = '00184040', [9] = '001c4040', } - + t['FSK2'] = { [1] = '00005040', [2] = '00045040', @@ -152,7 +152,7 @@ local function GetConfigs( modulation ) [7] = '00185040', [8] = '001c5040', } - + t['FSK1A'] = { [1] = '00006040', [2] = '00046040', @@ -163,7 +163,7 @@ local function GetConfigs( modulation ) [7] = '00186040', [8] = '001c6040', } - + t['FSK2A'] = { [1] = '00007040', [2] = '00047040', @@ -174,10 +174,10 @@ local function GetConfigs( modulation ) [7] = '00187040', [8] = '001c7040', } - + t['ASK'] = { [1] = '00008040', - [2] = '00048040', + [2] = '00048040', [3] = '00088040', [4] = '000c8040', [5] = '00108040', @@ -185,7 +185,7 @@ local function GetConfigs( modulation ) [7] = '00188040', [8] = '001c8040', } - + t['BI'] = { [1] = '00010040', [2] = '00050040', @@ -196,7 +196,7 @@ local function GetConfigs( modulation ) [7] = '00190040', [8] = '001d0040', } - + return t[modulation:upper()] end --- @@ -205,10 +205,10 @@ local function WipeCard() print('Wiping card') core.console('lf t55xx wipe') - + print('Detecting card') local res, msg = core.t55xx_detect() - if not res then + if not res then oops("Can't detect modulation. Test failed.") core.console("rem [ERR:DETECT:WIPED] Failed to detect after wipe") return false @@ -235,20 +235,20 @@ local function CheckReadBlock(block) end local function test(modulation) - + local process_block0_cmds = {} local y local block = "00" - + local s = ('Start test of %s'):format(modulation) print(s) - + process_block0_cmds = GetConfigs(modulation) - + if process_block0_cmds == nil then return oops('Cant find modulation '..modulation) end - + for _ = 1, #process_block0_cmds do - + local p_config_cmd = process_block0_cmds[_] local errors = 0 core.clearCommandBuffer() @@ -261,9 +261,9 @@ local function test(modulation) if err then return oops(err) end local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - -- Detect + -- Detect local res, msg = core.t55xx_detect() - if not res then + if not res then print("can't detect modulation, skip to next config") core.console(format("rem [ERR:DETECT:%s] Failed to detect modulation", p_config_cmd)) core.console(format('rem [SUMMARY:%s] FAIL detection', p_config_cmd)) @@ -304,11 +304,11 @@ local function main(args) core.clearCommandBuffer() local res - + -- Adjust this table to set which configurations should be tested -- local test_modes = { 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2', 'FSK1A', 'FSK2A', 'ASK', 'BI' } local test_modes = { 'ASK', 'PSK1' } - + for _ = 1, #test_modes do res = WipeCard() if res then @@ -322,6 +322,6 @@ local function main(args) exitMsg('Tests finished') core.console( format('rem [SUMMARY] Success rate: %d/%d tests passed%s', total_pass, total_tests, total_pass < total_tests and ", help me improving that number!" or " \\o/")) - + end main(args) diff --git a/client/util.h b/client/util.h index 208ae61f0..83a5c87cd 100644 --- a/client/util.h +++ b/client/util.h @@ -200,8 +200,8 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); bool CheckStringIsHEXValue(const char *value); void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, - const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, - bool uppercase); + const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, + bool uppercase); void print_hex(const uint8_t *data, const size_t len); void print_hex_break(const uint8_t *data, const size_t len, const uint8_t breaks); diff --git a/common/crc.h b/common/crc.h index dee8403c9..449b51bf3 100644 --- a/common/crc.h +++ b/common/crc.h @@ -65,13 +65,13 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size); /* Static initialization of a crc structure */ #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) \ - .refin = false, \ - .refout = false \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) \ + .refin = false, \ + .refout = false \ } #endif /* __CRC_H */ diff --git a/common/lfdemod.c b/common/lfdemod.c index 8c4a6b855..dfe959a37 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1620,7 +1620,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); return -1; } - + size_t clkStartIdx = 0; *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); if (*clk == 0) return -2; @@ -1911,13 +1911,13 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s if (waveLenCnt > fc) { //this wave is a phase shift /* - prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d" + prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d" , waveStart , waveLenCnt , lastClkBit + *clock - tol , i + 1 , fc); - */ + */ if (i + 1 >= lastClkBit + *clock - tol) { //should be a clock bit curPhase ^= 1; dest[numBits++] = curPhase; From 1b9914288d2e9933ac3a654c9ba965582df848d2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 19:10:34 +0200 Subject: [PATCH 067/141] remove extern --- armsrc/mifaresim.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/mifaresim.h b/armsrc/mifaresim.h index c735cc1dd..65eabdf68 100644 --- a/armsrc/mifaresim.h +++ b/armsrc/mifaresim.h @@ -15,7 +15,7 @@ #include -extern void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); +void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain); #define AC_DATA_READ 0 #define AC_DATA_WRITE 1 From a27d549a6082731510de9563ed62fd0a5058b6ce Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 19:48:20 +0200 Subject: [PATCH 068/141] WritePageHitagS: why on earth page <> page_ --- armsrc/hitagS.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index cd9573243..5c7bec491 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -1451,7 +1451,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { * Authenticates to the Tag with the given Key or Challenge. * Writes the given 32Bit data into page_ */ -void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { +void WritePageHitagS(hitag_function htf, hitag_data *htd, int page) { StopTicks(); @@ -1467,7 +1467,6 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; - int page = page_; unsigned char crc; uint8_t data[4] = {0, 0, 0, 0}; @@ -1509,7 +1508,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } - Dbprintf("Page: %d", page_); + Dbprintf("Page: %d", page); Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); tag.pstate = HT_READY; @@ -1582,7 +1581,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { if (rxlen == 0 && tag.tstate == HT_WRITING_PAGE_ACK) { //no write access on this page - Dbprintf("no write access on page %d", page_); + Dbprintf("no write access on page %d", page); bStop = !false; } else if (rxlen == 0 && tag.tstate != HT_WRITING_PAGE_DATA) { //start the authetication From a52a0bf53721d99de00c31e01975d941a001b527 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 20:21:03 +0200 Subject: [PATCH 069/141] args names --- armsrc/apps.h | 18 +++++------ armsrc/iclass.c | 22 ++++++------- armsrc/iso14443a.c | 78 ++++++++++++++++++++++----------------------- armsrc/iso14443a.h | 6 ++-- armsrc/iso15693.c | 10 +++--- armsrc/legicrf.h | 2 +- armsrc/lfops.c | 6 ++-- armsrc/lfsampling.c | 4 +-- 8 files changed, 73 insertions(+), 73 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index c1893975c..529f197ca 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -99,8 +99,8 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo); void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7 void T55xxResetRead(void); -void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode); -void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode); +void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg); +void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg); void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd); void T55xxWakeUp(uint32_t Pwd); void T55xx_ChkPwds(void); @@ -130,7 +130,7 @@ void ReaderIso14443a(UsbCommand *c); // Also used in iclass.c //bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); -void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity); +void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); void iso14a_set_trigger(bool enable); // also used in emv //bool prepare_allocated_tag_modulation(tag_response_info_t *response_info); @@ -212,15 +212,15 @@ void Iso15693InitReader(void); void RAMFUNC SniffIClass(void); void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void ReaderIClass(uint8_t arg0); -void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC); -void iClass_Authentication(uint8_t *MAC); +void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac); +void iClass_Authentication(uint8_t *mac); void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); -void iClass_WriteBlock(uint8_t blockNo, uint8_t *data); -void iClass_ReadBlk(uint8_t blockNo); -bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t datalen); +void iClass_WriteBlock(uint8_t blockno, uint8_t *data); +void iClass_ReadBlk(uint8_t blockno); +bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len); 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); +void iClass_ReadCheck(uint8_t blockno, uint8_t keytype); // cmd.h uint8_t cmd_receive(UsbCommand *cmd); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 1326306b1..658962a3c 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -2107,7 +2107,7 @@ void ReaderIClass(uint8_t arg0) { } // turn off afterwards -void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { +void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) { uint8_t cardsize = 0; uint8_t mem = 0; @@ -2134,7 +2134,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { if (read_status < 2) continue; //for now replay captured auth (as cc not updated) - memcpy(check + 5, MAC, 4); + memcpy(check + 5, mac, 4); if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) { DbpString("Error: Authentication Fail!"); @@ -2227,8 +2227,8 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { // not used. ?!? ( CMD_ICLASS_READCHECK) // turn off afterwards -void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { - uint8_t readcheck[] = { keyType, blockNo }; +void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) { + uint8_t readcheck[] = { keytype, blockno }; uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0}; size_t isOK = 0; isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); @@ -2348,9 +2348,9 @@ out: // Tries to read block. // retries 10times. -bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t len) { +bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) { uint8_t resp[10]; - uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; + uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00}; AddCrc(cmd + 1, 1); // expect size 10, retry 5times bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5); @@ -2402,10 +2402,10 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { BigBuf_free(); } -bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { +bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) { uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t write[] = { ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; memcpy(write + 2, data, 12); // data + mac AddCrc(write + 1, 13); @@ -2416,7 +2416,7 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { if (memcmp(write + 2, resp, 8)) { //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) - if (blockNo != 3 && blockNo != 4) { + if (blockno != 3 && blockno != 4) { isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); } } @@ -2425,8 +2425,8 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { } // turn off afterwards -void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { - bool isOK = iClass_WriteBlock_ext(blockNo, data); +void iClass_WriteBlock(uint8_t blockno, uint8_t *data) { + bool isOK = iClass_WriteBlock_ext(blockno, data); cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); switch_off(); } diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 13af0cfb4..465b73678 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -121,12 +121,12 @@ uint32_t iso14a_get_timeout(void) { //----------------------------------------------------------------------------- // Generate the parity value for a byte sequence //----------------------------------------------------------------------------- -void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { +void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par) { uint16_t paritybit_cnt = 0; uint16_t paritybyte_cnt = 0; uint8_t parityBits = 0; - for (uint16_t i = 0; i < iLen; i++) { + for (uint16_t i = 0; i < len; i++) { // Generate the parity bits parityBits |= ((oddparity8(pbtCmd[i])) << (7 - paritybit_cnt)); if (paritybit_cnt == 7) { @@ -193,9 +193,9 @@ void UartReset(void) { Uart.syncBit = 9999; } -void UartInit(uint8_t *data, uint8_t *parity) { +void UartInit(uint8_t *data, uint8_t *par) { Uart.output = data; - Uart.parity = parity; + Uart.parity = par; UartReset(); } @@ -366,9 +366,9 @@ void DemodReset(void) { Demod.samples = 0; } -void DemodInit(uint8_t *data, uint8_t *parity) { +void DemodInit(uint8_t *data, uint8_t *par) { Demod.output = data; - Demod.parity = parity; + Demod.parity = par; DemodReset(); } @@ -636,7 +636,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { //----------------------------------------------------------------------------- // Prepare tag messages //----------------------------------------------------------------------------- -static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) { +static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par, bool collision) { //uint8_t localCol = 0; ToSendReset(); @@ -679,7 +679,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par LastProxToAirDuration = 8 * ToSendMax; } else { // Get the parity bit - if (parity[i >> 3] & (0x80 >> (i & 0x0007))) { + if (par[i >> 3] & (0x80 >> (i & 0x0007))) { ToSend[++ToSendMax] = SEC_D; LastProxToAirDuration = 8 * ToSendMax - 4; } else { @@ -774,7 +774,7 @@ static void EmLogTraceTag(uint8_t *tag_data, uint16_t tag_len, uint8_t *tag_Pari // stop when button is pressed // or return TRUE when command is captured //----------------------------------------------------------------------------- -static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) { +static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *par, 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 @@ -782,7 +782,7 @@ static int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); // Now run a `software UART` on the stream of incoming samples. - UartInit(received, parity); + UartInit(received, par); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1520,7 +1520,7 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing //----------------------------------------------------------------------------- // Prepare reader command (in bits, support short frames) to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) { +void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *par) { int i, j; int last = 0; uint8_t b; @@ -1559,9 +1559,9 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8 } // Only transmit parity bit if we transmitted a complete byte - if (j == 8 && parity != NULL) { + if (j == 8 && par != NULL) { // Get the parity bit - if (parity[i >> 3] & (0x80 >> (i & 0x0007))) { + if (par[i >> 3] & (0x80 >> (i & 0x0007))) { // Sequence X ToSend[++ToSendMax] = SEC_X; LastProxToAirDuration = 8 * (ToSendMax + 1) - 2; @@ -1599,8 +1599,8 @@ void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8 //----------------------------------------------------------------------------- // Prepare reader command to send to FPGA //----------------------------------------------------------------------------- -void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *parity) { - CodeIso14443aBitsAsReaderPar(cmd, len * 8, parity); +void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *par) { + CodeIso14443aBitsAsReaderPar(cmd, len * 8, par); } //----------------------------------------------------------------------------- @@ -1608,7 +1608,7 @@ void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *p // Stop when button is pressed (return 1) or field was gone (return 2) // Or return 0 when command is captured //----------------------------------------------------------------------------- -int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { +int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) { *len = 0; uint32_t timer = 0, vtime = 0; @@ -1632,7 +1632,7 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; // Now run a 'software UART' on the stream of incoming samples. - UartInit(received, parity); + UartInit(received, par); // Clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1884,17 +1884,17 @@ void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing) { ReaderTransmitBitsPar(frame, len * 8, par, timing); } -int ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) +int ReaderReceiveOffset(uint8_t *receivedAnswer, uint16_t offset, uint8_t *par) { + if (!GetIso14443aAnswerFromTag(receivedAnswer, par, offset)) return false; - LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, parity, false); + LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); return Demod.len; } -int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) +int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par) { + if (!GetIso14443aAnswerFromTag(receivedAnswer, par, 0)) return false; - LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, parity, false); + LogTrace(receivedAnswer, Demod.len, Demod.startTime * 16 - DELAY_AIR2ARM_AS_READER, Demod.endTime * 16 - DELAY_AIR2ARM_AS_READER, par, false); return Demod.len; } @@ -2030,7 +2030,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { // if anticollision is false, then the UID must be provided in uid_ptr[] // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // requests ATS unless no_rats is true -int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { +int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 }; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -2044,19 +2044,19 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 int cascade_level = 0; int len; - if (p_card) { - p_card->uidlen = 0; - memset(p_card->uid, 0, 10); - p_card->ats_len = 0; + if (resp_data) { + resp_data->uidlen = 0; + memset(resp_data->uid, 0, 10); + resp_data->ats_len = 0; } if (!GetATQA(resp, resp_par)) { return 0; } - if (p_card) { - p_card->atqa[0] = resp[0]; - p_card->atqa[1] = resp[1]; + if (resp_data) { + resp_data->atqa[0] = resp[0]; + resp_data->atqa[1] = resp[1]; } if (anticollision) { @@ -2151,14 +2151,14 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 if (uid_ptr && anticollision) memcpy(uid_ptr + (cascade_level * 3), uid_resp, uid_resp_len); - if (p_card) { - memcpy(p_card->uid + (cascade_level * 3), uid_resp, uid_resp_len); - p_card->uidlen += uid_resp_len; + if (resp_data) { + memcpy(resp_data->uid + (cascade_level * 3), uid_resp, uid_resp_len); + resp_data->uidlen += uid_resp_len; } } - if (p_card) { - p_card->sak = sak; + if (resp_data) { + resp_data->sak = sak; } // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) @@ -2173,9 +2173,9 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32 if (!len) return 0; - if (p_card) { - memcpy(p_card->ats, resp, sizeof(p_card->ats)); - p_card->ats_len = len; + if (resp_data) { + memcpy(resp_data->ats, resp, sizeof(resp_data->ats)); + resp_data->ats_len = len; } // reset the PCB block number diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index d43ba6565..92638c10a 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -112,10 +112,10 @@ void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); tDemod *GetDemod(void); void DemodReset(void); -void DemodInit(uint8_t *data, uint8_t *parity); +void DemodInit(uint8_t *data, uint8_t *par); tUart *GetUart(void); void UartReset(void); -void UartInit(uint8_t *data, uint8_t *parity); +void UartInit(uint8_t *data, uint8_t *par); RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time); RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time); @@ -139,7 +139,7 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); int EmSend4bit(uint8_t resp); int EmSendCmd(uint8_t *resp, uint16_t respLen); int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision); -int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); +int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par); int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision); int EmSendPrecompiledCmd(tag_response_info_t *response_info); diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 12e9cc815..497a6aa90 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) { +// It expects "cmdout" to be at least CMD_ID_RESP large +static void BuildIdentifyRequest(uint8_t *cmdout) { 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; @@ -632,7 +632,7 @@ static void BuildIdentifyRequest(uint8_t *out) { AddCrc(cmd, 3); // coding as high speed (1 out of 4) CodeIso15693AsReader(cmd, CMD_ID_RESP); - memcpy(out, cmd, CMD_ID_RESP); + memcpy(cmdout, cmd, CMD_ID_RESP); } // uid is in transmission order (which is reverse of display order) @@ -666,7 +666,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) { +static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid) { uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -687,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_INV_RESP); + memcpy(cmdout, cmd, CMD_INV_RESP); } // Universal Method for sending to and recv bytes from a tag diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 9deb445bd..76c392257 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -16,6 +16,6 @@ void LegicRfInfo(void); void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); -void LegicRfWriter(uint16_t offset, uint16_t byte, uint8_t iv, uint8_t *data); +void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data); #endif /* __LEGICRF_H */ diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 1e6f22863..d5a1d21c6 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -651,7 +651,7 @@ void SimulateTagLowFrequency(int period, int gap, int ledcontrol) { #define DEBUG_FRAME_CONTENTS 1 -void SimulateTagLowFrequencyBidir(int divisor, int t0) { +void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen) { } // compose fc/5 fc/8 waveform (FSK1) @@ -824,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, int ledcontrol) { +void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // free eventually allocated BigBuf memory @@ -846,7 +846,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int } for (i = 0; i < size; i++) { - if (bits[i]) + if (BitStream[i]) fcAll(fcLow, &n, clk, &modCnt); else fcAll(fcHigh, &n, clk, &modCnt); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 7018fbae2..b20f6766b 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -248,9 +248,9 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { * Initializes the FPGA for reader-mode (field on), and acquires the samples. * @return number of bits sampled **/ -uint32_t SampleLF(bool printCfg, int sample_size) { +uint32_t SampleLF(bool silent, int sample_size) { BigBuf_Clear_ext(false); - return ReadLF(true, printCfg, sample_size); + return ReadLF(true, silent, sample_size); } /** * Initializes the FPGA for sniffer-mode (field off), and acquires the samples. From ebdfba033d7178929f28afb75922f8d3a10290f1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 20:35:58 +0200 Subject: [PATCH 070/141] arg names --- armsrc/apps.h | 2 +- armsrc/mifarecmd.c | 11 +++++----- armsrc/mifaredesfire.c | 50 ++++++++++++++++++++++-------------------- armsrc/mifareutil.h | 6 ++--- armsrc/pcf7931.h | 4 ++-- armsrc/printf.h | 2 +- 6 files changed, 39 insertions(+), 36 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index 529f197ca..4e3e1219b 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -141,7 +141,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c); void EPA_PACE_Replay(UsbCommand *c); // mifarecmd.h -void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); +void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUC_Auth(uint8_t arg0, uint8_t *datain); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index f6b7692e2..d0822cfbb 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -100,7 +100,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LEDsoff(); } -void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) { +void MifareUC_Auth(uint8_t arg0, uint8_t *datain) { bool turnOffField = (arg0 == 1); @@ -119,7 +119,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) { return; }; - if (!mifare_ultra_auth(keybytes)) { + if (!mifare_ultra_auth(datain)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; @@ -851,12 +851,13 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, // MIFARE nested authentication. // //----------------------------------------------------------------------------- -void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) { +void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { // params uint8_t blockNo = arg0 & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff; uint8_t targetBlockNo = arg1 & 0xff; uint8_t targetKeyType = (arg1 >> 8) & 0xff; + // calibrate = arg2 uint64_t ui64Key = 0; ui64Key = bytes_to_num(datain, 6); @@ -888,14 +889,14 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat BigBuf_free(); BigBuf_Clear_ext(false); - if (calibrate) clear_trace(); + if (arg2) clear_trace(); set_tracing(true); // statistics on nonce distance int16_t isOK = 0; #define NESTED_MAX_TRIES 12 uint16_t unsuccessfull_tries = 0; - if (calibrate) { // for first call only. Otherwise reuse previous calibration + if (arg2) { // calibrate: for first call only. Otherwise reuse previous calibration LED_B_ON(); WDT_HIT(); diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 1bddf3374..6168425bc 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -167,8 +167,10 @@ void MifareDesfireGetInformation() { OnSuccess(); } -void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain) { - +void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { + // mode = arg0 + // algo = arg1 + // keyno = arg2 int len = 0; //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; @@ -196,24 +198,24 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain LED_C_OFF(); // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) - // 4 different crypto algo DES, 3DES, 3K3DES, AES + // 4 different crypto arg1 DES, 3DES, 3K3DES, AES // 3 different communication modes, PLAIN,MAC,CRYPTO // des, key 0, - switch (mode) { + switch (arg0) { case 1: { uint8_t keybytes[16]; uint8_t RndA[8] = {0x00}; uint8_t RndB[8] = {0x00}; - if (algo == 2) { + if (arg1 == 2) { if (datain[1] == 0xff) { memcpy(keybytes, PICC_MASTER_KEY16, 16); } else { memcpy(keybytes, datain + 1, datalen); } } else { - if (algo == 1) { + if (arg1 == 1) { if (datain[1] == 0xff) { memcpy(keybytes, null_key_data8, 8); } else { @@ -225,13 +227,13 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain struct desfire_key defaultkey = {0}; desfirekey_t key = &defaultkey; - if (algo == 2) + if (arg1 == 2) Desfire_3des_key_new_with_version(keybytes, key); - else if (algo == 1) + else if (arg1 == 1) Desfire_des_key_new(keybytes, key); cmd[0] = AUTHENTICATE; - cmd[1] = keyno; //keynumber + cmd[1] = arg2; //keynumber len = DesfireAPDU(cmd, 2, resp); if (!len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) { @@ -249,9 +251,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } memcpy(encRndB, resp + 3, 8); - if (algo == 2) + if (arg1 == 2) tdes_dec(&decRndB, &encRndB, key->data); - else if (algo == 1) + else if (arg1 == 1) des_dec(&decRndB, &encRndB, key->data); memcpy(RndB, decRndB, 8); @@ -262,9 +264,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain memcpy(RndA, decRndA, 8); uint8_t encRndA[8] = {0x00}; - if (algo == 2) + if (arg1 == 2) tdes_dec(&encRndA, &decRndA, key->data); - else if (algo == 1) + else if (arg1 == 1) des_dec(&encRndA, &decRndA, key->data); memcpy(both, encRndA, 8); @@ -274,9 +276,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } - if (algo == 2) + if (arg1 == 2) tdes_dec(&encRndB, &decRndB, key->data); - else if (algo == 1) + else if (arg1 == 1) des_dec(&encRndB, &decRndB, key->data); memcpy(both + 8, encRndB, 8); @@ -302,9 +304,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain memcpy(encRndA, resp + 3, 8); - if (algo == 2) + if (arg1 == 2) tdes_dec(&encRndA, &encRndA, key->data); - else if (algo == 1) + else if (arg1 == 1) des_dec(&encRndA, &encRndA, key->data); rol(decRndA, 8); @@ -320,9 +322,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain /* // Current key is a 3DES key, change it to a DES key - if (algo == 2) { + if (arg1 == 2) { cmd[0] = CHANGE_KEY; - cmd[1] = keyno; + cmd[1] = arg2; uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; @@ -362,9 +364,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } else { // Current key is a DES key, change it to a 3DES key - if (algo == 1) { + if (arg1 == 1) { cmd[0] = CHANGE_KEY; - cmd[1] = keyno; + cmd[1] = arg2; uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; @@ -406,9 +408,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain */ OnSuccess(); - if (algo == 2) + if (arg1 == 2) cmd_send(CMD_ACK, 1, 0, 0, skey->data, 16); - else if (algo == 1) + else if (arg1 == 1) cmd_send(CMD_ACK, 1, 0, 0, skey->data, 8); } else { DbpString("Authentication failed."); @@ -418,7 +420,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } break; case 2: - //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); + //SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp); break; case 3: { diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index a6d4c28fe..a25c64fa4 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -83,8 +83,8 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); // Ultralight/NTAG... -int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); -int mifare_ultra_auth(uint8_t *key); +int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack); +int mifare_ultra_auth(uint8_t *keybytes); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); //int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); @@ -97,7 +97,7 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); // crypto functions -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len); void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); diff --git a/armsrc/pcf7931.h b/armsrc/pcf7931.h index b8121c29f..5e3c5a8e4 100644 --- a/armsrc/pcf7931.h +++ b/armsrc/pcf7931.h @@ -8,8 +8,8 @@ #include "string.h" size_t DemodPCF7931(uint8_t **outBlocks); -bool IsBlock0PCF7931(uint8_t *Block); -bool IsBlock1PCF7931(uint8_t *Block); +bool IsBlock0PCF7931(uint8_t *block); +bool IsBlock1PCF7931(uint8_t *block); void ReadPCF7931(); void SendCmdPCF7931(uint32_t *tab); bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p); diff --git a/armsrc/printf.h b/armsrc/printf.h index 616752ed6..ff0143790 100644 --- a/armsrc/printf.h +++ b/armsrc/printf.h @@ -15,7 +15,7 @@ #include #include "string.h" -int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0))); +int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0))); int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0))); int sprintf(char *dest, const char *fmt, ...) __attribute__((format(printf, 2, 3))); From 51d6fa13ebe56398cbc6e3a315eb76cca2feb51a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 21:46:00 +0200 Subject: [PATCH 071/141] arg names --- client/cliparser/argtable3.h | 2 +- client/cliparser/cliparser.h | 4 +-- client/cmddata.c | 30 ++++++++++---------- client/cmddata.h | 4 +-- client/cmdlf.c | 6 ++-- client/cmdlfawid.c | 2 +- client/cmdlfcotag.c | 2 +- client/cmdlfem4x.c | 6 ++-- client/cmdlffdx.c | 4 +-- client/cmdlfguard.c | 2 +- client/cmdlfhid.c | 2 +- client/cmdlfindala.c | 2 +- client/cmdlfio.c | 2 +- client/cmdlfjablotron.c | 2 +- client/cmdlfkeri.c | 2 +- client/cmdlfnedap.c | 2 +- client/cmdlfnexwatch.c | 2 +- client/cmdlfnoralsy.c | 2 +- client/cmdlfpac.c | 2 +- client/cmdlfparadox.c | 2 +- client/cmdlfpresco.c | 2 +- client/cmdlfpyramid.c | 2 +- client/cmdlfsecurakey.c | 2 +- client/cmdlfviking.c | 2 +- client/cmdlfvisa2000.c | 2 +- client/graph.c | 12 ++++---- client/hardnested/hardnested_bf_core.h | 4 +-- client/hardnested/hardnested_bitarray_core.c | 4 +-- client/mifare/mifarehost.h | 2 +- common/crc.c | 6 ++-- common/crc16.c | 16 +++++------ common/crc16.h | 2 +- 32 files changed, 69 insertions(+), 69 deletions(-) diff --git a/client/cliparser/argtable3.h b/client/cliparser/argtable3.h index a442ec0d5..c3ec479ea 100644 --- a/client/cliparser/argtable3.h +++ b/client/cliparser/argtable3.h @@ -271,7 +271,7 @@ struct arg_date *arg_daten(const char *shortopts, int maxcount, const char *glossary); -struct arg_end *arg_end(int maxerrors); +struct arg_end *arg_end(int maxcount); /**** other functions *******************************************/ diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h index 7dd3584bc..d1fa19bce 100644 --- a/client/cliparser/cliparser.h +++ b/client/cliparser/cliparser.h @@ -32,9 +32,9 @@ #define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp); -int CLIParserParseString(const char *str, void *argtable[], size_t vargtableLen, bool allowEmptyExec); +int CLIParserParseString(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); int CLIParserParseStringEx(const char *str, void *vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); -int CLIParserParseArg(int argc, char **argv, void *argtable[], size_t vargtableLen, bool allowEmptyExec); +int CLIParserParseArg(int argc, char **argv, void *vargtable[], size_t vargtableLen, bool allowEmptyExec); void CLIParserFree(); int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); diff --git a/client/cmddata.c b/client/cmddata.c index 5b3074433..959472c58 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -237,26 +237,26 @@ int usage_data_fsktonrz() { //set the demod buffer with given array of binary (one bit per byte) //by marshmellow -void setDemodBuf(uint8_t *buf, size_t size, size_t start_idx) { - if (buf == NULL) return; +void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx) { + if (buff == NULL) return; if (size > MAX_DEMOD_BUF_LEN - start_idx) size = MAX_DEMOD_BUF_LEN - start_idx; for (size_t i = 0; i < size; i++) - DemodBuffer[i] = buf[start_idx++]; + DemodBuffer[i] = buff[start_idx++]; DemodBufferLen = size; } -bool getDemodBuf(uint8_t *buf, size_t *size) { - if (buf == NULL) return false; +bool getDemodBuff(uint8_t *buff, size_t *size) { + if (buff == NULL) return false; if (size == NULL) return false; if (*size == 0) return false; *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; - memcpy(buf, DemodBuffer, *size); + memcpy(buff, DemodBuffer, *size); return true; } @@ -521,7 +521,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, if (verbose) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); //output - setDemodBuf(bits, BitLen, 0); + setDemodBuff(bits, BitLen, 0); setClockGrid(clk, startIdx); if (verbose) { @@ -608,7 +608,7 @@ int Cmdmandecoderaw(const char *Cmd) { size_t idx = 0; if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1) { //need to adjust to set bitstream back to manchester encoded data - //setDemodBuf(bits, size, idx); + //setDemodBuff(bits, size, idx); printEM410x(hi, id); } } @@ -638,7 +638,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; size = sizeof(bits); - if (!getDemodBuf(bits, &size)) return 0; + if (!getDemodBuff(bits, &size)) return 0; errCnt = BiphaseRawDecode(bits, &size, &offset, invert); if (errCnt < 0) { @@ -658,7 +658,7 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { //remove first bit from raw demod if (offset) - setDemodBuf(DemodBuffer, DemodBufferLen - offset, offset); + setDemodBuff(DemodBuffer, DemodBufferLen - offset, offset); setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock * offset / 2); return 1; @@ -696,7 +696,7 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) { return 0; } //success set DemodBuffer and return - setDemodBuf(BitStream, size, 0); + setDemodBuff(BitStream, size, 0); setClockGrid(clk, startIdx + clk * offset / 2); if (g_debugMode || verbose) { PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:", offset, clk, errCnt); @@ -1067,7 +1067,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) { int startIdx = 0; int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); if (size > 0) { - setDemodBuf(bits, size, 0); + setDemodBuff(bits, size, 0); setClockGrid(rfLen, startIdx); // Now output the bitstream to the scrollback by line of 16 bits @@ -1135,7 +1135,7 @@ int PSKDemod(const char *Cmd, bool verbose) { } } //prime demod buffer for output - setDemodBuf(bits, bitlen, 0); + setDemodBuff(bits, bitlen, 0); setClockGrid(clk, startIdx); return 1; } @@ -1185,7 +1185,7 @@ int CmdIdteckDemod(const char *Cmd) { return 0; } } - setDemodBuf(DemodBuffer, 64, idx); + setDemodBuff(DemodBuffer, 64, idx); //got a good demod uint32_t id = 0; @@ -1238,7 +1238,7 @@ int NRZrawDemod(const char *Cmd, bool verbose) { } if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); //prime demod buffer for output - setDemodBuf(bits, BitLen, 0); + setDemodBuff(bits, BitLen, 0); setClockGrid(clk, clkStartIdx); diff --git a/client/cmddata.h b/client/cmddata.h index 5f0fe80e0..cca722ed4 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -36,8 +36,8 @@ command_t *CmdDataCommands(); int CmdData(const char *Cmd); void printDemodBuff(void); -void setDemodBuf(uint8_t *buff, size_t size, size_t startIdx); -bool getDemodBuf(uint8_t *buff, size_t *size); +void setDemodBuff(uint8_t *buff, size_t size, size_t start_idx); +bool getDemodBuff(uint8_t *buff, size_t *size); void save_restoreDB(uint8_t saveOpt);// option '1' to save DemodBuffer any other to restore int CmdPrintDemodBuff(const char *Cmd); diff --git a/client/cmdlf.c b/client/cmdlf.c index 263e73749..1ea81b6ed 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -509,7 +509,7 @@ int CmdLFfskSim(const char *Cmd) { } } } else { - setDemodBuf(data, dataLen, 0); + setDemodBuff(data, dataLen, 0); } //default if not found @@ -603,7 +603,7 @@ int CmdLFaskSim(const char *Cmd) { if (clk == 0) clk = GetAskClock("0", false); } else { - setDemodBuf(data, dataLen, 0); + setDemodBuff(data, dataLen, 0); } if (clk == 0) clk = 64; if (encoding == 0) clk /= 2; //askraw needs to double the clock speed @@ -704,7 +704,7 @@ int CmdLFpskSim(const char *Cmd) { PrintAndLogEx(NORMAL, "carrier: %d", carrier); } else { - setDemodBuf(data, dataLen, 0); + setDemodBuff(data, dataLen, 0); } if (clk == 0) clk = 32; diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 72fc913da..72bd48a07 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -267,7 +267,7 @@ int CmdAWIDDemod(const char *Cmd) { return 0; } - setDemodBuf(bits, size, idx); + setDemodBuff(bits, size, idx); setClockGrid(50, waveIdx + (idx * 50)); diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index ec26c89ff..53b0d0451 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -40,7 +40,7 @@ int CmdCOTAGDemod(const char *Cmd) { return -1; } - setDemodBuf(bits, bitlen, 0); + setDemodBuff(bits, bitlen, 0); //got a good demod uint16_t cn = bytebits_to_byteLSBF(bits + 1, 16); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 8d5ebb68b..b3e0c42dd 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -356,7 +356,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) { size_t idx = 0; uint8_t bits[512] = {0}; size_t size = sizeof(bits); - if (!getDemodBuf(bits, &size)) { + if (!getDemodBuff(bits, &size)) { PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod"); return 0; } @@ -381,7 +381,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo) { } //set GraphBuffer for clone or sim command - setDemodBuf(DemodBuffer, (size == 40) ? 64 : 128, idx + 1); + setDemodBuff(DemodBuffer, (size == 40) ? 64 : 128, idx + 1); setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 1)*g_DemodClock)); PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %d, Len: %d, Printing Demod Buffer:", idx, size); @@ -1109,7 +1109,7 @@ bool setDemodBufferEM(uint32_t *word, size_t idx) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM, failed removing parity"); return false; } - setDemodBuf(DemodBuffer, 32, 0); + setDemodBuff(DemodBuffer, 32, 0); *word = bytebits_to_byteLSBF(DemodBuffer, 32); return true; } diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 972ef9627..46dd0c8ca 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -186,7 +186,7 @@ int CmdFDXBdemodBI(const char *Cmd) { return 0; } - setDemodBuf(bs, 128, preambleIndex); + setDemodBuff(bs, 128, preambleIndex); // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(bs, preambleIndex + 11, 9, 2, 117); @@ -256,7 +256,7 @@ int CmdFdxDemod(const char *Cmd) { } // set and leave DemodBuffer intact - setDemodBuf(DemodBuffer, 128, preambleIndex); + setDemodBuff(DemodBuffer, 128, preambleIndex); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock)); // remove marker bits (1's every 9th digit after preamble) (pType = 2) size = removeParity(DemodBuffer, 11, 9, 2, 117); diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index a3f8bbec9..1f89a87ef 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -220,7 +220,7 @@ int CmdGuardDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: gProxII byte %u after xor: %02x", (unsigned int)idx, ByteStream[idx]); } - setDemodBuf(DemodBuffer, 96, preambleIndex); + setDemodBuff(DemodBuffer, 96, preambleIndex); setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex * g_DemodClock)); //ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index b44a5e68a..9dbb721cd 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -155,7 +155,7 @@ int CmdHIDDemod(const char *Cmd) { return 0; } - setDemodBuf(bits, size, idx); + setDemodBuff(bits, size, idx); setClockGrid(50, waveIdx + (idx * 50)); if (hi2 == 0 && hi == 0 && lo == 0) { diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index c6be8bd29..b1d970575 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -208,7 +208,7 @@ int CmdIndalaDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Indala: error demoding psk idx: %d", idx); return 0; } - setDemodBuf(DemodBuffer, size, idx); + setDemodBuff(DemodBuffer, size, idx); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); //convert UID to HEX diff --git a/client/cmdlfio.c b/client/cmdlfio.c index df994b1a1..ae18ec4f7 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -112,7 +112,7 @@ int CmdIOProxDemod(const char *Cmd) { } return 0; } - setDemodBuf(bits, size, idx); + setDemodBuff(bits, size, idx); setClockGrid(64, waveIdx + (idx * 64)); if (idx == 0) { diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index e445b20b6..08312db4b 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -117,7 +117,7 @@ int CmdJablotronDemod(const char *Cmd) { return 0; } - setDemodBuf(DemodBuffer, 64, ans); + setDemodBuff(DemodBuffer, 64, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 199e639a9..c3df3e7be 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -84,7 +84,7 @@ int CmdKeriDemod(const char *Cmd) { return 0; } - setDemodBuf(DemodBuffer, size, idx); + setDemodBuff(DemodBuffer, size, idx); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); //got a good demod diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 320f07d6a..e03401e84 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -165,7 +165,7 @@ int CmdLFNedapDemod(const char *Cmd) { raw[1] = bytebits_to_byte(DemodBuffer + idx + 64, 32); raw[2] = bytebits_to_byte(DemodBuffer + idx + 32, 32); raw[3] = bytebits_to_byte(DemodBuffer + idx, 32); - setDemodBuf(DemodBuffer, 128, idx); + setDemodBuff(DemodBuffer, 128, idx); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); uint8_t firstParity = GetParity(DemodBuffer, EVEN, 63); diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 3d5c1083b..ffe3bd785 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -57,7 +57,7 @@ int CmdNexWatchDemod(const char *Cmd) { return 0; } - setDemodBuf(DemodBuffer, size, idx + 4); + setDemodBuff(DemodBuffer, size, idx + 4); setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx + 4)*g_DemodClock)); idx = 8 + 32; // 8 = preamble, 32 = reserved bits (always 0) diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index 0f515ba43..e2c4a5c90 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -128,7 +128,7 @@ int CmdNoralsyDemod(const char *Cmd) { } return 0; } - setDemodBuf(DemodBuffer, 96, ans); + setDemodBuff(DemodBuffer, 96, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 643e5295f..7c7742d95 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -46,7 +46,7 @@ int CmdPacDemod(const char *Cmd) { return 0; } - setDemodBuf(DemodBuffer, 128, ans); + setDemodBuff(DemodBuffer, 128, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 23d45bc27..5cca09b4e 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -108,7 +108,7 @@ int CmdParadoxDemod(const char *Cmd) { return 0; } - setDemodBuf(bits, size, idx); + setDemodBuff(bits, size, idx); setClockGrid(50, waveIdx + (idx * 50)); if (hi2 == 0 && hi == 0 && lo == 0) { diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index b76cdf5e3..cff86c88b 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -144,7 +144,7 @@ int CmdPrescoDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Presco: ans: %d", ans); return 0; } - setDemodBuf(DemodBuffer, 128, ans); + setDemodBuff(DemodBuffer, 128, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 169c07194..e3f2a90b5 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -131,7 +131,7 @@ int CmdPyramidDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: error demoding fsk idx: %d", idx); return 0; } - setDemodBuf(bits, size, idx); + setDemodBuff(bits, size, idx); setClockGrid(50, waveIdx + (idx * 50)); // Index map diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 527aba839..1f14f8083 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -47,7 +47,7 @@ int CmdSecurakeyDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Securakey: ans: %d", ans); return 0; } - setDemodBuf(DemodBuffer, 96, ans); + setDemodBuff(DemodBuffer, 96, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 6c4a408b1..49b4ccf2f 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -90,7 +90,7 @@ int CmdVikingDemod(const char *Cmd) { uint8_t checksum = bytebits_to_byte(DemodBuffer + ans + 32 + 24, 8); PrintAndLogEx(SUCCESS, "Viking Tag Found: Card ID %08X, Checksum: %02X", cardid, checksum); PrintAndLogEx(SUCCESS, "Raw: %08X%08X", raw1, raw2); - setDemodBuf(DemodBuffer, 64, ans); + setDemodBuff(DemodBuffer, 64, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); return 1; } diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 82bf491c2..3dcc7cf04 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -122,7 +122,7 @@ int CmdVisa2kDemod(const char *Cmd) { save_restoreGB(GRAPH_RESTORE); return 0; } - setDemodBuf(DemodBuffer, 96, ans); + setDemodBuff(DemodBuffer, 96, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans * g_DemodClock)); //got a good demod diff --git a/client/graph.c b/client/graph.c index 4decd40c8..1557efb7d 100644 --- a/client/graph.c +++ b/client/graph.c @@ -59,8 +59,8 @@ void save_restoreGB(uint8_t saveOpt) { return; } -void setGraphBuf(uint8_t *buf, size_t size) { - if (buf == NULL) return; +void setGraphBuf(uint8_t *buff, size_t size) { + if (buff == NULL) return; ClearGraph(false); @@ -68,21 +68,21 @@ void setGraphBuf(uint8_t *buf, size_t size) { size = MAX_GRAPH_TRACE_LEN; for (uint32_t i = 0; i < size; ++i) - GraphBuffer[i] = buf[i] - 128; + GraphBuffer[i] = buff[i] - 128; GraphTraceLen = size; RepaintGraphWindow(); return; } -size_t getFromGraphBuf(uint8_t *buf) { - if (buf == NULL) return 0; +size_t getFromGraphBuf(uint8_t *buff) { + if (buff == NULL) return 0; uint32_t i; for (i = 0; i < GraphTraceLen; ++i) { //trim if (GraphBuffer[i] > 127) GraphBuffer[i] = 127; if (GraphBuffer[i] < -127) GraphBuffer[i] = -127; - buf[i] = (uint8_t)(GraphBuffer[i] + 128); + buff[i] = (uint8_t)(GraphBuffer[i] + 128); } return i; } diff --git a/client/hardnested/hardnested_bf_core.h b/client/hardnested/hardnested_bf_core.h index 4f481cbc8..872fa2d08 100644 --- a/client/hardnested/hardnested_bf_core.h +++ b/client/hardnested/hardnested_bf_core.h @@ -64,7 +64,7 @@ typedef enum { void SetSIMDInstr(SIMDExecInstr instr); SIMDExecInstr GetSIMDInstrAuto(); -const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces); -void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par); +const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces); +void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par); #endif diff --git a/client/hardnested/hardnested_bitarray_core.c b/client/hardnested/hardnested_bitarray_core.c index 788d95597..e9e84aa40 100644 --- a/client/hardnested/hardnested_bitarray_core.c +++ b/client/hardnested/hardnested_bitarray_core.c @@ -593,8 +593,8 @@ uint32_t bitcount(uint32_t a) { return (*bitcount_function_p)(a); } -uint32_t count_states(uint32_t *bitarray) { - return (*count_states_function_p)(bitarray); +uint32_t count_states(uint32_t *A) { + return (*count_states_function_p)(A); } void bitarray_AND(uint32_t *A, uint32_t *B) { diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 81e0e8f03..fd3935d41 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -70,7 +70,7 @@ typedef struct { extern char logHexFileName[FILE_PATH_SIZE]; int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); -int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKeys, bool calibrate); +int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate); int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key); int mfCheckKeys_fast(uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); diff --git a/common/crc.c b/common/crc.c index 2ad7609b1..c3bd90064 100644 --- a/common/crc.c +++ b/common/crc.c @@ -107,12 +107,12 @@ uint32_t CRC8Mad(uint8_t *buff, size_t size) { return crc_finish(&crc); } // width=4 poly=0xC, reversed poly=0x7 init=0x5 refin=true refout=true xorout=0x0000 check= name="CRC-4/LEGIC" -uint32_t CRC4Legic(uint8_t *cmd, size_t size) { +uint32_t CRC4Legic(uint8_t *buff, size_t size) { crc_t crc; crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, true, true); crc_update2(&crc, 1, 1); /* CMD_READ */ - crc_update2(&crc, cmd[0], 8); - crc_update2(&crc, cmd[1], 8); + crc_update2(&crc, buff[0], 8); + crc_update2(&crc, buff[1], 8); return reflect(crc_finish(&crc), 4); } // width=8 poly=0x63, reversed poly=0x8D init=0x55 refin=true refout=true xorout=0x0000 check=0xC6 name="CRC-8/LEGIC" diff --git a/common/crc16.c b/common/crc16.c index 69ada3b24..075b5d724 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -9,21 +9,21 @@ static uint16_t crc_table[256]; static bool crc_table_init = false; -static CrcType_t crc_type = CRC_NONE; +static CrcType_t current_crc_type = CRC_NONE; -void init_table(CrcType_t ct) { +void init_table(CrcType_t crctype) { // same crc algo, and initialised already - if (ct == crc_type && crc_table_init) + if (crctype == current_crc_type && crc_table_init) return; // not the same crc algo. reset table. - if (ct != crc_type) + if (crctype != current_crc_type) reset_table(); - crc_type = ct; + current_crc_type = crctype; - switch (ct) { + switch (crctype) { case CRC_14443_A: case CRC_14443_B: case CRC_15693: @@ -44,7 +44,7 @@ void init_table(CrcType_t ct) { break; default: crc_table_init = false; - crc_type = CRC_NONE; + current_crc_type = CRC_NONE; break; } } @@ -80,7 +80,7 @@ void generate_table(uint16_t polynomial, bool refin) { void reset_table(void) { memset(crc_table, 0, sizeof(crc_table)); crc_table_init = false; - crc_type = CRC_NONE; + current_crc_type = CRC_NONE; } // table lookup LUT solution diff --git a/common/crc16.h b/common/crc16.h index 9a202f514..e59ed1832 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -32,7 +32,7 @@ typedef enum { uint16_t update_crc16_ex(uint16_t crc, uint8_t c, uint16_t polynomial); uint16_t update_crc16(uint16_t crc, uint8_t c); -uint16_t crc16(uint8_t const *message, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout); +uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout); uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n); void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8_t *second); From 50e131f99b028e539dc7689d945731cd1be00f51 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 21:59:34 +0200 Subject: [PATCH 072/141] arg names --- client/cmdhf14a.c | 2 +- client/cmdhf15.h | 2 +- client/cmdhfmfdes.h | 6 +++--- client/cmdhfmfu.h | 2 +- client/cmdlfhitag.h | 2 +- client/cmdlfpresco.h | 2 +- 6 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 0894c578f..dad8495a3 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -15,7 +15,7 @@ bool APDUInFramingEnable = true; static int CmdHelp(const char *Cmd); -static int waitCmd(uint8_t iLen); +static int waitCmd(uint8_t iSelect); static const manufactureName manufactureMapping[] = { // ID, "Vendor Country" diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 141163547..5a3753100 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -38,7 +38,7 @@ int CmdHF15Reader(const char *Cmd); int CmdHF15Sim(const char *Cmd); int CmdHF15Afi(const char *Cmd); int CmdHF15Dump(const char *Cmd); -int CmdHF15Raw(const char *cmd); +int CmdHF15Raw(const char *Cmd); int CmdHF15Readmulti(const char *Cmd); int CmdHF15Read(const char *Cmd); int CmdHF15Write(const char *Cmd); diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h index 9aeb7dbeb..6f2f0fa3f 100644 --- a/client/cmdhfmfdes.h +++ b/client/cmdhfmfdes.h @@ -11,9 +11,9 @@ #define __MFDESFIRE_H int CmdHFMFDes(const char *Cmd); -int CmdHF14ADesAuth(const char *cmd); -int CmdHF14ADesRb(const char *cmd); -int CmdHF14ADesWb(const char *cmd); +int CmdHF14ADesAuth(const char *Cmd); +int CmdHF14ADesRb(const char *Cmd); +int CmdHF14ADesWb(const char *Cmd); int CmdHF14ADesInfo(const char *Cmd); int CmdHF14ADesEnumApplications(const char *Cmd); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 315b4b542..28f79d086 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -43,7 +43,7 @@ int CmdHF14AMfUeLoad(const char *Cmd); int CmdHF14AMfUSim(const char *Cmd); uint32_t GetHF14AMfU_Type(void); -int ul_print_type(uint32_t tagtype, uint8_t spacer); +int ul_print_type(uint32_t tagtype, uint8_t spaces); void printMFUdump(mfu_dump_t *card); void printMFUdumpEx(mfu_dump_t *card, uint16_t pages, uint8_t startpage); diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index 6728d00e0..650e5d892 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -20,6 +20,6 @@ int CmdLFHitagInfo(const char *Cmd); int CmdLFHitagReader(const char *Cmd); int CmdLFHitagCheckChallenges(const char *Cmd); int CmdLFHitagWriter(const char *Cmd); -int CmdLFHitagDump(const char *cmd); +int CmdLFHitagDump(const char *Cmd); #endif diff --git a/client/cmdlfpresco.h b/client/cmdlfpresco.h index 5ae74a11f..9c84f75b6 100644 --- a/client/cmdlfpresco.h +++ b/client/cmdlfpresco.h @@ -28,7 +28,7 @@ int CmdPrescoClone(const char *Cmd); int CmdPrescoSim(const char *Cmd); int detectPresco(uint8_t *dest, size_t *size); -int GetWiegandFromPresco(const char *id, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5); +int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5); int usage_lf_presco_clone(void); int usage_lf_presco_sim(void); From 7259a27f05072576c13354ab9b5f4850fabac19a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 22:04:02 +0200 Subject: [PATCH 073/141] Change printT55xxBlock API --- client/cmdlft55xx.c | 8 +++----- client/cmdlft55xx.h | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 61507cea4..835df18f2 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -379,9 +379,7 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 if (!AquireData(page1, block, usepwd, password)) return 0; if (!DecodeT55xxBlock()) return 0; - char blk[10] = {0}; - sprintf(blk, "%02d", block); - printT55xxBlock(blk); + printT55xxBlock(block); return 1; } @@ -777,7 +775,7 @@ bool GetT55xxBlockData(uint32_t *blockdata) { return true; } -void printT55xxBlock(const char *blockNum) { +void printT55xxBlock(uint8_t blockNum) { uint32_t blockData = 0; uint8_t bytes[4] = {0}; @@ -787,7 +785,7 @@ void printT55xxBlock(const char *blockNum) { num_to_bytes(blockData, 4, bytes); - PrintAndLogEx(NORMAL, " %s | %08X | %s | %s", blockNum, blockData, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); + PrintAndLogEx(NORMAL, " %02d | %08X | %s | %s", blockNum, blockData, sprint_bin(DemodBuffer + config.offset, 32), sprint_ascii(bytes, 4)); } bool testModulation(uint8_t mode, uint8_t modread) { diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index dca8c6f39..71526b997 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -157,7 +157,7 @@ char *GetModulationStr(uint32_t id, bool xmode); char *GetModelStrFromCID(uint32_t cid); char *GetSelectedModulationStr(uint8_t id); void printT5xxHeader(uint8_t page); -void printT55xxBlock(const char *demodStr); +void printT55xxBlock(uint8_t blockNum); int printConfiguration(t55xx_conf_block_t b); int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password); From 24acbf86eba0cd5ce9b9a91350d869b7745b4853 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 6 Apr 2019 22:15:57 +0200 Subject: [PATCH 074/141] arg names --- client/cmdsmartcard.h | 6 +++--- client/emv/dol.h | 2 +- client/emv/emv_pki.h | 8 ++++---- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index f7adb7690..1e94499af 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -29,9 +29,9 @@ int CmdSmartcard(const char *Cmd); -int CmdSmartRaw(const char *cmd); -int CmdSmartUpgrade(const char *cmd); -int CmdSmartInfo(const char *cmd); +int CmdSmartRaw(const char *Cmd); +int CmdSmartUpgrade(const char *Cmd); +int CmdSmartInfo(const char *Cmd); int CmdSmartReader(const char *Cmd); bool smart_select(bool silent, smart_card_atr_t *atr); diff --git a/client/emv/dol.h b/client/emv/dol.h index 9b1b51656..496ae66f5 100644 --- a/client/emv/dol.h +++ b/client/emv/dol.h @@ -20,6 +20,6 @@ #include struct tlv *dol_process(const struct tlv *tlv, const struct tlvdb *tlvdb, tlv_tag_t tag); -struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *buf, size_t len); +struct tlvdb *dol_parse(const struct tlv *tlv, const unsigned char *data, size_t data_len); #endif diff --git a/client/emv/emv_pki.h b/client/emv/emv_pki.h index 0b80f2665..91ff60166 100644 --- a/client/emv/emv_pki.h +++ b/client/emv/emv_pki.h @@ -28,10 +28,10 @@ struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv); struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db); -struct tlvdb *emv_pki_recover_dac(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *sda_tlv); -struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData); -struct tlvdb *emv_pki_recover_idn(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *dyn_tlv); -struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData); +struct tlvdb *emv_pki_recover_dac(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv); +struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData); +struct tlvdb *emv_pki_recover_idn(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv); +struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *dyn_tlv, bool showData); struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, bool showData); struct tlvdb *emv_pki_perform_cda(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlvdb *this_db, From 7a24d7fdb6b8ff6f7059a4af17e56de005dc439e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 08:52:10 +0200 Subject: [PATCH 075/141] chg: 'lf indala demod' - texual --- client/cmdlfindala.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index b1d970575..985ae81d2 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -265,7 +265,9 @@ int CmdIndalaDemod(const char *Cmd) { uid5 = bytebits_to_byte(DemodBuffer + 128, 32); uid6 = bytebits_to_byte(DemodBuffer + 160, 32); uid7 = bytebits_to_byte(DemodBuffer + 192, 32); - PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = 0x%x%08x%08x%08x%08x%08x%08x" + PrintAndLogEx( + SUCCESS + , "Indala Found - bitlength %d, Raw 0x%x%08x%08x%08x%08x%08x%08x" , DemodBufferLen , uid1 , uid2 @@ -558,7 +560,7 @@ int CmdIndalaClone(const char *Cmd) { UsbCommand c = {0, {0, 0, 0}}; if (isLongUid) { - PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with UID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with RawID %s", sprint_hex(data, datalen)); c.cmd = CMD_INDALA_CLONE_TAG_L; c.d.asDwords[0] = bytes_to_num(data, 4); c.d.asDwords[1] = bytes_to_num(data + 4, 4); @@ -568,7 +570,7 @@ int CmdIndalaClone(const char *Cmd) { c.d.asDwords[5] = bytes_to_num(data + 20, 4); c.d.asDwords[6] = bytes_to_num(data + 24, 4); } else { - PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with UID %s", sprint_hex(data, datalen)); + PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with RawID %s", sprint_hex(data, datalen)); c.cmd = CMD_INDALA_CLONE_TAG; c.d.asDwords[0] = bytes_to_num(data, 4); c.d.asDwords[1] = bytes_to_num(data + 4, 4); From aea6c6d3c5797afda00dec5b596eb6c777138d7b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:17:43 +0200 Subject: [PATCH 076/141] fixes, shadow --- armsrc/Standalone/hf_bog.c | 12 ++++++------ armsrc/Standalone/hf_bog.h | 4 ---- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 40f3abba9..36e600392 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -85,7 +85,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { uint8_t *data = dmaBuf; uint8_t previous_data = 0; - int dataLen = 0; + int dataLen; bool TagIsActive = false; bool ReaderIsActive = false; @@ -110,7 +110,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { // triggered == false -- to wait first for card bool triggered = !(param & 0x03); - uint32_t rsamples = 0; + uint32_t my_rsamples = 0; // Current captured passwords counter uint8_t auth_attempts = 0; @@ -151,11 +151,11 @@ void RAMFUNC SniffAndStore(uint8_t param) { LED_A_OFF(); // Need two samples to feed Miller and Manchester-Decoder - if (rsamples & 0x01) { + if (my_rsamples & 0x01) { if (!TagIsActive) { // no need to try decoding reader data if the tag is sending uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); - if (MillerDecoding(readerdata, (rsamples - 1) * 4)) { + if (MillerDecoding(readerdata, (my_rsamples - 1) * 4)) { LED_C_ON(); // check - if there is a short 7bit request from reader @@ -190,7 +190,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { // no need to try decoding tag data if the reader is sending - and we cannot afford the time if (!ReaderIsActive) { uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); - if (ManchesterDecoding(tagdata, 0, (rsamples - 1) * 4)) { + if (ManchesterDecoding(tagdata, 0, (my_rsamples - 1) * 4)) { LED_B_ON(); if (!LogTrace(receivedResp, @@ -214,7 +214,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { } previous_data = *data; - rsamples++; + my_rsamples++; data++; if (data == dmaBuf + DMA_BUFFER_SIZE) { data = dmaBuf; diff --git a/armsrc/Standalone/hf_bog.h b/armsrc/Standalone/hf_bog.h index 8b7d4c695..3588ff610 100644 --- a/armsrc/Standalone/hf_bog.h +++ b/armsrc/Standalone/hf_bog.h @@ -6,10 +6,6 @@ // StandAlone Mod //----------------------------------------------------------------------------- -#ifndef FALSE -#define FALSE 0 -#endif - #ifndef __HF_BOG_H #define __HF_BOG_H From da7dc2353c34251ba058d937b9fa52576933079c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:30:52 +0200 Subject: [PATCH 077/141] style and warnings --- armsrc/Standalone/hf_colin.c | 119 +++++++++++++++++++---------------- 1 file changed, 65 insertions(+), 54 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index e6ac015fc..87f89883c 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -76,12 +76,14 @@ void cjSetCursLeft() { void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); } +/* void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) { char tosendkey[13]; sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4], foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type); } +*/ void ReadLastTagFromFlash() { SpinOff(0); @@ -89,7 +91,6 @@ void ReadLastTagFromFlash() { LED_B_ON(); LED_C_ON(); LED_D_ON(); - uint16_t isok = 0; uint32_t startidx = 0; uint16_t len = 1024; @@ -109,7 +110,7 @@ void ReadLastTagFromFlash() { for (size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - isok = Flash_ReadDataCont(startidx + i, mem, len); + uint16_t isok = Flash_ReadDataCont(startidx + i, mem, len); if (isok == len) { emlSetMem(mem, 0, 64); } else { @@ -137,8 +138,6 @@ void WriteTagToFlash(uint8_t index, size_t size) { LED_C_ON(); LED_D_ON(); - uint8_t isok = 0; - uint16_t res = 0; uint32_t len = size; uint32_t bytes_sent = 0; uint32_t bytes_remaining = len; @@ -168,10 +167,10 @@ void WriteTagToFlash(uint8_t index, size_t size) { memcpy(buff, data + bytes_sent, bytes_in_packet); bytes_remaining -= bytes_in_packet; - res = Flash_WriteDataCont(bytes_sent + (index * size), buff, bytes_in_packet); + uint16_t res = Flash_WriteDataCont(bytes_sent + (index * size), buff, bytes_in_packet); bytes_sent += bytes_in_packet; - isok = (res == bytes_in_packet) ? 1 : 0; + uint8_t isok = (res == bytes_in_packet) ? 1 : 0; if (!isok) { DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent); @@ -305,14 +304,14 @@ void RunMod() { // and why not a simple memset abuse to 0xffize the whole space in one go ? // uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21 uint8_t foundKey[2][40][6]; - for (uint16_t t = 0; t < 2; t++) { + for (uint16_t i = 0; i < 2; i++) { for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - foundKey[t][sectorNo][0] = 0xFF; - foundKey[t][sectorNo][1] = 0xFF; - foundKey[t][sectorNo][2] = 0xFF; - foundKey[t][sectorNo][3] = 0xFF; - foundKey[t][sectorNo][4] = 0xFF; - foundKey[t][sectorNo][5] = 0xFF; + foundKey[i][sectorNo][0] = 0xFF; + foundKey[i][sectorNo][1] = 0xFF; + foundKey[i][sectorNo][2] = 0xFF; + foundKey[i][sectorNo][3] = 0xFF; + foundKey[i][sectorNo][4] = 0xFF; + foundKey[i][sectorNo][5] = 0xFF; } } @@ -465,12 +464,12 @@ failtag: ; // Type 0 / A first uint16_t t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + for (uint16_t s = 0; s < sectorsCnt; s++) { + num_to_bytes(0x484558414354, 6, foundKey[t][s]); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][s][0], foundKey[t][s][1], foundKey[t][s][2], + foundKey[t][s][3], foundKey[t][s][4], foundKey[t][s][5]); cjSetCursRight(); - DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); + DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t); } t = 1; uint16_t sectorNo = 0; @@ -611,14 +610,19 @@ failtag: // emlClearMem(); // A very weak one... - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - num_to_bytes(key64, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + for (uint16_t i = 0; i < 2; i++) { + for (uint16_t s = 0; s < sectorsCnt; s++) { + num_to_bytes(key64, 6, foundKey[i][s]); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", + foundKey[i][s][0], + foundKey[i][s][1], + foundKey[i][s][2], + foundKey[i][s][3], + foundKey[i][s][4], + foundKey[i][s][5] + ); cjSetCursRight(); - - DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); + DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, i); } } trapped = 1; @@ -644,25 +648,33 @@ failtag: cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); - ; + t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + for (uint16_t s = 0; s < sectorsCnt; s++) { + num_to_bytes(0x414c41524f4e, 6, foundKey[t][s]); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", + foundKey[t][s][0], + foundKey[t][s][1], + foundKey[t][s][2], + foundKey[t][s][3], + foundKey[t][s][4], + foundKey[t][s][5]); cjSetCursRight(); - - DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); - ; + DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t); } + t = 1; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]); - sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], - foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); + for (uint16_t s = 0; s < sectorsCnt; s++) { + num_to_bytes(0x424c41524f4e, 6, foundKey[t][s]); + sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", + foundKey[t][s][0], + foundKey[t][s][1], + foundKey[t][s][2], + foundKey[t][s][3], + foundKey[t][s][4], + foundKey[t][s][5]); cjSetCursRight(); - - DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", sectorNo, tosendkey, t); + DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t); } trapped = 1; break; @@ -801,7 +813,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat uint8_t numSectors = arg0; uint8_t keyType = arg1; - uint64_t ui64Key = 0; struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; @@ -823,40 +834,40 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat DbprintfEx(FLAG_RAWPRINT, "Can't select card"); } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { - ui64Key = emlGetKey(sectorNo, keyType); - if (sectorNo == 0) { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + for (uint8_t s = 0; isOK && s < numSectors; s++) { + uint64_t ui64Key = emlGetKey(s, keyType); + if (s == 0) { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(s), keyType, ui64Key, AUTH_FIRST)) { isOK = false; if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo); + DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", s); break; } } else { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(s), keyType, ui64Key, AUTH_NESTED)) { isOK = false; if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", sectorNo); + DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", s); break; } } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(s); blockNo++) { + if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(s) + blockNo, dataoutbuf)) { isOK = false; if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo); + DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", s, blockNo); break; }; if (isOK) { *datain = 1; - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { - emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); + if (blockNo < NumBlocksPerSector(s) - 1) { + emlSetMem(dataoutbuf, FirstBlockOfSector(s) + blockNo, 1); } else { // sector trailer, keep the keys, set only the AC - emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + emlGetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); - emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + emlSetMem(dataoutbuf2, FirstBlockOfSector(s) + blockNo, 1); } } else { *datain = 0; From db78d26b9f13dccd7cb1995fb64b0b8438b80e29 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:33:34 +0200 Subject: [PATCH 078/141] styles --- armsrc/Standalone/hf_mattyrun.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 31243739b..1f2fb6f11 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -295,17 +295,15 @@ void RunMod() { /* Iterates through each sector checking if there is a correct key. */ - int key = -1; - int block = 0; bool err = 0; bool allKeysFound = true; uint32_t size = mfKeysCnt; for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { - block = blockNo; + int block = blockNo; for (int sec = 0; sec < sectorsCnt && !err; ++sec) { Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt); - key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); + int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); if (key == -1) { LED(LED_RED, 50); //red Dbprintf("\t✕ Key not found for this sector!"); @@ -393,12 +391,12 @@ void RunMod() { Needs further testing. */ if (fillFromEmulator) { - uint8_t retry = 5, cnt; + uint8_t retry = 5; Dbprintf("\t Trying to dump into blank card."); int flags = 0; LED_A_ON(); //yellow for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) { - cnt = 0; + uint8_t cnt = 0; emlGetMem(mblock, blockNum, 1); // switch on field and send magic sequence if (blockNum == 0) flags = 0x08 + 0x02; From 8e6920cd95de32144c323fd0eeaaa4c609d9679f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:40:59 +0200 Subject: [PATCH 079/141] fix styles and warnings --- armsrc/iclass.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 658962a3c..fd07a5916 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -855,7 +855,7 @@ void RAMFUNC SniffIClass(void) { //int datalen = 0; uint32_t previous_data = 0; - uint32_t time_0 = 0, time_start = 0, time_stop = 0; + uint32_t time_0 = 0, time_start = 0, time_stop; uint32_t sniffCounter = 0; bool TagIsActive = false; bool ReaderIsActive = false; @@ -1395,7 +1395,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf) { // To control where we are in the protocol uint32_t time_0 = GetCountSspClk(); uint32_t t2r_stime = 0, t2r_etime = 0; - uint32_t r2t_stime = 0, r2t_etime = 0; + uint32_t r2t_stime, r2t_etime = 0; LED_A_ON(); bool buttonPressed = false; @@ -1626,7 +1626,7 @@ send: */ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { int i = 0; - volatile uint8_t b = 0; + volatile uint8_t b; FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); @@ -1720,7 +1720,6 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int //----------------------------------------------------------------------------- void CodeIClassCommand(const uint8_t *cmd, int len) { int i, j, k; - uint8_t b; ToSendReset(); @@ -1732,7 +1731,7 @@ void CodeIClassCommand(const uint8_t *cmd, int len) { // Modulate the bytes for (i = 0; i < len; i++) { - b = cmd[i]; + uint8_t b = cmd[i]; for (j = 0; j < 4; j++) { for (k = 0; k < 4; k++) { @@ -1875,14 +1874,13 @@ void setupIclassReader() { } bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, uint8_t retries) { - uint8_t got_n = 0; while (retries-- > 0) { ReaderTransmitIClass(command, cmdsize); //iceman - if received size is bigger than expected, we smash the stack here // since its called with fixed sized arrays - got_n = ReaderReceiveIClass(resp); + uint8_t got_n = ReaderReceiveIClass(resp); // 0xBB is the internal debug separator byte.. if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { @@ -1983,9 +1981,7 @@ void ReaderIClass(uint8_t arg0) { //Read App Issuer Area block CRC(0x05) => 0xde 0x64 uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; - int read_status = 0; uint16_t tryCnt = 0; - uint8_t result_status = 0; bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag @@ -2008,9 +2004,9 @@ void ReaderIClass(uint8_t arg0) { } tryCnt++; - result_status = 0; + uint8_t result_status = 0; - read_status = handshakeIclassTag_ext(card_data, use_credit_key); + int read_status = handshakeIclassTag_ext(card_data, use_credit_key); if (read_status == 0) continue; if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN; From 3ab9dbe4c667167073dfb5035bd9e7f790acf4ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:52:52 +0200 Subject: [PATCH 080/141] fix styles --- armsrc/flashmem.c | 2 ++ armsrc/flashmem.h | 10 ---------- 2 files changed, 2 insertions(+), 10 deletions(-) diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 56b564b1d..d2010fe6d 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -504,10 +504,12 @@ bool Flash_Erase64k(uint8_t block) { return true; } +/* // Erase chip void Flash_EraseChip(void) { FlashSendLastByte(CHIPERASE); } +*/ void Flashmem_print_status(void) { DbpString("Flash memory"); diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 012d6ae7f..d899a4d31 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -101,9 +101,6 @@ #define MAX_BLOCKS 4 #define MAX_SECTORS 16 - - - #define MCK 48000000 //#define FLASH_BAUD 24000000 #define FLASH_MINFAST 24000000 //33000000 @@ -113,7 +110,6 @@ #define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) - //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// void Dbprintf(const char *fmt, ...); @@ -129,7 +125,6 @@ void Flash_TransferAdresse(uint32_t address); bool Flash_CheckBusy(uint32_t timeout); - void Flash_WriteEnable(); bool Flash_WipeMemoryPage(uint8_t page); bool Flash_WipeMemory(); @@ -137,18 +132,13 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector); //bool Flash_Erase32k(uint32_t address); bool Flash_Erase64k(uint8_t block); - void Flash_UniqueID(uint8_t *uid); uint8_t Flash_ReadID(void); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); - uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); - uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len); void Flashmem_print_status(void); - - #endif From 593202867a8c309aee76549bbbbe9b7257cf06f8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:56:35 +0200 Subject: [PATCH 081/141] remove include --- armsrc/mifareutil.h | 1 - 1 file changed, 1 deletion(-) diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index a25c64fa4..d0fb5c37f 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -21,7 +21,6 @@ #include "iso14443a.h" #include "crapto1/crapto1.h" #include "des.h" -#include "random.h" // fast_prand, prand // mifare authentication #define CRYPT_NONE 0 From ff74d567419119f2dd05a1a6d538d2cc49f5f79d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 10:58:50 +0200 Subject: [PATCH 082/141] remove unused --- armsrc/Makefile | 3 +-- common/random.c | 30 ------------------------------ common/random.h | 21 --------------------- 3 files changed, 1 insertion(+), 53 deletions(-) delete mode 100644 common/random.c delete mode 100644 common/random.h diff --git a/armsrc/Makefile b/armsrc/Makefile index ef6d8f675..5ec73b2b3 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -67,7 +67,7 @@ SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire SRC_CRC = crc.c crc16.c crc32.c SRC_ICLASS = iclass.c optimized_cipher.c SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c -SRC_BEE = bee.c +# SRC_BEE = bee.c # RDV40 related hardware support ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS))) @@ -161,7 +161,6 @@ THUMBSRC = start.c \ string.c \ BigBuf.c \ ticks.c \ - random.c \ hfsnoop.c diff --git a/common/random.c b/common/random.c deleted file mode 100644 index a6e714c4c..000000000 --- a/common/random.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "random.h" - -static uint32_t g_nextrandom; - -/* Generates a (non-cryptographically secure) 32-bit random number. - * - * We don't have an implementation of the "rand" function. Instead we use a - * method of seeding with the time it took to call "autoseed" from first run. - * - * https://github.com/Proxmark/proxmark3/pull/209/commits/f9c1dcd9f6e68a8c07cffed697a9c4c8caed6015 - * - * Iceman, rand needs to be fast. - * https://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/ - */ - -inline void fast_prand() { - fast_prandEx(GetTickCount()); -} -inline void fast_prandEx(uint32_t seed) { - g_nextrandom = seed; -} - -uint32_t prand() { -// g_nextrandom *= 6364136223846793005; -// g_nextrandom += 1; -//return (uint32_t)(g_nextrandom >> 32) % 0xffffffff; - g_nextrandom = (214013 * g_nextrandom + 2531011); - return (g_nextrandom >> 16) & 0xFFFF; -} - diff --git a/common/random.h b/common/random.h deleted file mode 100644 index 85c90dd38..000000000 --- a/common/random.h +++ /dev/null @@ -1,21 +0,0 @@ -//----------------------------------------------------------------------------- -// Micolous Jan 2017 -// Iceman Jan 2017 -// 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. -//----------------------------------------------------------------------------- -// pseudo rng generator. To be used when PM3 simulates Mifare tag. -// i.e. 'hf mf sim' -// 'hf 14a sim' -//----------------------------------------------------------------------------- - -#ifndef __RANDOM_H -#define __RANDOM_H - -#include "common.h" -#include "ticks.h" -void fast_prand(); -void fast_prandEx(uint32_t seed); -uint32_t prand(); -#endif From c9b3dd32d1ee75247181ad43537378aa2823dde0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 11:00:28 +0200 Subject: [PATCH 083/141] remove random --- armsrc/Standalone/hf_bog.h | 3 +-- armsrc/iso14443a.h | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/armsrc/Standalone/hf_bog.h b/armsrc/Standalone/hf_bog.h index 3588ff610..3dd68b3e2 100644 --- a/armsrc/Standalone/hf_bog.h +++ b/armsrc/Standalone/hf_bog.h @@ -20,8 +20,7 @@ #include #include "apps.h" #include "printf.h" - #include "parity.h" -#include "random.h" + #endif /* __HF_BOG_H */ diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 92638c10a..80cb6d105 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -27,7 +27,6 @@ extern "C" { #include "crapto1/crapto1.h" #include "mifareutil.h" #include "parity.h" -#include "random.h" #include "mifare.h" // structs // When the PM acts as tag and is receiving it takes From 49a0fda10b7317bf2a5cc27be6629203a100b412 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 11:36:24 +0200 Subject: [PATCH 084/141] styles --- armsrc/appmain.c | 26 +++++++++++--------------- armsrc/apps.h | 3 +-- 2 files changed, 12 insertions(+), 17 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c1967663e..56fecd948 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -78,10 +78,12 @@ void ToSendStuffBit(int b) { } } +/* useful when debugging new protocol implementations like FeliCa void PrintToSendBuffer(void) { DbpString("Printing ToSendBuffer:"); Dbhexdump(ToSendMax, ToSend, 0); } +*/ void print_result(char *name, uint8_t *buf, size_t len) { @@ -159,18 +161,17 @@ void Dbprintf(const char *fmt, ...) { // prints HEX & ASCII void Dbhexdump(int len, uint8_t *d, bool bAsci) { #if DEBUG - int l = 0, i; char ascii[9]; while (len > 0) { - l = (len > 8) ? 8 : len; + int l = (len > 8) ? 8 : len; memcpy(ascii, d, l); ascii[l] = 0; // filter safe ascii - for (i = 0; i < l; i++) { + for (int i = 0; i < l; i++) { if (ascii[i] < 32 || ascii[i] > 126) { ascii[i] = '.'; } @@ -230,7 +231,7 @@ uint16_t AvgAdc(int ch) { void MeasureAntennaTuning(void) { uint8_t LF_Results[256]; - uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0; + uint32_t i, peak = 0, peakv = 0, peakf = 0; uint32_t v_lf125 = 0, v_lf134 = 0, v_hf = 0; // in mV memset(LF_Results, 0, sizeof(LF_Results)); @@ -253,7 +254,7 @@ void MeasureAntennaTuning(void) { WDT_HIT(); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); SpinDelay(20); - adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); + uint32_t adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); if (i == 95) v_lf125 = adcval; // voltage at 125Khz if (i == 89) @@ -1177,8 +1178,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: { LED_B_ON(); uint8_t *mem = BigBuf_get_addr(); - bool isok = false; - size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; // arg0 = startindex @@ -1187,8 +1186,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); + size_t len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + bool isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); if (isok != 0) Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i + len, len); } @@ -1251,7 +1250,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_FLASHMEM_READ: { LED_B_ON(); - uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; @@ -1269,7 +1267,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { len = MIN((len - i), size); Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); - isok = Flash_ReadDataCont(startidx + i, mem, len); + uint16_t isok = Flash_ReadDataCont(startidx + i, mem, len); if (isok == len) { print_result("Chunk: ", mem, len); } else { @@ -1367,8 +1365,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_ON(); uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); - bool isok = false; - size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; // arg0 = startindex @@ -1380,9 +1376,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { } for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + size_t len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - isok = Flash_ReadDataCont(startidx + i, mem, len); + bool isok = Flash_ReadDataCont(startidx + i, mem, len); if (!isok) Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); diff --git a/armsrc/apps.h b/armsrc/apps.h index 4e3e1219b..90c53f146 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -58,7 +58,7 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci); uint16_t AvgAdc(int ch); void print_result(char *name, uint8_t *buf, size_t len); -void PrintToSendBuffer(void); +//void PrintToSendBuffer(void); void ToSendStuffBit(int b); void ToSendReset(void); void ListenReaderField(int limit); @@ -154,7 +154,6 @@ 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(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); From 4856252912e755478be22863ca5074a49b735e90 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 11:39:49 +0200 Subject: [PATCH 085/141] styles --- armsrc/iso14443a.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 465b73678..7f9040c43 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -500,8 +500,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { uint8_t *data = dmaBuf; uint8_t previous_data = 0; - int maxDataLen = 0; - int dataLen = 0; + int maxDataLen = 0, dataLen; bool TagIsActive = false; bool ReaderIsActive = false; @@ -1135,7 +1134,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t *data) { uint8_t emdata[MAX_FRAME_SIZE]; // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] int start = (receivedCmd[1] + 12) * 4; - int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; + len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; emlGetMemBt(emdata, start, len); AddCrc14A(emdata, len); EmSendCmd(emdata, len + 2); From 1e35130fbea441b2a86d8b9db4550d67bf86e36a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 11:41:43 +0200 Subject: [PATCH 086/141] missing include --- armsrc/appmain.c | 1 + 1 file changed, 1 insertion(+) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 56fecd948..fd0d4cafc 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -23,6 +23,7 @@ #include "lfsampling.h" #include "BigBuf.h" #include "mifareutil.h" +#include "mifaresim.h" #include "hitag.h" #define DEBUG 1 From a78af2bb06319f91b9f9554ff58a20d92677d79d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 11:51:12 +0200 Subject: [PATCH 087/141] rename crc -> crc_ctx. triggers overshadowing --- common/crc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/crc.h b/common/crc.h index 449b51bf3..7ad2fdc69 100644 --- a/common/crc.h +++ b/common/crc.h @@ -12,7 +12,7 @@ #include "common.h" //stdint, stddef, stdbool #include "util.h" // reflect, bswap_16 -typedef struct crc { +typedef struct crc_ctx { uint32_t state; int order; uint32_t polynom; From 91897f1f2e7d85acdbf6cac5e1615438c998c3f2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:06:48 +0200 Subject: [PATCH 088/141] copy bytes --- armsrc/Standalone/hf_young.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 866b13e0c..24e20dd7f 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -158,7 +158,7 @@ void RunMod() { Bytes 5-7 are reserved SAK and ATQA for mifare classic -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it */ - uint8_t oldBlock0[16] = {0}, newBlock0[16], testBlock0[16] = {0}; + uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; // arg0 = Flags, arg1=blockNo MifareCGetBlock(params, 0, oldBlock0); if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { @@ -166,7 +166,7 @@ void RunMod() { playing = 1; } else { Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); - memcpy(newBlock0, oldBlock0, 16); + memcpy(newBlock0 + 5, oldBlock0 + 5, 11); // Copy uid for bank (2nd is for longer UIDs not supported if classic) memcpy(newBlock0, uids[selected].uid, 4); From c4920d7179999d17b4550cae77a1055377997538 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:07:50 +0200 Subject: [PATCH 089/141] fix crc overshadowing --- armsrc/iso15693.c | 16 ++++++++-------- client/cmdhf15.c | 30 +++++++++++++++--------------- common/crc16.c | 2 +- common/crc16.h | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 497a6aa90..4afb54c9f 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -81,9 +81,9 @@ #define Logic1 Iso15693Logic1 #define FrameEOF Iso15693FrameEOF -#define Crc(data, len) crc(CRC_15693, (data), (len)) -#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) -#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +//#define Crc(data, len) Crc(CRC_15693, (data), (len)) +#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len)) +#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) #define sprintUID(target,uid) Iso15693sprintUID((target), (uid)) @@ -629,7 +629,7 @@ static void BuildIdentifyRequest(uint8_t *cmdout) { // no mask cmd[2] = 0x00; // CRC - AddCrc(cmd, 3); + AddCrc15(cmd, 3); // coding as high speed (1 out of 4) CodeIso15693AsReader(cmd, CMD_ID_RESP); memcpy(cmdout, cmd, CMD_ID_RESP); @@ -658,7 +658,7 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb // Block number to read cmd[10] = blockNumber;//0x00; // CRC - AddCrc(cmd, 11); + AddCrc15(cmd, 11); CodeIso15693AsReader(cmd, CMD_READ_RESP); memcpy(out, cmd, CMD_ID_RESP); } @@ -685,7 +685,7 @@ static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid) { cmd[8] = uid[1]; //0x05; cmd[9] = uid[0]; //0xe0; // CRC - AddCrc(cmd, 10); + AddCrc15(cmd, 10); CodeIso15693AsReader(cmd, CMD_INV_RESP); memcpy(cmdout, cmd, CMD_INV_RESP); } @@ -932,7 +932,7 @@ void BruteforceIso15693Afi(uint32_t speed) { data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; data[1] = ISO15_CMD_INVENTORY; data[2] = 0; // mask length - AddCrc(data, 3); + AddCrc15(data, 3); datalen += 2; recvlen = SendDataTag(data, datalen, false, speed, buf); @@ -951,7 +951,7 @@ void BruteforceIso15693Afi(uint32_t speed) { for (uint16_t i = 0; i < 256; i++) { data[2] = i & 0xFF; - AddCrc(data, 4); + AddCrc15(data, 4); datalen += 2; recvlen = SendDataTag(data, datalen, false, speed, buf); WDT_HIT(); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 31d266d6d..670c649ff 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -29,9 +29,9 @@ #define Logic1 Iso15693Logic1 #define FrameEOF Iso15693FrameEOF -#define Crc(data, len) crc(CRC_15693, (data), (len)) -#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) -#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +#define Crc15(data, len) Crc(CRC_15693, (data), (len)) +#define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len)) +#define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) #define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) @@ -198,7 +198,7 @@ int getUID(uint8_t *buf) { c.d.asBytes[1] = ISO15_CMD_INVENTORY; c.d.asBytes[2] = 0; // mask length - AddCrc(c.d.asBytes, 3); + AddCrc15(c.d.asBytes, 3); c.arg[0] = 5; // len uint8_t retry; @@ -212,7 +212,7 @@ int getUID(uint8_t *buf) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t resplen = resp.arg[0]; - if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { + if (resplen >= 12 && CheckCrc15(resp.d.asBytes, 12)) { memcpy(buf, resp.d.asBytes + 2, 8); return 1; } @@ -519,7 +519,7 @@ int CmdHF15Info(const char *Cmd) { if (!prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO)) return 0; - AddCrc(req, c.arg[0]); + AddCrc15(req, c.arg[0]); c.arg[0] += 2; //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); @@ -721,7 +721,7 @@ int CmdHF15Dump(const char *Cmd) { for (int retry = 0; retry < 5; retry++) { req[10] = blocknum; - AddCrc(req, 11); + AddCrc15(req, 11); c.arg[0] = 13; clearCommandBuffer(); @@ -737,7 +737,7 @@ int CmdHF15Dump(const char *Cmd) { recv = resp.d.asBytes; - if (!CheckCrc(recv, len)) { + if (!CheckCrc15(recv, len)) { PrintAndLogEx(FAILED, "crc fail"); continue; } @@ -958,7 +958,7 @@ int CmdHF15Raw(const char *Cmd) { } if (crc) { - AddCrc(data, datalen); + AddCrc15(data, datalen); datalen += 2; } @@ -1099,7 +1099,7 @@ int CmdHF15Readmulti(const char *Cmd) { req[reqlen++] = pagenum; req[reqlen++] = pagecount; - AddCrc(req, reqlen); + AddCrc15(req, reqlen); c.arg[0] = reqlen + 2; clearCommandBuffer(); @@ -1118,7 +1118,7 @@ int CmdHF15Readmulti(const char *Cmd) { recv = resp.d.asBytes; - if (!CheckCrc(recv, status)) { + if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); return 2; } @@ -1178,7 +1178,7 @@ int CmdHF15Read(const char *Cmd) { req[reqlen++] = (uint8_t)blocknum; - AddCrc(req, reqlen); + AddCrc15(req, reqlen); c.arg[0] = reqlen + 2; @@ -1198,7 +1198,7 @@ int CmdHF15Read(const char *Cmd) { recv = resp.d.asBytes; - if (!CheckCrc(recv, status)) { + if (!CheckCrc15(recv, status)) { PrintAndLogEx(NORMAL, "CRC failed"); return 2; } @@ -1261,7 +1261,7 @@ int CmdHF15Write(const char *Cmd) { req[reqlen++] = temp & 0xff; cmd2 += 2; } - AddCrc(req, reqlen); + AddCrc15(req, reqlen); c.arg[0] = reqlen + 2; PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); @@ -1282,7 +1282,7 @@ int CmdHF15Write(const char *Cmd) { recv = resp.d.asBytes; - if (!CheckCrc(recv, status)) { + if (!CheckCrc15(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); return 2; } diff --git a/common/crc16.c b/common/crc16.c index 075b5d724..1396c0fe8 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -191,7 +191,7 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8 *first = (crc & 0xFF); *second = ((crc >> 8) & 0xFF); } -uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) { +uint16_t Crc(CrcType_t ct, const uint8_t *d, size_t n) { // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) if (n < 3) return 0; diff --git a/common/crc16.h b/common/crc16.h index e59ed1832..843cc07e5 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -34,7 +34,7 @@ uint16_t update_crc16_ex(uint16_t crc, uint8_t c, uint16_t polynomial); uint16_t update_crc16(uint16_t crc, uint8_t c); uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout); -uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n); +uint16_t Crc(CrcType_t ct, const uint8_t *d, size_t n); void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8_t *second); bool check_crc(CrcType_t ct, const uint8_t *d, size_t n); From a8ad793f7f16ba928a5815639fc25e5127b44532 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:10:04 +0200 Subject: [PATCH 090/141] more crc overshadow --- client/cmdanalyse.c | 2 +- client/cmdhf15.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 5ca75b79f..3026e49d9 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -300,7 +300,7 @@ int CmdAnalyseCRC(const char *Cmd) { // ISO14443 crc B compute_crc(CRC_14443_B, data, len, &b1, &b2); uint16_t crcBB_1 = b1 << 8 | b2; - uint16_t bbb = crc(CRC_14443_B, data, len); + uint16_t bbb = Crc(CRC_14443_B, data, len); PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 670c649ff..877469fd5 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -479,7 +479,7 @@ int CmdHF15Demod(const char *Cmd) { for (i = 0; i < k; i++) PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); - PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2)); + PrintAndLogEx(NORMAL, "CRC %04x", Crc15(outBuf, k - 2)); return 0; } From a7448f802f62e6490c5e8df0566c179e2e0de3e1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Apr 2019 12:10:51 +0200 Subject: [PATCH 091/141] make style: don't indent preprocessor directives --- Makefile | 2 +- armsrc/Standalone/hf_colin.c | 40 ++++++++++++++++++------------------ client/cmdlfindala.c | 18 ++++++++-------- common/crc.h | 18 ++++++++-------- 4 files changed, 39 insertions(+), 39 deletions(-) diff --git a/Makefile b/Makefile index 77c205e68..512c9e2db 100644 --- a/Makefile +++ b/Makefile @@ -136,7 +136,7 @@ style: -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 \ + --indent=spaces=4 --indent-switches \ --keep-one-line-blocks --max-instatement-indent=60 \ --style=google --pad-oper --unpad-paren --pad-header \ --align-pointer=name {} \; diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 87f89883c..d477fe560 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -614,13 +614,13 @@ failtag: for (uint16_t s = 0; s < sectorsCnt; s++) { num_to_bytes(key64, 6, foundKey[i][s]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[i][s][0], - foundKey[i][s][1], - foundKey[i][s][2], - foundKey[i][s][3], - foundKey[i][s][4], - foundKey[i][s][5] - ); + foundKey[i][s][0], + foundKey[i][s][1], + foundKey[i][s][2], + foundKey[i][s][3], + foundKey[i][s][4], + foundKey[i][s][5] + ); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, i); } @@ -653,26 +653,26 @@ failtag: for (uint16_t s = 0; s < sectorsCnt; s++) { num_to_bytes(0x414c41524f4e, 6, foundKey[t][s]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][s][0], - foundKey[t][s][1], - foundKey[t][s][2], - foundKey[t][s][3], - foundKey[t][s][4], - foundKey[t][s][5]); + foundKey[t][s][0], + foundKey[t][s][1], + foundKey[t][s][2], + foundKey[t][s][3], + foundKey[t][s][4], + foundKey[t][s][5]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t); } - + t = 1; for (uint16_t s = 0; s < sectorsCnt; s++) { num_to_bytes(0x424c41524f4e, 6, foundKey[t][s]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", - foundKey[t][s][0], - foundKey[t][s][1], - foundKey[t][s][2], - foundKey[t][s][3], - foundKey[t][s][4], - foundKey[t][s][5]); + foundKey[t][s][0], + foundKey[t][s][1], + foundKey[t][s][2], + foundKey[t][s][3], + foundKey[t][s][4], + foundKey[t][s][5]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %s ; TYP: %d", s, tosendkey, t); } diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 985ae81d2..b136d9434 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -268,15 +268,15 @@ int CmdIndalaDemod(const char *Cmd) { PrintAndLogEx( SUCCESS , "Indala Found - bitlength %d, Raw 0x%x%08x%08x%08x%08x%08x%08x" - , DemodBufferLen - , uid1 - , uid2 - , uid3 - , uid4 - , uid5 - , uid6 - , uid7 - ); + , DemodBufferLen + , uid1 + , uid2 + , uid3 + , uid4 + , uid5 + , uid6 + , uid7 + ); } if (g_debugMode) { diff --git a/common/crc.h b/common/crc.h index 7ad2fdc69..7cb9caff9 100644 --- a/common/crc.h +++ b/common/crc.h @@ -64,14 +64,14 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size); /* Static initialization of a crc structure */ #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ - .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) \ - .refin = false, \ - .refout = false \ - } + .state = ((_initial_value) & ((1L<<(_order))-1)), \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) \ + .refin = false, \ + .refout = false \ +} #endif /* __CRC_H */ From 7eee2acfbf7317ac6adac2d319ecbe3a178af6e7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:10:52 +0200 Subject: [PATCH 092/141] more crc overshadow --- armsrc/iso15693.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 4afb54c9f..998c43520 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -780,7 +780,7 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { strncat(status, "No error ", DBD15STATLEN - strlen(status)); } - if (CheckCrc(d, len)) + if (CheckCrc15(d, len)) strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status)); else strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status)); From 8003d95be945db6c4b97a33f0f10f8efc110ed24 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:13:05 +0200 Subject: [PATCH 093/141] crc --- client/cmdanalyse.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 3026e49d9..3bd3f08cb 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -321,40 +321,40 @@ int CmdAnalyseCRC(const char *Cmd) { PrintAndLogEx(NORMAL, "CRC16 based\n\n"); // input from commandline - PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", Crc(CRC_CCITT, dataStr, sizeof(dataStr))); uint8_t poll[] = {0xb2, 0x4d, 0x12, 0x01, 0x01, 0x2e, 0x3d, 0x17, 0x26, 0x47, 0x80, 0x95, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f}; - PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll + 2, sizeof(poll) - 4)); - PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll + 2, sizeof(poll) - 2)); + PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", Crc(CRC_FELICA, poll + 2, sizeof(poll) - 4)); + PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", Crc(CRC_FELICA, poll + 2, sizeof(poll) - 2)); uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr) - 2)); + PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", Crc(CRC_ICLASS, sel_corr, sizeof(sel_corr) - 2)); PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); // ISO14443 crc A compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcAA = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, Crc(CRC_14443_A, dataStr, sizeof(dataStr))); // ISO14443 crc B compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcBB = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, Crc(CRC_14443_B, dataStr, sizeof(dataStr))); // ISO15693 crc (x.25) compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcCC = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, Crc(CRC_15693, dataStr, sizeof(dataStr))); // ICLASS compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcDD = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, Crc(CRC_ICLASS, dataStr, sizeof(dataStr))); // FeliCa compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcEE = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, Crc(CRC_FELICA, dataStr, sizeof(dataStr))); free(data); return 0; From 12739719915b43f93a384001765e93687ba1b7a3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:14:16 +0200 Subject: [PATCH 094/141] more crc --- client/scripting.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index 4d8aa5fe8..9c84bbf93 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -467,7 +467,7 @@ static int l_crc16(lua_State *L) { size_t size; const char *p_str = luaL_checklstring(L, 1, &size); - uint16_t checksum = crc(CRC_CCITT, (uint8_t *) p_str, size); + uint16_t checksum = Crc(CRC_CCITT, (uint8_t *) p_str, size); lua_pushunsigned(L, checksum); return 1; } From 9c3a5203000aea659e8ef1ca2d1265a2559c8d0f Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Apr 2019 12:18:15 +0200 Subject: [PATCH 095/141] iso14443a_select_card resp_data -> p_card --- armsrc/iso14443a.c | 32 ++++++++++++++++---------------- armsrc/iso14443a.h | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 7f9040c43..881bfa0bd 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2029,7 +2029,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { // if anticollision is false, then the UID must be provided in uid_ptr[] // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // requests ATS unless no_rats is true -int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { +int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 }; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; @@ -2043,19 +2043,19 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uin int cascade_level = 0; int len; - if (resp_data) { - resp_data->uidlen = 0; - memset(resp_data->uid, 0, 10); - resp_data->ats_len = 0; + if (p_card) { + p_card->uidlen = 0; + memset(p_card->uid, 0, 10); + p_card->ats_len = 0; } if (!GetATQA(resp, resp_par)) { return 0; } - if (resp_data) { - resp_data->atqa[0] = resp[0]; - resp_data->atqa[1] = resp[1]; + if (p_card) { + p_card->atqa[0] = resp[0]; + p_card->atqa[1] = resp[1]; } if (anticollision) { @@ -2150,14 +2150,14 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uin if (uid_ptr && anticollision) memcpy(uid_ptr + (cascade_level * 3), uid_resp, uid_resp_len); - if (resp_data) { - memcpy(resp_data->uid + (cascade_level * 3), uid_resp, uid_resp_len); - resp_data->uidlen += uid_resp_len; + if (p_card) { + memcpy(p_card->uid + (cascade_level * 3), uid_resp, uid_resp_len); + p_card->uidlen += uid_resp_len; } } - if (resp_data) { - resp_data->sak = sak; + if (p_card) { + p_card->sak = sak; } // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) @@ -2172,9 +2172,9 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uin if (!len) return 0; - if (resp_data) { - memcpy(resp_data->ats, resp, sizeof(resp_data->ats)); - resp_data->ats_len = len; + if (p_card) { + memcpy(p_card->ats, resp, sizeof(p_card->ats)); + p_card->ats_len = len; } // reset the PCB block number diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 80cb6d105..1e4de4626 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -129,7 +129,7 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); void iso14443a_setup(uint8_t fpga_minor_mode); int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res); -int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); +int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); void iso14a_set_trigger(bool enable); From ce5fcf1e2d89a276cd9109fdd786b7f1842a2cde Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:20:17 +0200 Subject: [PATCH 096/141] simplify --- bootrom/bootrom.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 53a33f525..e5cb77ff7 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -311,10 +311,9 @@ void BootROM(void) { common_area.magic = COMMON_AREA_MAGIC; common_area.version = 1; - common_area.flags.bootrom_present = 1; } - common_area.flags.bootrom_present = 1; + if (common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) { common_area.command = COMMON_AREA_COMMAND_NONE; flash_mode(1); From 7485c5ed2e2307a021dc250d191c886646b89d7c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Apr 2019 12:23:34 +0200 Subject: [PATCH 097/141] armsrc BitStream -> bits --- armsrc/apps.h | 6 +++--- armsrc/lfops.c | 20 ++++++++++---------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index 90c53f146..f4df953e5 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 *bits, int ledcontrol); +void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int ledcontrol); +void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, 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); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index d5a1d21c6..4b15c7320 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -824,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 *BitStream, int ledcontrol) { +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 @@ -846,7 +846,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, } for (i = 0; i < size; i++) { - if (BitStream[i]) + if (bits[i]) fcAll(fcLow, &n, clk, &modCnt); else fcAll(fcHigh, &n, clk, &modCnt); @@ -901,7 +901,7 @@ 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 *bits, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); @@ -914,20 +914,20 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, if (encoding == 2) { //biphase uint8_t phase = 0; for (i = 0; i < size; i++) { - biphaseSimBit(BitStream[i]^invert, &n, clk, &phase); + biphaseSimBit(bits[i]^invert, &n, clk, &phase); } if (phase == 1) { //run a second set inverted to keep phase in check for (i = 0; i < size; i++) { - biphaseSimBit(BitStream[i]^invert, &n, clk, &phase); + biphaseSimBit(bits[i]^invert, &n, clk, &phase); } } } else { // ask/manchester || ask/raw for (i = 0; i < size; i++) { - askSimBit(BitStream[i]^invert, &n, clk, encoding); + askSimBit(bits[i]^invert, &n, clk, encoding); } - if (encoding == 0 && BitStream[0] == BitStream[size - 1]) { //run a second set inverted (for ask/raw || biphase phase) + if (encoding == 0 && bits[0] == bits[size - 1]) { //run a second set inverted (for ask/raw || biphase phase) for (i = 0; i < size; i++) { - askSimBit(BitStream[i]^invert ^ 1, &n, clk, encoding); + askSimBit(bits[i]^invert ^ 1, &n, clk, encoding); } } } @@ -968,7 +968,7 @@ 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 *bits, int ledcontrol) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); @@ -978,7 +978,7 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream, uint8_t invert = arg2 & 0xFF; uint8_t curPhase = 0; for (i = 0; i < size; i++) { - if (BitStream[i] == curPhase) { + if (bits[i] == curPhase) { pskSimBit(carrier, &n, clk, &curPhase, false); } else { pskSimBit(carrier, &n, clk, &curPhase, true); From a7dea8f1e71a7bd815383c07b08231f4933d76ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:30:25 +0200 Subject: [PATCH 098/141] overshadowed buf. --- client/cliparser/cliparser.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index 766cf9ba4..6bba6f58b 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -26,7 +26,6 @@ int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { programHint = vprogramHint; programHelp = vprogramHelp; memset(buf, 0x00, 500); - return 0; } @@ -155,12 +154,12 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen = 0; int ibuf = 0; - uint8_t buf[256] = {0}; - int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX + uint8_t tmp_buf[256] = {0}; + int res = CLIParamStrToBuf(argstr, tmp_buf, maxdatalen * 2, &ibuf); // *2 because here HEX if (res || !ibuf) return res; - switch (param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { + switch (param_gethex_to_eol((char *)tmp_buf, 0, data, maxdatalen, datalen)) { case 1: printf("Parameter error: Invalid HEX value.\n"); return 1; @@ -180,15 +179,15 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int if (!argstr->count) return 0; - uint8_t buf[256] = {0}; + uint8_t tmp_buf[256] = {0}; int ibuf = 0; for (int i = 0; i < argstr->count; i++) { int len = strlen(argstr->sval[i]); - memcpy(&buf[ibuf], argstr->sval[i], len); + memcpy(&tmp_buf[ibuf], argstr->sval[i], len); ibuf += len; } - buf[ibuf] = 0; + tmp_buf[ibuf] = 0; if (!ibuf) return 0; @@ -196,7 +195,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int if (ibuf > maxdatalen) return 2; - memcpy(data, buf, ibuf); + memcpy(data, tmp_buf, ibuf); *datalen = ibuf; return 0; From 8c359921e927498d0ada94649f21f4c832062baf Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sun, 7 Apr 2019 12:30:49 +0200 Subject: [PATCH 099/141] keybytes for MifareUC_Auth --- armsrc/apps.h | 2 +- armsrc/mifarecmd.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/armsrc/apps.h b/armsrc/apps.h index f4df953e5..b4c38098c 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -143,7 +143,7 @@ void EPA_PACE_Replay(UsbCommand *c); // mifarecmd.h void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); -void MifareUC_Auth(uint8_t arg0, uint8_t *datain); +void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index d0822cfbb..56049a9cd 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -100,7 +100,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) LEDsoff(); } -void MifareUC_Auth(uint8_t arg0, uint8_t *datain) { +void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes) { bool turnOffField = (arg0 == 1); @@ -119,7 +119,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *datain) { return; }; - if (!mifare_ultra_auth(datain)) { + if (!mifare_ultra_auth(keybytes)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); return; From 69ba2d6a5b3a782c1acd9c2b10834ca99b9f072b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:33:33 +0200 Subject: [PATCH 100/141] rename variables in order to prevent a popular usbcommand named as c. --- client/util.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/util.h b/client/util.h index 83a5c87cd..dcd702fb0 100644 --- a/client/util.h +++ b/client/util.h @@ -174,7 +174,7 @@ #ifndef DropField #define DropField() { \ - UsbCommand c = {CMD_READER_ISO_14443a, {0,0,0}}; clearCommandBuffer(); SendCommand(&c); \ + UsbCommand c_drop = {CMD_READER_ISO_14443a, {0,0,0}}; clearCommandBuffer(); SendCommand(&c_drop); \ } #endif From 0b455607a9f7a183ac2da41225c4af8a59ffeb90 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 12:41:29 +0200 Subject: [PATCH 101/141] fsize can't be zero --- client/cmdhficlass.c | 8 ++++---- client/cmdhfmfu.c | 2 +- client/cmdsmartcard.c | 4 ++-- client/loclass/elite_crack.c | 2 +- client/loclass/fileutils.c | 2 +- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index c25bebdd3..ed73a98cc 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -636,7 +636,7 @@ int CmdHFiClassELoad(const char *Cmd) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogDevice(WARNING, "error, when getting filesize"); fclose(f); return 1; @@ -729,7 +729,7 @@ int CmdHFiClassDecrypt(const char *Cmd) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogEx(WARNING, "error, when getting filesize"); fclose(f); return 2; @@ -1609,7 +1609,7 @@ int CmdHFiClassReadTagFile(const char *Cmd) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogEx(WARNING, "Error, when getting filesize"); fclose(f); return 1; @@ -1766,7 +1766,7 @@ static int loadKeys(char *filename) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogEx(WARNING, "Error, when getting filesize"); fclose(f); return 1; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index f20665df6..45c67bcb3 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2076,7 +2076,7 @@ int CmdHF14AMfURestore(const char *Cmd) { fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogEx(WARNING, "Error, when getting filesize"); fclose(f); return 1; diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index b1c3c3797..a930d3be5 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -645,7 +645,7 @@ int CmdSmartUpgrade(const char *Cmd) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogEx(WARNING, "error, when getting filesize"); fclose(f); return 1; @@ -676,7 +676,7 @@ int CmdSmartUpgrade(const char *Cmd) { fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize < 0) { PrintAndLogEx(FAILED, "Could not determine size of SHA-512 file"); fclose(f); free(dump); diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 038d8e475..5a280e7c1 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -539,7 +539,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) { long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogDevice(WARNING, "Error, when getting filesize"); fclose(f); return 1; diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 4ac77633a..4bfe0129e 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -292,7 +292,7 @@ int loadFile(const char *preferredName, const char *suffix, void *data, size_t m long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if (fsize < 0) { + if (fsize <= 0) { PrintAndLogDevice(FAILED, "error, when getting filesize"); retval = 1; goto out; From 5ea649e59dc42da4ea42a37aed8830daab82b8d4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 15:18:02 +0200 Subject: [PATCH 102/141] style --- common/lfdemod.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index dfe959a37..abf7d82fe 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -984,10 +984,10 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif if (*fc != 2 && *fc != 4 && *fc != 8) return 0; - size_t waveStart = 0, waveEnd = 0, firstFullWave = 0, lastClkBit = 0; + size_t waveStart, waveEnd, firstFullWave = 0, lastClkBit; - uint8_t clkCnt, tol = 1; - uint16_t peakcnt = 0, errCnt = 0, waveLenCnt = 0, fullWaveLen = 0; + uint8_t clkCnt, tol; + uint16_t peakcnt, errCnt, waveLenCnt, fullWaveLen = 0; uint16_t bestErr[] = {1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000, 1000}; uint16_t peaksdet[] = {0, 0, 0, 0, 0, 0, 0, 0, 0}; @@ -1019,7 +1019,6 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif if (dest[i] < dest[i + 1] && dest[i + 1] >= dest[i + 2]) { if (waveStart == 0) { waveStart = i + 1; - waveLenCnt = 0; } else { //waveEnd waveEnd = i + 1; waveLenCnt = waveEnd - waveStart; @@ -1666,12 +1665,9 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, if (fclow == 0) fclow = 8; //set the threshold close to 0 (graph) or 128 std to avoid static - size_t preLastSample = 0; - size_t LastSample = 0; - size_t currSample = 0; - size_t last_transition = 0; - size_t idx; - size_t numBits = 0; + size_t preLastSample, LastSample = 0; + size_t currSample = 0, last_transition = 0; + size_t idx, numBits = 0; //find start of modulating data in trace idx = findModStart(dest, size, fchigh); @@ -1865,8 +1861,8 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s uint8_t curPhase = *invert; uint8_t fc = 0; - size_t i = 0, numBits = 0, waveStart = 1, waveEnd = 0, firstFullWave = 0, lastClkBit = 0; - uint16_t fullWaveLen = 0, waveLenCnt = 0, avgWaveVal = 0; + size_t i = 0, numBits = 0, waveStart = 1, waveEnd, firstFullWave = 0, lastClkBit = 0; + uint16_t fullWaveLen = 0, waveLenCnt, avgWaveVal = 0; uint16_t errCnt = 0, errCnt2 = 0; *clock = DetectPSKClock(dest, *size, *clock, &firstFullWave, &curPhase, &fc); @@ -1894,8 +1890,11 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s *startIdx = firstFullWave - (*clock * numBits) + 2; //set start of wave as clock align lastClkBit = firstFullWave; - if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i", firstFullWave, fullWaveLen, *startIdx); - if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit, fc); + if (g_debugMode == 2) { + prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i", firstFullWave, fullWaveLen, *startIdx); + prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit, fc); + } + waveStart = 0; dest[numBits++] = curPhase; //set first read bit for (i = firstFullWave + fullWaveLen - 1; i < *size - 3; i++) { @@ -1903,7 +1902,6 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s if (dest[i] + fc < dest[i + 1] && dest[i + 1] >= dest[i + 2]) { if (waveStart == 0) { waveStart = i + 1; - waveLenCnt = 0; avgWaveVal = dest[i + 1]; } else { //waveEnd waveEnd = i + 1; From d8f539c217e522a54de4c0f50c0fc561a0bc38e7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 15:20:27 +0200 Subject: [PATCH 103/141] style --- client/tinycbor/cbor.h | 2 +- client/tinycbor/cborparser.c | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/tinycbor/cbor.h b/client/tinycbor/cbor.h index a6175d3ab..238a2717f 100644 --- a/client/tinycbor/cbor.h +++ b/client/tinycbor/cbor.h @@ -409,7 +409,7 @@ CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next); -CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length); +CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len); CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next) { diff --git a/client/tinycbor/cborparser.c b/client/tinycbor/cborparser.c index 23e87f98a..2dade3a0d 100644 --- a/client/tinycbor/cborparser.c +++ b/client/tinycbor/cborparser.c @@ -208,7 +208,6 @@ static bool is_fixed_type(uint8_t type) { static CborError preparse_value(CborValue *it) { const CborParser *parser = it->parser; - it->type = CborInvalidType; /* are we at the end? */ if (it->ptr == parser->end) From 7bf24a170fcbd02d9a5a4e026ca2202a66bb7e26 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 15:22:01 +0200 Subject: [PATCH 104/141] style --- client/mifare/ndef.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index da03ecc8f..12f89b53e 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -115,7 +115,6 @@ int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { if (header->IDLenPresent) { header->IDLen = (header->ShortRecordBit ? (data[3]) : (data[6])); - header->Payload = header->Type + header->TypeLen; } else { header->IDLen = 0; } From ef610f373a7c14f1c590375240e636a25792cfb3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:21:27 +0200 Subject: [PATCH 105/141] style --- armsrc/lfops.c | 55 ++++++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 4b15c7320..cfb93b7d2 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -997,9 +997,8 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits, int // loop to get raw HID waveform then FSK demodulate the TAG ID from it void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - size_t size = 0; + size_t size; uint32_t hi2 = 0, hi = 0, lo = 0; - int idx = 0; int dummyIdx = 0; // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); @@ -1015,7 +1014,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) DoAcquisition_default(-1, true); // FSK demodulator size = 50 * 128 * 2; //big enough to catch 2 sequences of largest format - idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); + int idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); if (idx < 0) continue; if (idx > 0 && lo > 0 && (size == 96 || size == 192)) { @@ -1029,7 +1028,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) ); } else { //standard HID tags 44/96 bits uint8_t bitlen = 0; - uint32_t fc = 0; + uint32_t fac = 0; uint32_t cardnum = 0; if (((hi >> 5) & 1) == 1) { //if bit 38 is set then < 37 bit format is used @@ -1041,35 +1040,35 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) idx3++; } bitlen = idx3 + 19; - fc = 0; + fac = 0; cardnum = 0; if (bitlen == 26) { cardnum = (lo >> 1) & 0xFFFF; - fc = (lo >> 17) & 0xFF; + fac = (lo >> 17) & 0xFF; } if (bitlen == 37) { cardnum = (lo >> 1) & 0x7FFFF; - fc = ((hi & 0xF) << 12) | (lo >> 20); + fac = ((hi & 0xF) << 12) | (lo >> 20); } if (bitlen == 34) { cardnum = (lo >> 1) & 0xFFFF; - fc = ((hi & 1) << 15) | (lo >> 17); + fac = ((hi & 1) << 15) | (lo >> 17); } if (bitlen == 35) { cardnum = (lo >> 1) & 0xFFFFF; - fc = ((hi & 1) << 11) | (lo >> 21); + fac = ((hi & 1) << 11) | (lo >> 21); } } 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); + fac = ((hi & 0xF) << 12) | (lo >> 20); } Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", hi, lo, (lo >> 1) & 0xFFFF, bitlen, - fc, + fac, cardnum ); } @@ -1095,7 +1094,7 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) //big enough to catch 2 sequences of largest format size_t size = 12800; //50 * 128 * 2; - int idx = 0, dummyIdx = 0; + int dummyIdx = 0; BigBuf_Clear_keep_EM(); @@ -1109,7 +1108,7 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) DoAcquisition_default(-1, true); // FSK demodulator - idx = detectAWID(dest, &size, &dummyIdx); + int idx = detectAWID(dest, &size, &dummyIdx); if (idx <= 0 || size != 96) continue; // Index map @@ -1147,16 +1146,16 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) // w = wiegand parity // (26 bit format shown) - uint32_t fc = 0; + uint32_t fac = 0; uint32_t cardnum = 0; uint32_t code1 = 0; uint32_t code2 = 0; uint8_t fmtLen = bytebits_to_byte(dest, 8); if (fmtLen == 26) { - fc = bytebits_to_byte(dest + 9, 8); + fac = bytebits_to_byte(dest + 9, 8); cardnum = bytebits_to_byte(dest + 17, 16); code1 = bytebits_to_byte(dest + 8, fmtLen); - Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fac, cardnum, code1, rawHi2, rawHi, rawLo); } else { cardnum = bytebits_to_byte(dest + 8 + (fmtLen - 17), 16); if (fmtLen > 32) { @@ -1174,8 +1173,6 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) *low = rawLo; break; } - // reset - idx = 0; WDT_HIT(); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1186,8 +1183,8 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - size_t size = 0, idx = 0; - int clk = 0, invert = 0, errCnt = 0, maxErr = 20; + size_t size, idx = 0; + int clk = 0, invert = 0, errCnt, maxErr = 20; uint32_t hi = 0; uint64_t lo = 0; @@ -1238,7 +1235,7 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) } WDT_HIT(); hi = lo = size = idx = 0; - clk = invert = errCnt = 0; + clk = invert = 0; } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Stopped"); @@ -1249,7 +1246,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - int dummyIdx = 0, idx = 0; + int dummyIdx = 0; uint32_t code = 0, code2 = 0; uint8_t version = 0, facilitycode = 0, crc = 0; uint16_t number = 0, calccrc = 0; @@ -1269,7 +1266,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { //fskdemod and get start index WDT_HIT(); - idx = detectIOProx(dest, &size, &dummyIdx); + int idx = detectIOProx(dest, &size, &dummyIdx); if (idx < 0) continue; //valid tag found @@ -1325,8 +1322,6 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { code = code2 = 0; version = facilitycode = 0; number = 0; - idx = 0; - WDT_HIT(); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -1481,8 +1476,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { bool PwdMode = arg0 & 0x1; uint8_t Page = (arg0 & 0x2) >> 1; bool brute_mem = arg0 & 0x4; - - uint32_t i = 0; + uint32_t i; // regular read mode bool RegReadMode = (Block == 0xFF); @@ -1771,7 +1765,7 @@ void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) { #define EM410X_ID_LENGTH 40 void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { - int i, id_bit; + int i; uint64_t id = EM410X_HEADER; uint64_t rev_id = 0; // reversed ID int c_parity[4]; // column parity @@ -1790,7 +1784,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { } for (i = 0; i < EM410X_ID_LENGTH; ++i) { - id_bit = rev_id & 1; + int id_bit = rev_id & 1; if (i % 4 == 0) { // Don't write row parity bit at start of parsing @@ -1926,7 +1920,6 @@ uint8_t Prepare_Addr(uint8_t addr) { //==================================================================== uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) { - register uint8_t line_parity; register uint8_t column_parity; register uint8_t i, j; register uint16_t data; @@ -1935,7 +1928,7 @@ uint8_t Prepare_Data(uint16_t data_low, uint16_t data_hi) { column_parity = 0; for (i = 0; i < 4; i++) { - line_parity = 0; + register uint8_t line_parity = 0; for (j = 0; j < 8; j++) { line_parity ^= data; column_parity ^= (data & 1) << j; From c65d782d73108f4537af32b52faa134d19f47375 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:23:07 +0200 Subject: [PATCH 106/141] shadowing --- client/cmdhf14a.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index dad8495a3..dc85069ab 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -692,8 +692,8 @@ int CmdHF14ACUIDs(const char *Cmd) { PrintAndLogEx(WARNING, "card select failed."); } else { char uid_string[20]; - for (uint16_t i = 0; i < card->uidlen; i++) { - sprintf(&uid_string[2 * i], "%02X", card->uid[i]); + for (uint16_t m = 0; m < card->uidlen; m++) { + sprintf(&uid_string[2 * m], "%02X", card->uid[m]); } PrintAndLogEx(NORMAL, "%s", uid_string); } From 0ffe2a4700d8c7624f5caf88ebe8322ae0fcb61a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:25:19 +0200 Subject: [PATCH 107/141] shadowing --- client/cmdhf14a.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index dc85069ab..5ed16e747 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -418,7 +418,6 @@ int CmdHF14AInfo(const char *Cmd) { c.arg[2] = 0; clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; WaitForResponse(CMD_ACK, &resp); memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); From 03b44b324b8452ad7aa49a7f80cc2bb00ef1d0c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:30:02 +0200 Subject: [PATCH 108/141] assign --- client/cmdhfepa.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 0386155c1..ecd185783 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -61,8 +61,8 @@ int CmdHFEPACollectPACENonces(const char *Cmd) { // perform the PACE protocol by replaying APDUs int CmdHFEPAPACEReplay(const char *Cmd) { // the 4 APDUs which are replayed + their lengths - uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75]; - uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0}; + uint8_t msesa_apdu[41] = {0}, gn_apdu[8] = {0}, map_apdu[75] = {0}; + uint8_t pka_apdu[75] = {0}, ma_apdu[18] = {0}, apdu_lengths[5] = {0}; // pointers to the arrays to be able to iterate uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; @@ -74,15 +74,18 @@ int CmdHFEPAPACEReplay(const char *Cmd) { // Proxmark response UsbCommand resp; - int skip = 0, skip_add = 0, scan_return = 0; + int skip = 0, skip_add = 0, scan_return; // for each APDU for (int i = 0; i < sizeof(apdu_lengths); i++) { // scan to next space or end of string while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { // convert - scan_return = sscanf(Cmd + skip, "%2X%n", + scan_return = sscanf(Cmd + skip, + "%2X%n", (unsigned int *)(apdus[i] + apdu_lengths[i]), - &skip_add); + &skip_add + ); + if (scan_return < 1) { PrintAndLogEx(NORMAL, (char *)usage_msg); PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); From 9eba3a849a86131743179664c97211b1cd2258ae Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:34:21 +0200 Subject: [PATCH 109/141] shadowing --- client/whereami.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/client/whereami.c b/client/whereami.c index fe61273d2..9ecfd2870 100644 --- a/client/whereami.c +++ b/client/whereami.c @@ -287,11 +287,9 @@ int WAI_PREFIX(getModulePath)(char *out, int capacity, int *dirname_length) { memcpy(out, resolved, length); if (dirname_length) { - int i; - - for (i = length - 1; i >= 0; --i) { - if (out[i] == '/') { - *dirname_length = i; + for (int j = length - 1; j >= 0; --j) { + if (out[j] == '/') { + *dirname_length = j; break; } } From 8d9bd810201ae7cfe78b97caeee23ac2bb44c5c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 16:49:22 +0200 Subject: [PATCH 110/141] never used assignments --- client/mifare/mifarehost.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index de2ac2cfa..6c02ce05e 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -381,7 +381,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE / 6) ? (USB_CMD_DATA_SIZE / 6) : keycnt; uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00}; - for (int i = 0; i < keycnt; i += max_keys) { + for (i = 0; j < keycnt; i += max_keys) { int size = keycnt - i > max_keys ? max_keys : keycnt - i; @@ -775,7 +775,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; - nt = bytes_to_num(data, 4); + //nt = bytes_to_num(data, 4); return 0; } else { traceState = TRACE_ERROR; @@ -785,8 +785,8 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { case TRACE_AUTH2: if (len == 8) { traceState = TRACE_AUTH_OK; - nr_enc = bytes_to_num(data, 4); - ar_enc = bytes_to_num(data + 4, 4); + //nr_enc = bytes_to_num(data, 4); + //ar_enc = bytes_to_num(data + 4, 4); return 0; } else { traceState = TRACE_ERROR; @@ -835,7 +835,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { } else { PrintAndLogEx(NORMAL, "[!] nested key recovery not implemented!\n"); - at_enc = bytes_to_num(data, 4); + //at_enc = bytes_to_num(data, 4); crypto1_destroy(traceCrypto1); traceState = TRACE_ERROR; } From 27003904ce4572df6fba48042f1c2ab9b0108882 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 18:12:58 +0200 Subject: [PATCH 111/141] printandlogs.. --- client/cmddata.c | 4 +- client/cmdhf14a.c | 20 ++++---- client/cmdhfmfp.c | 2 +- client/emv/emvcore.c | 97 ++++++++++++++++++++++++------------ client/emv/test/cryptotest.c | 2 +- client/loclass/fileutils.c | 4 +- client/mifare/mifare4.c | 4 +- client/ui.h | 2 - client/util.c | 8 ++- 9 files changed, 86 insertions(+), 57 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 959472c58..f413a77ef 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1973,13 +1973,13 @@ int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { int firstClockEdge = 0; ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge); if (g_debugMode > 1) { - PrintAndLog("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); + PrintAndLogEx(NORMAL, "DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); } } // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { if (g_debugMode > 1) { - PrintAndLog("DEBUG FSKtoNRZ: no fsk clocks found"); + PrintAndLogEx(NORMAL,"DEBUG FSKtoNRZ: no fsk clocks found"); } return 0; } diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 5ed16e747..75f30f6f8 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -238,30 +238,30 @@ int Hf14443_4aGetCardData(iso14a_card_select_t *card) { uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision if (select_status == 0) { - PrintAndLog("E->iso14443a card select failed"); + PrintAndLogEx(ERR, "E->iso14443a card select failed"); return 1; } if (select_status == 2) { - PrintAndLog("E->Card doesn't support iso14443-4 mode"); + PrintAndLogEx(ERR, "E->Card doesn't support iso14443-4 mode"); return 1; } if (select_status == 3) { - PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); - PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLogEx(NORMAL, "E->Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(NORMAL, "\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); return 1; } - PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); - PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); - PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); + PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLogEx(NORMAL, "ATQA: %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLogEx(NORMAL, " SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); if (card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); + PrintAndLogEx(NORMAL, "E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); return 1; } - PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); - + + PrintAndLogEx(NORMAL, " ATS: %s", sprint_hex(card->ats, card->ats_len)); return 0; } diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 7178591a2..942000755 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -385,7 +385,7 @@ int CmdHFMFPRdbl(const char *cmd) { } if (blocksCount > 1 && mfIsSectorTrailer(blockn)) { - PrintAndLog("WARNING: trailer!"); + PrintAndLogEx(WARNING, "WARNING: trailer!"); } uint8_t sectorNum = mfSectorNum(blockn & 0xff); diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 43d6ddaf1..d30c307d4 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -34,24 +34,24 @@ typedef struct { static const TAIDList AIDlist [] = { // Visa International - { CV_VISA, "A00000000305076010"}, // VISA ELO Credit - { CV_VISA, "A0000000031010" }, // VISA Debit/Credit (Classic) - { CV_VISA, "A000000003101001" }, // VISA Credit - { CV_VISA, "A000000003101002" }, // VISA Debit - { CV_VISA, "A0000000032010" }, // VISA Electron - { CV_VISA, "A0000000032020" }, // VISA - { CV_VISA, "A0000000033010" }, // VISA Interlink - { CV_VISA, "A0000000034010" }, // VISA Specific - { CV_VISA, "A0000000035010" }, // VISA Specific - { CV_VISA, "A0000000036010" }, // Domestic Visa Cash Stored Value - { CV_VISA, "A0000000036020" }, // International Visa Cash Stored Value - { CV_VISA, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA) - { CV_VISA, "A0000000038010" }, // VISA Plus - { CV_VISA, "A0000000039010" }, // VISA Loyalty - { CV_VISA, "A000000003999910" }, // VISA Proprietary ATM + { CV_VISA, "A00000000305076010" }, // VISA ELO Credit + { CV_VISA, "A0000000031010" }, // VISA Debit/Credit (Classic) + { CV_VISA, "A000000003101001" }, // VISA Credit + { CV_VISA, "A000000003101002" }, // VISA Debit + { CV_VISA, "A0000000032010" }, // VISA Electron + { CV_VISA, "A0000000032020" }, // VISA + { CV_VISA, "A0000000033010" }, // VISA Interlink + { CV_VISA, "A0000000034010" }, // VISA Specific + { CV_VISA, "A0000000035010" }, // VISA Specific + { CV_VISA, "A0000000036010" }, // Domestic Visa Cash Stored Value + { CV_VISA, "A0000000036020" }, // International Visa Cash Stored Value + { CV_VISA, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA) + { CV_VISA, "A0000000038010" }, // VISA Plus + { CV_VISA, "A0000000039010" }, // VISA Loyalty + { CV_VISA, "A000000003999910" }, // VISA Proprietary ATM // Visa USA - { CV_VISA, "A000000098" }, // Debit Card - { CV_VISA, "A0000000980848" }, // Debit Card + { CV_VISA, "A000000098" }, // Debit Card + { CV_VISA, "A0000000980848" }, // Debit Card // Mastercard International { CV_MASTERCARD, "A00000000401" }, // MasterCard PayPass { CV_MASTERCARD, "A0000000041010" }, // MasterCard Credit @@ -66,6 +66,7 @@ static const TAIDList AIDlist [] = { { CV_MASTERCARD, "A0000000046000" }, // Cirrus { CV_MASTERCARD, "A0000000048002" }, // SecureCode Auth EMV-CAP { CV_MASTERCARD, "A0000000049999" }, // MasterCard PayPass + { CV_MASTERCARD, "B012345678" }, // Maestro TEST Used for development // American Express { CV_AMERICANEXPRESS, "A000000025" }, { CV_AMERICANEXPRESS, "A0000000250000" }, @@ -82,11 +83,41 @@ static const TAIDList AIDlist [] = { // JCB CO., LTD. { CV_JCB, "A00000006510" }, // JCB { CV_JCB, "A0000000651010" }, // JCB J Smart Credit + // Switch Card Services Ltd. + { CV_SWITCH, "A0000000050001" }, // Maestro UK + { CV_SWITCH, "A0000000050002" }, // Solo + // Diners Club International Ltd. + { CV_DINERS, "A0000001523010" }, // Discover, Pulse D Pas Discover Card + { CV_DINERS, "A0000001524010" }, // Discover, Discover Debit Common Card // Other - { CV_OTHER, "A0000001544442" }, // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A. - { CV_OTHER, "F0000000030001" }, // BRADESCO - { CV_OTHER, "A0000005241010" }, // RuPay - RuPay - { CV_OTHER, "D5780000021010" } // Bankaxept - Bankaxept + { CV_OTHER, "A00000002401" }, // Midland Bank Plc - Self Service + { CV_OTHER, "A0000000291010" }, // LINK Interchange Network Ltd - Link / American Express + { CV_OTHER, "A00000006900" }, // Société Européenne de Monnaie Electronique SEME - Moneo + { CV_OTHER, "A000000077010000021000000000003B" }, // Oberthur Technologies France - Visa AEPN + { CV_OTHER, "A0000001211010" }, // PBS Danmark A/S - Denmark - Dankort (VISA GEM Vision) - Danish domestic debit card + { CV_OTHER, "A0000001410001" }, // Associazione Bancaria Italiana - Italy - PagoBANCOMAT - CoGeBan Consorzio BANCOMAT (Italian domestic debit card) + { CV_OTHER, "A0000001544442" }, // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A. + { CV_OTHER, "A000000172950001" }, // Financial Information Service Co. Ltd. - Taiwan - BAROC Financial Application Taiwan- The Bankers Association of the Republic of China + { CV_OTHER, "A0000001850002" }, // Post Office Limited - United Kingdom - UK Post Office Account card + { CV_OTHER, "A0000002281010" }, // Saudi Arabian Monetary Agency (SAMA) - Kingdom of Saudi Arabia - SPAN (M/Chip) - SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency) + { CV_OTHER, "A0000002282010" }, // Saudi Arabian Monetary Agency (SAMA) - Kingdom of Saudi Arabia - SPAN (VIS) - SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency) + { CV_OTHER, "A0000002771010" }, // Interac Association - Canada - INTERAC - Canadian domestic credit/debit card + { CV_OTHER, "A00000031510100528" }, // Currence Holding/PIN BV - The Netherlands- Currence PuC + { CV_OTHER, "A0000003156020" }, // Currence Holding/PIN BV - The Netherlands - Chipknip + { CV_OTHER, "A0000003591010028001" }, // Euro Alliance of Payment Schemes s.c.r.l. (EAPS) - Belgium - Girocard EAPS - ZKA (Germany) + { CV_OTHER, "A0000003710001" }, // Verve - Nigeria - InterSwitch Verve Card - Nigerian local switch company + { CV_OTHER, "A0000004540010" }, // eTranzact - Nigeria - Etranzact Genesis Card - Nigerian local switch company + { CV_OTHER, "A0000004540011" }, // eTranzact - Nigeria - Etranzact Genesis Card 2 - Nigerian local switch company + { CV_OTHER, "A0000004766C" }, // Google - United States - GOOGLE_PAYMENT_AID + { CV_OTHER, "A0000005241010" }, // RuPay - India - RuPay - RuPay (India) + { CV_OTHER, "A0000006723010" }, // TROY - Turkey - TROY chip credit card - Turkey's Payment Method + { CV_OTHER, "A0000006723020" }, // TROY - Turkey - TROY chip debit card - Turkey's Payment Method + { CV_OTHER, "A0000007705850" }, // Indian Oil Corporation Limited - India - XTRAPOWER Fleet Card Program - Indian Oil’s Pre Paid Program + { CV_OTHER, "D27600002545500100" }, // ZKA - Germany - Girocard - ZKA Girocard (Geldkarte) (Germany) + { CV_OTHER, "D4100000030001" }, // KS X 6923/6924 (T-Money, South Korea and Snapper+, Wellington, New Zealand) + { CV_OTHER, "D5280050218002" }, // The Netherlands - ? - (Netherlands) + { CV_OTHER, "D5780000021010" }, // Bankaxept Norway Bankaxept Norwegian domestic debit card + { CV_OTHER, "F0000000030001" }, // BRADESCO - Brazilian Bank Banco Bradesco }; static const size_t AIDlistLen = sizeof(AIDlist) / sizeof(TAIDList); @@ -403,6 +434,8 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO int res; bool fileFound = false; + char *PSE_or_PPSE = PSENum == 1 ? "PSE" : "PPSE"; + // select PPSE res = EMVSelectPSE(channel, ActivateField, true, PSENum, data, sizeof(data), &datalen, &sw); @@ -452,7 +485,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO if (tsfi) { struct tlvdb *tsfitmp = tlvdb_find_path(tsfi, (tlv_tag_t[]) {0x70, 0x61, 0x00}); if (!tsfitmp) { - PrintAndLogEx(FAILED, "SFI 0x%02d don't have records.", sfidatalen[ui]); + PrintAndLogEx(FAILED, "SFI 0x%02d doesn't have any records.", sfidatalen[ui]); continue; } res = EMVCheckAID(channel, decodeTLV, tsfitmp, tlv); @@ -472,14 +505,14 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO } if (!fileFound) - PrintAndLogEx(FAILED, "PPSE don't have records."); + PrintAndLogEx(FAILED, "PPSE doesn't have any records."); tlvdb_free(t); } else { - PrintAndLogEx(WARNING, "PPSE ERROR: Can't get TLV from response."); + PrintAndLogEx(WARNING, "%s ERROR: Can't get TLV from response.", PSE_or_PPSE); } } else { - PrintAndLogEx(WARNING, "PPSE ERROR: Can't select PPSE AID. Error: %d", res); + PrintAndLogEx(WARNING, "%s ERROR: Can't select PPSE AID. Error: %d", PSE_or_PPSE, res); } if (!LeaveFieldON) @@ -798,7 +831,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { return 4; } - PrintAndLogEx(NORMAL, "\n* * Calc DDOL"); + PrintAndLogEx(NORMAL, "\n* Calc DDOL"); const struct tlv *ddol_tlv = tlvdb_get(tlv, 0x9f49, NULL); if (!ddol_tlv) { ddol_tlv = &default_ddol_tlv; @@ -816,7 +849,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { PrintAndLogEx(NORMAL, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); - PrintAndLogEx(NORMAL, "\n* * Internal Authenticate"); + PrintAndLogEx(NORMAL, "\n* Internal Authenticate"); int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); if (res) { PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw); @@ -843,7 +876,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { tlvdb_free(t80); if (decodeTLV) { - PrintAndLogEx(NORMAL, "* * * Decode response format 1:"); + PrintAndLogEx(NORMAL, "* * Decode response format 1:"); TLVPrintFromTLV(dda_db); } } @@ -934,7 +967,7 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv); if (!icc_pk) { - PrintAndLogEx(WARNING, "Error: ICC setrificate not found. Exit."); + PrintAndLogEx(WARNING, "Error: ICC certificate not found. Exit."); emv_pk_free(pk); emv_pk_free(issuer_pk); return 2; @@ -976,7 +1009,7 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st PrintAndLogEx(NORMAL, "CDA verified OK."); tlvdb_add(tlv, idn_db); } else { - PrintAndLogEx(NORMAL, "\nERROR: CDA verify error"); + PrintAndLogEx(ERR, "\nERROR: CDA verify error"); } emv_pk_free(pk); @@ -989,14 +1022,14 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { struct emv_pk *pk = get_ca_pk(tlvRoot); if (!pk) { - PrintAndLog("ERROR: Key not found. Exit."); + PrintAndLogEx(ERR, "ERROR: Key not found. Exit."); return 1; } struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot); if (!issuer_pk) { emv_pk_free(pk); - PrintAndLog("WARNING: Issuer certificate not found. Exit."); + PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit."); return 2; } PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx", diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 39043e544..4bb49f039 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -94,7 +94,7 @@ int ExecuteCryptoTests(bool verbose) { res = roca_self_test(); if (res) TestFail = true; - PrintAndLog("\n--------------------------"); + PrintAndLogEx(NORMAL, "\n--------------------------"); if (TestFail) PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_("FAIL")); diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 4bfe0129e..d85adc0c8 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -405,13 +405,13 @@ int loadFileJSON(const char *preferredName, const char *suffix, void *data, size root = json_load_file(fileName, 0, &error); if (!root) { - PrintAndLog("ERROR: json " _YELLOW_("%s") " error on line %d: %s", fileName, error.line, error.text); + PrintAndLogEx(ERR, "ERROR: json " _YELLOW_("%s") " error on line %d: %s", fileName, error.line, error.text); retval = 2; goto out; } if (!json_is_object(root)) { - PrintAndLog("ERROR: Invalid json " _YELLOW_("%s") " format. root must be an object.", fileName); + PrintAndLogEx(ERR, "ERROR: Invalid json " _YELLOW_("%s") " format. root must be an object.", fileName); retval = 3; goto out; } diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index b3d40dd57..f3189f37f 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -164,7 +164,7 @@ int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t } if (verbose) - PrintAndLog("MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen)); + PrintAndLogEx(NORMAL, "MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen)); return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); } @@ -285,7 +285,7 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF DropField(); if (verbose) - PrintAndLog(""); + PrintAndLogEx(NORMAL, ""); if (session) { session->Authenticated = true; diff --git a/client/ui.h b/client/ui.h index 7df965976..cace7e6fd 100644 --- a/client/ui.h +++ b/client/ui.h @@ -44,8 +44,6 @@ extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, extern bool GridLocked; extern bool showDemod; -//extern uint8_t g_debugMode; - extern pthread_mutex_t print_lock; void iceIIR_Butterworth(int *data, const size_t len); diff --git a/client/util.c b/client/util.c index 8be1aa896..b257ea766 100644 --- a/client/util.c +++ b/client/util.c @@ -128,13 +128,13 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) { va_start(valist, dataLength); uint8_t *vdata = NULL; - size_t vlength = 0; + do { vdata = va_arg(valist, uint8_t *); if (!vdata) break; - vlength = va_arg(valist, size_t); + size_t vlength = va_arg(valist, size_t); if (*dataLength + vlength > maxDataLength) { va_end(valist); return 1; @@ -650,12 +650,10 @@ https://github.com/ApertureLabsLtd/RFIDler/blob/master/firmware/Pic32/RFIDler.X/ int hextobinarray(char *target, char *source) { int length, i, count = 0; char *start = source; - char x; - length = strlen(source); // process 4 bits (1 hex digit) at a time while (length--) { - x = *(source++); + char x = *(source++); // capitalize if (x >= 'a' && x <= 'f') x -= 32; From 4c4471331b0e32ae8560dec82aac803d202a2280 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 18:32:03 +0200 Subject: [PATCH 112/141] fix --- client/mifare/mifarehost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 6c02ce05e..181d41e87 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -381,7 +381,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE / 6) ? (USB_CMD_DATA_SIZE / 6) : keycnt; uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00}; - for (i = 0; j < keycnt; i += max_keys) { + for (i = 0; i < keycnt; i += max_keys) { int size = keycnt - i > max_keys ? max_keys : keycnt - i; From c881acd6311c22640ff3e8d9f5fca28f990928e3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 18:35:01 +0200 Subject: [PATCH 113/141] more --- client/emv/emvcore.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 806a9366f..25adc2b85 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -61,6 +61,8 @@ enum CardPSVendor { CV_AMERICANEXPRESS, CV_JCB, CV_CB, + CV_SWITCH, + CV_DINERS, CV_OTHER, }; enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen); From 98d24a4fe8d38d08227e73b7b20c64daa7ce1a89 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 18:42:47 +0200 Subject: [PATCH 114/141] style --- client/cliparser/argtable3.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index f8e4c2387..e1bedbb4f 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -2960,10 +2960,19 @@ static int trex_class(TRex *exp) { while (*exp->_p != ']' && exp->_p != exp->_eol) { if (*exp->_p == '-' && first != -1) { int r, t; - if (*exp->_p++ == ']') trex_error(exp, _SC("unfinished range")); + if (*exp->_p++ == ']') { + trex_error(exp, _SC("unfinished range")); + } + r = trex_newnode(exp, OP_RANGE); - if (first > *exp->_p) trex_error(exp, _SC("invalid range")); - if (exp->_nodes[first].type == OP_CCLASS) trex_error(exp, _SC("cannot use character classes in ranges")); + if (first > *exp->_p) { + trex_error(exp, _SC("invalid range")); + } + + if (exp->_nodes[first].type == OP_CCLASS) { + trex_error(exp, _SC("cannot use character classes in ranges")); + } + exp->_nodes[r].left = exp->_nodes[first].type; t = trex_escapechar(exp); exp->_nodes[r].right = t; @@ -2984,8 +2993,6 @@ static int trex_class(TRex *exp) { if (first != -1) { int c = first; exp->_nodes[chain].next = c; - chain = c; - first = -1; } /* hack? */ exp->_nodes[ret].left = exp->_nodes[ret].next; @@ -4541,8 +4548,9 @@ void arg_print_formatted(FILE *fp, const unsigned colwidth = (rmargin - lmargin) + 1; /* Someone doesn't like us... */ - if (line_end < line_start) - { fprintf(fp, "%s\n", text); } + if (line_end == line_start) { + fprintf(fp, "%s\n", text); + } while (line_end - 1 > line_start) { /* Eat leading whitespaces. This is essential because while From b6345a5df7406b1ebb9d3028efe26849b51a842a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 18:44:15 +0200 Subject: [PATCH 115/141] style --- client/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index ed73a98cc..5688fb8e1 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1109,7 +1109,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { PrintAndLogEx(WARNING, "command execute timeout 2"); return 0; } - uint8_t isOK = resp.arg[0] & 0xff; + isOK = resp.arg[0] & 0xff; blocksRead = resp.arg[1]; if (!isOK && !blocksRead) { PrintAndLogEx(WARNING, "read block failed 2"); From c4d88c239bc522154ee475360ce2e9eac4353329 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 19:21:24 +0200 Subject: [PATCH 116/141] style --- client/jansson/jansson.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/jansson/jansson.h b/client/jansson/jansson.h index b832a791f..e282674f3 100644 --- a/client/jansson/jansson.h +++ b/client/jansson/jansson.h @@ -243,7 +243,7 @@ int json_array_append_new(json_t *json, json_t *value); int json_array_insert_new(json_t *json, size_t index, json_t *value); int json_array_remove(json_t *json, size_t index); int json_array_clear(json_t *json); -int json_array_extend(json_t *json, json_t *other); +int json_array_extend(json_t *json, json_t *other_json); static JSON_INLINE int json_array_set(json_t *array, size_t ind, json_t *value) { @@ -262,16 +262,16 @@ int json_array_insert(json_t *array, size_t ind, json_t *value) { const char *json_string_value(const json_t *json); size_t json_string_length(const json_t *json); -json_int_t json_integer_value(const json_t *integer); -double json_real_value(const json_t *real); +json_int_t json_integer_value(const json_t *json); +double json_real_value(const json_t *json); double json_number_value(const json_t *json); int json_string_set(json_t *json, const char *value); int json_string_setn(json_t *json, const char *value, size_t len); int json_string_set_nocheck(json_t *json, const char *value); int json_string_setn_nocheck(json_t *json, const char *value, size_t len); -int json_integer_set(json_t *integer, json_int_t value); -int json_real_set(json_t *real, double value); +int json_integer_set(json_t *json, json_int_t value); +int json_real_set(json_t *json, double value); /* pack, unpack */ @@ -294,13 +294,13 @@ json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_res /* equality */ -int json_equal(const json_t *value1, const json_t *value2); +int json_equal(const json_t *json1, const json_t *json2); /* copying */ -json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result); -json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result); +json_t *json_copy(json_t *json) JANSSON_ATTRS(warn_unused_result); +json_t *json_deep_copy(const json_t *json) JANSSON_ATTRS(warn_unused_result); json_t *json_path_get(const json_t *json, const char *path); int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); From b37981df74832b053598a5de1eba2c3f13e9b449 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:08:53 +0200 Subject: [PATCH 117/141] shadow --- client/cmdhfmf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index f00093acb..4706017cb 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1683,7 +1683,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { + for (i = 0; i < keycnt; i += chunksize) { if (ukbhit()) { int gc = getchar(); @@ -1717,7 +1717,7 @@ out: // check.. uint8_t found_keys = 0; - for (uint8_t i = 0; i < sectorsCnt; ++i) { + for (i = 0; i < sectorsCnt; ++i) { if (e_sector[i].foundKey[0]) found_keys++; @@ -1734,7 +1734,7 @@ out: if (transferToEml) { uint8_t block[16] = {0x00}; - for (uint8_t i = 0; i < sectorsCnt; ++i) { + for ( i = 0; i < sectorsCnt; ++i) { mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); @@ -1929,7 +1929,7 @@ int CmdHF14AMfChk(const char *Cmd) { } // empty e_sector - for (int i = 0; i < SectorsCnt; ++i) { + for (i = 0; i < SectorsCnt; ++i) { e_sector[i].Key[0] = 0xffffffffffff; e_sector[i].Key[1] = 0xffffffffffff; e_sector[i].foundKey[0] = false; @@ -1948,7 +1948,7 @@ int CmdHF14AMfChk(const char *Cmd) { for (trgKeyType = (keyType == 2) ? 0 : keyType; trgKeyType < 2; (keyType == 2) ? (++trgKeyType) : (trgKeyType = 2)) { int b = blockNo; - for (int i = 0; i < SectorsCnt; ++i) { + for (i = 0; i < SectorsCnt; ++i) { // skip already found keys. if (e_sector[i].foundKey[trgKeyType]) continue; @@ -2022,7 +2022,7 @@ out: if (transferToEml) { uint8_t block[16] = {0x00}; - for (uint8_t i = 0; i < SectorsCnt; ++i) { + for (i = 0; i < SectorsCnt; ++i) { mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); if (e_sector[i].foundKey[0]) num_to_bytes(e_sector[i].Key[0], 6, block); From f27d618a0837826401208c1bbdece21a8a13205a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:12:24 +0200 Subject: [PATCH 118/141] shadowing --- client/cmdhfmfhard.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 415bcbaa2..12aec1cb2 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1284,7 +1284,6 @@ static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t } - static void simulate_acquire_nonces() { time_t time1 = time(NULL); last_sample_clock = 0; @@ -1292,7 +1291,7 @@ static void simulate_acquire_nonces() { hardnested_stage = CHECK_1ST_BYTES; bool acquisition_completed = false; uint32_t total_num_nonces = 0; - float brute_force; + float brute_force_depth; bool reported_suma8 = false; cuid = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff); @@ -1331,19 +1330,19 @@ static void simulate_acquire_nonces() { apply_sum_a0(); } update_nonce_data(true); - acquisition_completed = shrink_key_space(&brute_force); + acquisition_completed = shrink_key_space(&brute_force_depth); if (!reported_suma8) { char progress_string[80]; sprintf(progress_string, "Apply Sum property. Sum(a0) = %d", sums[first_byte_Sum]); - hardnested_print_progress(num_acquired_nonces, progress_string, brute_force, 0); + hardnested_print_progress(num_acquired_nonces, progress_string, brute_force_depth, 0); reported_suma8 = true; } else { - hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force, 0); + hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force_depth, 0); } } else { update_nonce_data(true); - acquisition_completed = shrink_key_space(&brute_force); - hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force, 0); + acquisition_completed = shrink_key_space(&brute_force_depth); + hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force_depth, 0); } } while (!acquisition_completed); @@ -1369,7 +1368,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ uint32_t flags = 0; uint8_t write_buf[9]; uint32_t total_num_nonces = 0; - float brute_force; + float brute_force_depth; bool reported_suma8 = false; char progress_text[80]; FILE *fnonces = NULL; @@ -1453,19 +1452,19 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ apply_sum_a0(); } update_nonce_data(true); - acquisition_completed = shrink_key_space(&brute_force); + acquisition_completed = shrink_key_space(&brute_force_depth); if (!reported_suma8) { char progress_string[80]; sprintf(progress_string, "Apply Sum property. Sum(a0) = %d", sums[first_byte_Sum]); - hardnested_print_progress(num_acquired_nonces, progress_string, brute_force, 0); + hardnested_print_progress(num_acquired_nonces, progress_string, brute_force_depth, 0); reported_suma8 = true; } else { - hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force, 0); + hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force_depth, 0); } } else { update_nonce_data(true); - acquisition_completed = shrink_key_space(&brute_force); - hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force, 0); + acquisition_completed = shrink_key_space(&brute_force_depth); + hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force_depth, 0); } } @@ -2293,8 +2292,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc } hardnested_stage = CHECK_1ST_BYTES | CHECK_2ND_BYTES; update_nonce_data(false); - float brute_force; - shrink_key_space(&brute_force); + float brute_force_depth; + shrink_key_space(&brute_force_depth); } else { // acquire nonces. uint16_t is_OK = acquire_nonces(blockNo, keyType, key, trgBlockNo, trgKeyType, nonce_file_write, slow, filename); if (is_OK != 0) { From 648706d691702d1dcffa193eecd70852971ddf75 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:13:30 +0200 Subject: [PATCH 119/141] shadowing --- client/cmdlf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 1ea81b6ed..1246b5f04 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -228,7 +228,7 @@ int CmdFlexdemod(const char *Cmd) { i = start; for (bit = 0; bit < 64; bit++) { sum = 0; - for (int j = 0; j < 16; j++) { + for (j = 0; j < 16; j++) { sum += data[i++]; } bits[bit] = (sum > 0) ? 1 : 0; From e95955b793baf67a1839ab1e26a5dec1a60b878c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:17:59 +0200 Subject: [PATCH 120/141] shadowing --- client/cmdlfem4x.c | 13 +++++-------- client/cmdlfem4x.h | 1 - 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index b3e0c42dd..f68bf04b4 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -254,13 +254,11 @@ void printEM410x(uint32_t hi, uint64_t id) { PrintAndLogEx(SUCCESS, "EM410x %s pattern found", (hi) ? "XL" : ""); - uint64_t iii = 1; uint64_t id2lo = 0; - uint32_t ii = 0; - uint32_t i = 0; - for (ii = 5; ii > 0; ii--) { + uint8_t m =, i = 0; + for (m = 5; m > 0; m--) { for (i = 0; i < 8; i++) { - id2lo = (id2lo << 1LL) | ((id & (iii << (i + ((ii - 1) * 8)))) >> (i + ((ii - 1) * 8))); + id2lo = (id2lo << 1LL) | ((id & (mi << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); } } @@ -299,10 +297,9 @@ void printEM410x(uint32_t hi, uint64_t id) { uint32_t p1id = (id & 0xFFFFFF); uint8_t arr[32] = {0x00}; - int i = 0; int j = 23; - for (; i < 24; ++i, --j) { - arr[i] = (p1id >> i) & 1; + for (int k = 0 ; k < 24; ++k, --j) { + arr[k] = (p1id >> k) & 1; } uint32_t p1 = 0; diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index 08670a4b3..383b9fa57 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -27,7 +27,6 @@ int CmdLFEM4X(const char *Cmd); - int CmdEM410xDemod(const char *Cmd); int CmdEM410xRead(const char *Cmd); int CmdEM410xSim(const char *Cmd); From 8aa5dec805ac9b0fc9ca95913c80266891d7b38f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:21:14 +0200 Subject: [PATCH 121/141] styles --- client/cmdlfindala.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index b136d9434..257e85894 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -446,9 +446,8 @@ int CmdIndalaDemodAlt(const char *Cmd) { } // Checking UID against next occurrences - int failed = 0; for (; i + uidlen <= rawbit;) { - failed = 0; + int failed = 0; for (bit = 0; bit < uidlen; bit++) { if (bits[bit] != rawbits[i++]) { failed = 1; @@ -468,14 +467,13 @@ int CmdIndalaDemodAlt(const char *Cmd) { // since this changes graphbuffer data. GraphTraceLen = 32 * uidlen; i = 0; - int phase = 0; + int phase; for (bit = 0; bit < uidlen; bit++) { if (bits[bit] == 0) { phase = 0; } else { phase = 1; } - int j; for (j = 0; j < 32; j++) { GraphBuffer[i++] = phase; phase = !phase; From f1a01dcc7bc161a74ba661d061555282a46ea34f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:22:24 +0200 Subject: [PATCH 122/141] fix --- client/cmdlfem4x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index f68bf04b4..98b8f4c71 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -255,7 +255,7 @@ void printEM410x(uint32_t hi, uint64_t id) { PrintAndLogEx(SUCCESS, "EM410x %s pattern found", (hi) ? "XL" : ""); uint64_t id2lo = 0; - uint8_t m =, i = 0; + uint8_t m, i = 0; for (m = 5; m > 0; m--) { for (i = 0; i < 8; i++) { id2lo = (id2lo << 1LL) | ((id & (mi << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); From 514611e88543c6d09eb8aaf29d6db641f40b5033 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:24:13 +0200 Subject: [PATCH 123/141] fix --- client/cmdlfem4x.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 98b8f4c71..e9998269d 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -254,11 +254,12 @@ void printEM410x(uint32_t hi, uint64_t id) { PrintAndLogEx(SUCCESS, "EM410x %s pattern found", (hi) ? "XL" : ""); + uint64_t n = 1; uint64_t id2lo = 0; uint8_t m, i = 0; for (m = 5; m > 0; m--) { for (i = 0; i < 8; i++) { - id2lo = (id2lo << 1LL) | ((id & (mi << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); + id2lo = (id2lo << 1LL) | ((id & (n << (i + ((m - 1) * 8)))) >> (i + ((m - 1) * 8))); } } From f6a80e0dc8b5e9fc1a4ede81d7d98d7e6ef35d6e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 7 Apr 2019 20:34:42 +0200 Subject: [PATCH 124/141] funcArgNamesDifferent --- client/jansson/jansson.h | 4 ++-- client/jansson/jansson_private.h | 3 +-- client/jansson/utf.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/client/jansson/jansson.h b/client/jansson/jansson.h index e282674f3..6f42d68c1 100644 --- a/client/jansson/jansson.h +++ b/client/jansson/jansson.h @@ -320,12 +320,12 @@ int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, j typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); -json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_loads(const char *string, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); -json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); /* encoding */ diff --git a/client/jansson/jansson_private.h b/client/jansson/jansson_private.h index 5957f70b2..094d79e75 100644 --- a/client/jansson/jansson_private.h +++ b/client/jansson/jansson_private.h @@ -84,12 +84,11 @@ void jsonp_error_vset(json_error_t *error, int line, int column, /* Locale independent string<->double conversions */ int jsonp_strtod(strbuffer_t *strbuffer, double *out); -int jsonp_dtostr(char *buffer, size_t size, double value, int prec); +int jsonp_dtostr(char *buffer, size_t size, double value, int precision); /* Wrappers for custom memory functions */ void *jsonp_malloc(size_t size) JANSSON_ATTRS(warn_unused_result); void jsonp_free(void *ptr); -char *jsonp_strndup(const char *str, size_t length) JANSSON_ATTRS(warn_unused_result); char *jsonp_strdup(const char *str) JANSSON_ATTRS(warn_unused_result); char *jsonp_strndup(const char *str, size_t len) JANSSON_ATTRS(warn_unused_result); diff --git a/client/jansson/utf.h b/client/jansson/utf.h index e182df78f..0ca69253e 100644 --- a/client/jansson/utf.h +++ b/client/jansson/utf.h @@ -20,7 +20,7 @@ int utf8_encode(int32_t codepoint, char *buffer, size_t *size); size_t utf8_check_first(char byte); size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint); -const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint); +const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint); int utf8_check_string(const char *string, size_t length); From e3a82cd8491ed4e426eb36237b0ab5bd051934b4 Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+5w0rdfish@users.noreply.github.com> Date: Sun, 7 Apr 2019 23:38:00 +0100 Subject: [PATCH 125/141] Restructure of RRG repo Added installtion videos. Re-wrote installtion instructions --- .../Arch-Linux-Installation-Instructions.md | 60 ++++ .../Coverity-Scan-Config-&-Run.md | 24 ++ ...OS-X-Homebrew-Installation-Instructions.md | 29 ++ .../Parrot-OS-Proxmark3-RDV4-installation.md | 98 +++++ .../Ubuntu-Installation-Instructions.md | 102 ++++++ .../Windows-Installation-Instructions.md | 83 +++++ README.md | 334 ++---------------- Use_of_Proxmark/1_Validation.md | 57 +++ .../2_Configuration-and-Verification.md | 38 ++ Use_of_Proxmark/3_Commands-and-Features.md | 21 ++ prox.png | Bin 0 -> 234632 bytes 11 files changed, 551 insertions(+), 295 deletions(-) create mode 100644 Installation_Instructions/Arch-Linux-Installation-Instructions.md create mode 100644 Installation_Instructions/Coverity-Scan-Config-&-Run.md create mode 100644 Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md create mode 100644 Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md create mode 100644 Installation_Instructions/Ubuntu-Installation-Instructions.md create mode 100644 Installation_Instructions/Windows-Installation-Instructions.md create mode 100644 Use_of_Proxmark/1_Validation.md create mode 100644 Use_of_Proxmark/2_Configuration-and-Verification.md create mode 100644 Use_of_Proxmark/3_Commands-and-Features.md create mode 100644 prox.png diff --git a/Installation_Instructions/Arch-Linux-Installation-Instructions.md b/Installation_Instructions/Arch-Linux-Installation-Instructions.md new file mode 100644 index 000000000..28245dbfa --- /dev/null +++ b/Installation_Instructions/Arch-Linux-Installation-Instructions.md @@ -0,0 +1,60 @@ +# Setup and build for ArchLinux + +## Notes + +Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. +`sudo apt remove modemmanager` + +## Manual Installation +Run +```sh +sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed +``` +```sh +yaourt -S termcap +``` + +```sh +sudo apt remove modemmanager +``` +or +```sh +systemctl stop ModemManager +systemctl disable ModemManager +``` + +Clone fork +```sh +git clone https://github.com/RfidResearchGroup/proxmark3.git +``` + +Get the latest commits +```sh +git pull +``` + +Install the blacklist rules and add user to dialout group (if you on a Linux/ubuntu/debian). +If you do this one, you need to logout and login in again to make sure your rights got changed. +```sh +make udev +``` + +Clean and complete compilation +```sh +make clean && make all +``` + +Flash the BOOTROM & FULLIMAGE +```sh +client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +``` + +Change into the client folder +```sh +cd client +``` + +Run the client +```sh +./proxmark3 /dev/ttyACM0 +``` diff --git a/Installation_Instructions/Coverity-Scan-Config-&-Run.md b/Installation_Instructions/Coverity-Scan-Config-&-Run.md new file mode 100644 index 000000000..9979c41e1 --- /dev/null +++ b/Installation_Instructions/Coverity-Scan-Config-&-Run.md @@ -0,0 +1,24 @@ + +## Coverity Scan Config & Run +Download the Coverity Scan Self-buld and install it. +You will need to configure ARM-NON-EABI- Compiler for it to use: + + Configure + +```sh +cov-configure --comptype gcc --compiler /opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc +``` + +Run it (I'm running on Ubuntu) + +```sh +cov-build --dir cov-int make all +``` + +Make a tarball + +```sh +tar czvf proxmark3.tgz cov-int +``` + +Upload it to coverity.com diff --git a/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md b/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md new file mode 100644 index 000000000..61ab754d5 --- /dev/null +++ b/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md @@ -0,0 +1,29 @@ +## Homebrew (Mac OS X) +These instructions comes from @Chrisfu, where I got the proxmark3.rb scriptfile from. +Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/chrisfu/) + +1. Install homebrew if you haven't yet already done so: http://brew.sh/ + +2. Tap this repo: `brew tap RfidResearchGroup/proxmark3` + +3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub. + +Upgrading HomeBrew tap formula +----------------------------- +*This method is useful for those looking to run bleeding-edge versions of iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.* + +Tested on macOS High Sierra 10.13.2 + +*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above* + +1. Force HomeBrew to pull the latest source from github +`brew upgrade --fetch-HEAD RfidResearchGroup/proxmark3` + +2. Flash the bootloader & fullimage.elf + * With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. Continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"* + `$ sudo proxmark3-flasher /dev/tty.usbmodem881 -b /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/bootrom.elf /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/fullimage.elf` + + +`$ sudo proxmark3-flasher /dev/tty.usbmodem881 ` + +4. Enjoy the update diff --git a/Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md b/Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md new file mode 100644 index 000000000..7b6187e1a --- /dev/null +++ b/Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md @@ -0,0 +1,98 @@ + +# Parrot OS Installation + +## Notes + +Some further notes can be found at @5w0rdfish repo [Proxmark Installation for Parrot OS](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS) + +# Video Installation guide +[![ParrotOS Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/Wl9AsrU4igo "ParrotOS Installation Tutorial") + + +--- +## Manual Install +First what we want to do is get an update for the system. If you need to upgrade do this **before** the install + +### Update +```sh +sudo apt-get update +``` +### Requirements. + +```sh +sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev \ +libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi +``` +If you do get any issues during the requirements installation, I have found it to help using the synaptic package manager. + +### Clone Fork +```sh +git clone https://github.com/RfidResearchGroup/proxmark3.git +``` + +### Change directory into the directory created +```sh +cd proxmark3 +``` + +### Get the latest commits +```sh +git pull +``` + +### Make Udev +Iceman has made the udev script which takes care of the blacklist rules. This should take care of the remove modem manager. +The make udev command also create's an alias for the pm3 under /dev which you will use to connect to the proxmark. + +```sh +sudo make udev +``` + +> **Note** If you have any issues connecting or during the flash, follow the steps listed [here](https://github.com/RfidResearchGroup/proxmark3/issues/35) and use the command sudo apt remove modemmanager + +Log out and log back in again. And now we are all set to take the next step. + +### Clean and Compile +Clean and complete compilation *within the proxmark3 folder* + +```sh + make clean && make all +``` +### Check Connection +Once this is complete run the following comands to make sure the proxmark is being picked up by your computer. + +```sh +sudo dmesg | grep -i usb +``` +It should show up as a CDC device: +```sh +[10416.555108] usb 2-1.2: Product: PM3 +[10416.555111] usb 2-1.2: Manufacturer: proxmark.org +[10416.555871] cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device +``` + +### Flash the BOOTROM & FULLIMAGE + ```sh + client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +``` +### Change into the client folder + +```sh +cd client +``` +### Run the client + ``` sh +./proxmark3 /dev/pm #press tab on the keyboard for it to detect the proxmark +``` +or + +### Run the client + ```sh +./proxmark3 /dev/ttyACM0 +``` + +### Run a test command + ```sh +hw tune +``` + diff --git a/Installation_Instructions/Ubuntu-Installation-Instructions.md b/Installation_Instructions/Ubuntu-Installation-Instructions.md new file mode 100644 index 000000000..6df3b704e --- /dev/null +++ b/Installation_Instructions/Ubuntu-Installation-Instructions.md @@ -0,0 +1,102 @@ +# Setup and build for UBUNTU +## Notes +GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 +See the [Proxmark3 Ubuntu wiki page](https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux) + +A nice and cool install script made by @daveio is found here: +https://github.com/daveio/attacksurface/blob/master/proxmark3/pm3-setup.sh + +Iceman has also added this script to the fork. +https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh + +# Video Installation guide +[![ParrotOS Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/DThmkH8CdMo "Ubuntu Installation Tutorial") + +--- +## Manual Installation +### Update + +```sh +sudo apt-get update +``` +### Requirements + +```sh +sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi +``` + +### Clone Fork + +```sh +git clone https://github.com/RfidResearchGroup/proxmark3.git +``` +### Change Directory + +```sh +cd proxmark3 +``` + +### Get the latest commits + +```sh +git pull +``` + +### Install the blacklist rules and add user to dialout group. + +```sh +sudo make udev +``` + +### Restart +Restart Ubuntu + +### Enter proxmark folder +```sh +cd proxmark3 +``` +### Clean and Compile +```sh +make clean && make all +``` +### Check Connection +Once this is complete run the following comands to make sure the proxmark is being picked up by your computer. + +```sh +sudo dmesg | grep -i usb +``` + +### Flash the BOOTROM & FULLIMAGE + ```sh + client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +``` + +### Issues +If you have issues with the install please try the following below or head on over to the proxmark forum. +#### Remove Modem Manager + +```sh +sudo apt remove modemmanager +``` +and then restart ubuntu. + +### Change into the client folder +```sh +cd client +``` + +### Run the client + ``` sh +./proxmark3 /dev/pm #press tab on the keyboard for it to detect the proxmark +``` +or + +### Run the client + ```sh +./proxmark3 /dev/ttyACM0 +``` + +### Run a test command + ```sh +hw tune +``` diff --git a/Installation_Instructions/Windows-Installation-Instructions.md b/Installation_Instructions/Windows-Installation-Instructions.md new file mode 100644 index 000000000..6a20a510f --- /dev/null +++ b/Installation_Instructions/Windows-Installation-Instructions.md @@ -0,0 +1,83 @@ +# Building on Windows +You will need to use the Gator96100 Proxspace package to assist in your windows installation. +This can be downloaded from https://github.com/Gator96100/ProxSpace/ + +## Notes +If you receive gcc errors using v3.1 during build, download and use v2.2. This may help resolve the issue. + +- https://github.com/Gator96100/ProxSpace/releases/tag/v3.1 (release v3.1 with gcc v7.3.0 ) +- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0) + +--- +# Video Installation guide +[![Windows Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/zzF0NCMJnYU "Windows Installation Tutorial") + +## Manual Installation + +### Driver Installation + +Install required drivers for your windows installation. You will may need admin privileges to do this. +(This is covered in the video) Step by step guides are online such as [RiscCorps](https://store.ryscc.com/blogs/news/how-to-install-a-proxmark3-driver-on-windows-10) + +### Install Github + +Install Github for Windows https://desktop.github.com/ + +### Download / clone Proxspace repo + +Download the required proxspace repo. https://github.com/Gator96100/ProxSpace/ + +Extract 'ProxSpace' to a location on drive without spaces. +For example D:\OneDrive\Documents\GitHub is ok whereas C:\My Documents\My Projects\proxspace is not. + +### Clone RFID RESEARCH GROUP files + +Clone fork +```sh +git clone https://github.com/RfidResearchGroup/proxmark3.git +``` +### Copy files to Proxspace + +Copy all the contents from the proxmark3 folder into the proxspace pm3 folder + +### Run the .bat + +Run runme.bat or runme64.bat depending on your Windows architecture. + +Please note you will need to use / as you are using BASH. + +### Make + +CLEAN COMPILE inside the pm3 window. +```sh +make clean && make all +``` +### Flash the image + +Flash the BOOTROM & FULLIMAGE +```sh +client/flasher.exe comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +``` + +### Run the client + +Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark software where "X" is the com port number assigned to proxmark3 under Windows. + +Change into the client folder +```sh +cd client +``` + +Run the client +```sh +./proxmark3.exe comX +``` + +### Test + +Check your firmware revision on the Proxmark III with +```sh +hw ver +``` +For basic help type help. Or for help on a set of sub commands type the command followed by help. For example hf mf help. +Make sure you head over to the use of [proxmark area](https://github.com/5w0rdfish/proxmark3/tree/master/Use_of_Proxmark) to help you get on your way! diff --git a/README.md b/README.md index cfdbacc61..47192cb43 100644 --- a/README.md +++ b/README.md @@ -1,71 +1,33 @@ -Proxmark3 RDV40 dedicated repo, based on iceman fork +Proxmark3 RDV4.0 Dedicated Github =============== +This repo is based on iceman fork for proxmark3. It is dedicated to bringing the most out of the new features for proxmark3 RDV4.0 new hardware and design. + [![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest) -## Notice -This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device. + -# Donations -Nothing says thank you as much as a donation, https://www.patreon.com/iceman1001 +--- -## ToC - -- Coverity Scan Config & Run -- Whats changed? -- Why didn't you based it on offical PM3 Master? -- Why don't you add this or that functionality? -- PM3 GUI -- Development -- KALI and ARCHLINUX users -- Setup and build for UBUNTU -- Setup and build for ArchLinux -- Homebrew (Mac OS X) -- Upgrading HomeBrew tap formula -- Building on Windows -- Gator96100 distro -- Build and run -- Validating proxmark client functionality -- Run the following commands -- Quit client -- First things on your RDV40 -- Verify sim module firmware version - -- The end - -## Coverity Scan Config & Run -Download the Coverity Scan Self-buld and install it. -You will need to configure ARM-NON-EABI- Compiler for it to use: - -- Configure - -`cov-configure --comptype gcc --compiler /opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc` - -- Run it (I'm running on Ubuntu) - -`cov-build --dir cov-int make all` - -- Make a tarball - -`tar czvf proxmark3.tgz cov-int` - -- Upload it to coverity.com +# PROXMARK INSTALLATION AND OVERVIEW +| FAQ's & Updates | Installation | Use of the Proxmark | +| ------------- |:-------------:| -----:| +|[Whats changed?](#whats-changed) | [Setup and build for ArchLinux](/Installation_Instructions/Arch-Linux-Installation-Instructions.md) | [Validating proxmark client functionality](/Use_of_Proxmark/1_Validation.md)| +|[Development](#development) | [Setup and build for UBUNTU](/Installation_Instructions/Ubuntu-Installation-Instructions.md) | [First Use and Verification](/Use_of_Proxmark/2_Configuration-and-Verification.md) | +| [Why don't you add this or that functionality?](#why-dont-you-add-this-or-that-functionality) | [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Forumula](/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [Commands & Features](/Use_of_Proxmark/3_Commands-and-Features.md)| +|[Why didn't you based it on offical PM3 Master?](#why-didnt-you-based-it-on-offical-pm3-master) |[ParrotOS Installation ](/Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md)|[PM3 GUI](#pm3-gui) +|[Notices](#notices)|[Setup and build for Windows](/Installation_Instructions/Windows-Installation-Instructions.md)|| +|[Issues](#issues)|[Coverity Scan Config & Run](/Installation_Instructions/Coverity-Scan-Config-%26-Run.md)|| +||| + +--- ## Whats changed? * added flash memory 256kb. * added smart card module * added FPC connector - ---- -## Why didn't you based it on offical PM3 Master? -The separation from offical pm3 repo gives us very much freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the offical pm3 repo with RDV40 specific code. - -## Why don't you add this or that functionality? -Give us a hint, and we'll see if we can't merge in the stuff you have. - -## PM3 GUI -The official PM3-GUI from Gaucho will not work. -The new universial GUI will work. [Proxmark3 Univerisal GUI](https://github.com/burma69/PM3UniversalGUI) ## Development This fork now compiles just fine on @@ -75,248 +37,30 @@ This fork now compiles just fine on - ParrotOS - WSL (Windows subsystem linux) on Windows 10 - Docker container +--- +## Why didn't you based it on offical PM3 Master? +The separation from offical pm3 repo gives us very much freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the offical pm3 repo with RDV40 specific code. -## KALI and ARCHLINUX users +## Why don't you add this or that functionality? +Give us a hint, and we'll see if we can't merge in the stuff you have. + +## PM3 GUI +The official PM3-GUI from Gaucho will not work. +The new universial GUI will work. [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) + +## Notices Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. -```sh -sudo apt remove modemmanager -``` -or -```sh -systemctl stop ModemManager -systemctl disable ModemManager -``` - -## Setup and build for UBUNTU -GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 -See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux - -A nice and cool install script made by @daveio is found here: -https://github.com/daveio/attacksurface/blob/master/proxmark3/pm3-setup.sh -I have also added this script to the fork. -https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh - -- Run -`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi` - -- Clone fork -`git clone https://github.com/RfidResearchGroup/proxmark3.git` - -- Get the latest commits -`git pull` - -- Install the blacklist rules and add user to dialout group (if you on a Linux/ubuntu/debian). If you do this one, you need to logout and login in again to make sure your rights got changed. -`make udev` - -- Clean and complete compilation -`make clean && make all` - -- Flash the BOOTROM & FULLIMAGE -`client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf` - -- Change into the client folder -`cd client` - -- Run the client -`./proxmark3 /dev/ttyACM0` - -## Setup and build for ArchLinux -- Run -`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed` -`yaourt -S termcap` - -- Remove modemmanager `sudo apt remove modemmanager` + +## Issues +Please see the [Proxmark Forum](http://www.proxmark.org/forum/index.php) and see if your issue is listed in the first instance google is your friend :) Questions will be answered via the forum by Iceman and the team. -- Clone fork -`git clone https://github.com/RfidResearchGroup/proxmark3.git` +## The end -- Get the latest commits -`git pull` +[@herrmann1001](https://mobile.twitter.com/herrmann1001) at host iuse.se +July 2018, Sweden +updated Feb 2019 [@5w0rdfish](https://mobile.twitter.com/5w0rdFish) -- Install the blacklist rules and add user to dialout group (if you on a Linux/ubuntu/debian). If you do this one, you need to logout and login in again to make sure your rights got changed. -`make udev` +# Donations +Nothing says thank you as much as a donation, https://www.patreon.com/iceman1001 -- Clean and complete compilation -`make clean && make all` - -- Flash the BOOTROM & FULLIMAGE -`client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf` - -- Change into the client folder -`cd client` - -- Run the client -`./proxmark3 /dev/ttyACM0` - -## Homebrew (Mac OS X) -These instructions comes from @Chrisfu, where I got the proxmark3.rb scriptfile from. -Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/chrisfu/) - -1. Install homebrew if you haven't yet already done so: http://brew.sh/ - -2. Tap this repo: `brew tap RfidResearchGroup/proxmark3` - -3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub. - -Upgrading HomeBrew tap formula ------------------------------ -*This method is useful for those looking to run bleeding-edge versions of iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.* - -Tested on macOS High Sierra 10.13.2 - -*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above* - -1. Force HomeBrew to pull the latest source from github -`brew upgrade --fetch-HEAD RfidResearchGroup/proxmark3` - -2. Flash the bootloader & fullimage.elf - * With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. Continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"* - `$ sudo proxmark3-flasher /dev/tty.usbmodem881 -b /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/bootrom.elf /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/fullimage.elf` - - -`$ sudo proxmark3-flasher /dev/tty.usbmodem881 ` - -4. Enjoy the update - - -## Building on Windows - -### Gator96100 distro -Rather than download and install every one of these packages, a new ProxSpace -environment archive file will be made available for download on the project -page at @Gator96100's repo - -Afterwards just clone the iceman repo or download someone elses. -Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/) - -Links -- https://github.com/Gator96100/ProxSpace/releases/tag/v3.1 (release v3.1 with gcc v7.3.0 ) -- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0) - - -### Build and run - -- Clone fork -`git clone https://github.com/RfidResearchGroup/proxmark3.git` - -- Get the latest commits -`git pull` - -- CLEAN COMPILE -`make clean && make all` - -Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark software where "X" is the com port number assigned to proxmark3 under Windows. - -- Flash the BOOTROM & FULLIMAGE -`client/flasher.exe comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf` - -- Change into the client folder -`cd client` - -- Run the client -`proxmark3.exe comX` - - -## Validating proxmark client functionality - -If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this. - ->[=] UART Setting serial baudrate 460800 -> ->Proxmark3 RFID instrument -> -> [ CLIENT ] -> -> client: iceman build for RDV40 with flashmem; smartcard; -> -> [ ARM ] -> -> bootrom: iceman/master/4517531c-dirty-unclean 2018-12-13 15:42:24 -> -> os: iceman/master/5a34550a-dirty-unclean 2019-01-07 23:04:07 -> -> [ FPGA ] -> -> LF image built for 2s30vq100 on 2018/ 9/ 8 at 13:57:51 -> -> HF image built for 2s30vq100 on 2018/ 9/ 3 at 21:40:23 -> -> [ Hardware ] -> ->--= uC: AT91SAM7S512 Rev B -> ->--= Embedded Processor: ARM7TDMI -> ->--= Nonvolatile Program Memory Size: 512K bytes, Used: 247065 bytes (47%) Free: 277223 bytes (53%) -> ->--= Second Nonvolatile Program Memory Size: None -> ->--= Internal SRAM Size: 64K bytes -> ->--= Architecture Identifier: AT91SAM7Sxx Series -> ->--= Nonvolatile Program Memory Type: Embedded Flash Memory -> -> pm3 --> - -### Run the following commands - pm3 --> hw status - pm3 --> hw version - pm3 --> hw tune - -You are now ready to use your newly upgraded proxmark3 device. Many commands uses the **h** parameter to show a help text. The client uses a arcaic command structure which will be hard to grasp at first. Here are some commands to start off with. - - pm3 --> hf - pm3 --> hf 14a info - pm3 --> lf - pm3 --> lf search - -### Quit client - pm3 --> quit - - -### First things on your RDV40 -You will need to run these commands to make sure your rdv4 is prepared - - pm3 --> mem load f default_keys m - pm3 --> mem load f default_pwd t - pm3 --> mem load f default_iclass_keys i - pm3 --> lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 p - -### Verify sim module firmware version -To make sure you got the latest sim module firmware. -_Lastest version is v3.11_ - - pm3 --> hw status - -Find version in the long output, look for these two lines - - #db# Smart card module (ISO 7816) - #db# version.................v2.06 - -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 - -You get the following output, this is a successful execution. - - [!] WARNING - Smartcard socket firmware upgrade. - [!] A dangerous command, do wrong and you will brick the smart card socket - [+] Smartcard socket firmware uploading to PM3 - .. - [+] Smartcard socket firmware updating, don't turn off your PM3! - #db# FW 0000 - #db# FW 0080 - #db# FW 0100 - #db# FW 0180 - #db# FW 0200 - #db# FW 0280 - [+] Smartcard socket firmware upgraded successful - - -## the end - -`iceman at host iuse.se` -`July 2018, Sweden` diff --git a/Use_of_Proxmark/1_Validation.md b/Use_of_Proxmark/1_Validation.md new file mode 100644 index 000000000..334150fe8 --- /dev/null +++ b/Use_of_Proxmark/1_Validation.md @@ -0,0 +1,57 @@ +## 1. Validating proxmark client functionality + +If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this. +We should be able to answer ..can I connect to my proxmark device? does it respond? + +>[=] UART Setting serial baudrate 460800 +> +>Proxmark3 RFID instrument +> +> [ CLIENT ] +> +> client: iceman build for RDV40 with flashmem; smartcard; +> +> [ ARM ] +> +> bootrom: iceman/master/4517531c-dirty-unclean 2018-12-13 15:42:24 +> +> os: iceman/master/5a34550a-dirty-unclean 2019-01-07 23:04:07 +> +> [ FPGA ] +> +> LF image built for 2s30vq100 on 2018/ 9/ 8 at 13:57:51 +> +> HF image built for 2s30vq100 on 2018/ 9/ 3 at 21:40:23 +> +> [ Hardware ] +> +>--= uC: AT91SAM7S512 Rev B +> +>--= Embedded Processor: ARM7TDMI +> +>--= Nonvolatile Program Memory Size: 512K bytes, Used: 247065 bytes (47%) Free: 277223 bytes (53%) +> +>--= Second Nonvolatile Program Memory Size: None +> +>--= Internal SRAM Size: 64K bytes +> +>--= Architecture Identifier: AT91SAM7Sxx Series +> +>--= Nonvolatile Program Memory Type: Embedded Flash Memory +> +> pm3 --> + +### Run the following commands + pm3 --> hw status + pm3 --> hw version + pm3 --> hw tune + +You are now ready to use your newly upgraded proxmark3 device. Many commands uses the **h** parameter to show a help text. The client uses a arcaic command structure which will be hard to grasp at first. Here are some commands to start off with. + + pm3 --> hf + pm3 --> hf 14a info + pm3 --> lf + pm3 --> lf search + +### Quit client + pm3 --> quit diff --git a/Use_of_Proxmark/2_Configuration-and-Verification.md b/Use_of_Proxmark/2_Configuration-and-Verification.md new file mode 100644 index 000000000..e226652c6 --- /dev/null +++ b/Use_of_Proxmark/2_Configuration-and-Verification.md @@ -0,0 +1,38 @@ +### First things on your RDV40 +You will need to run these commands to make sure your rdv4 is prepared + + pm3 --> mem load f default_keys m + pm3 --> mem load f default_pwd t + pm3 --> mem load f default_iclass_keys i + pm3 --> lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 p + +### Verify sim module firmware version +To make sure you got the latest sim module firmware. +_Lastest version is v3.11_ + + pm3 --> hw status + +Find version in the long output, look for these two lines + + #db# Smart card module (ISO 7816) + #db# version.................v2.06 + +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 + +You get the following output, this is a successful execution. + + [!] WARNING - Smartcard socket firmware upgrade. + [!] A dangerous command, do wrong and you will brick the smart card socket + [+] Smartcard socket firmware uploading to PM3 + .. + [+] Smartcard socket firmware updating, don't turn off your PM3! + #db# FW 0000 + #db# FW 0080 + #db# FW 0100 + #db# FW 0180 + #db# FW 0200 + #db# FW 0280 + [+] Smartcard socket firmware upgraded successful diff --git a/Use_of_Proxmark/3_Commands-and-Features.md b/Use_of_Proxmark/3_Commands-and-Features.md new file mode 100644 index 000000000..ecc9aae0f --- /dev/null +++ b/Use_of_Proxmark/3_Commands-and-Features.md @@ -0,0 +1,21 @@ + +# Commands and Features + +## New Features in RDV4 + +Further details coming soon + +### Run the following commands + pm3 --> hw status + pm3 --> hw version + pm3 --> hw tune + +You are now ready to use your newly upgraded proxmark3 device. Many commands uses the **h** parameter to show a help text. The client uses a arcaic command structure which will be hard to grasp at first. Here are some commands to start off with. + + pm3 --> hf + pm3 --> hf 14a info + pm3 --> lf + pm3 --> lf search + +### Quit client + pm3 --> quit diff --git a/prox.png b/prox.png new file mode 100644 index 0000000000000000000000000000000000000000..1fce7e315c7200139777e7a26bc322fb9d082ebc GIT binary patch literal 234632 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�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 literal 0 HcmV?d00001 From fd2b0d98becd39e644bdb51130901343a003b7d1 Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+Chrissy-Morgan@users.noreply.github.com> Date: Mon, 8 Apr 2019 00:05:12 +0100 Subject: [PATCH 126/141] Create Kali-Installation-Instructions.md Created Kali page --- .../Kali-Installation-Instructions.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 Installation_Instructions/Kali-Installation-Instructions.md diff --git a/Installation_Instructions/Kali-Installation-Instructions.md b/Installation_Instructions/Kali-Installation-Instructions.md new file mode 100644 index 000000000..cd1b6c959 --- /dev/null +++ b/Installation_Instructions/Kali-Installation-Instructions.md @@ -0,0 +1,105 @@ +# Kali Installation +Kali users usually must kill their modem manager in order for the proxmark3 to enumerate properly. +''' sudo apt remove modemmanager ''' + +# Video Installation guide +[![Kali Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/Wl9AsrU4igo "ParrotOS Installation Tutorial") + + +--- +## Manual Install +First what we want to do is get an update for the system. If you need to upgrade do this **before** the install +An upgrade was carried out prior to following these instructions. + +### Update +```sh +sudo apt-get update +``` +### Requirements. + +```sh +sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev \ +libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi +``` +If you do get any issues during the requirements installation, I have found it to help using the synaptic package manager. + +### Clone Fork +```sh +git clone https://github.com/RfidResearchGroup/proxmark3.git +``` + +### Change directory into the directory created +```sh +cd proxmark3 +``` + +### Get the latest commits +```sh +git pull +``` + +### Make Udev +Iceman has made the udev script which takes care of the blacklist rules. This should take care of the remove modem manager. +The make udev command also create's an alias for the pm3 under /dev which you will use to connect to the proxmark. + +```sh +sudo make udev +``` +if you have any issues: +```sh +sudo apt remove modemmanager +``` + +> **Note** If you have any issues connecting or during the flash, follow the steps listed [here](https://github.com/RfidResearchGroup/proxmark3/issues/35) and use the command sudo apt remove modemmanager + +Log out and log back in again. And now we are all set to take the next step. + +Enter the proxmark3 folder +```sh +cd proxmark3 +``` + +### Clean and Compile +Clean and complete compilation + +```sh + make clean && make all +``` +### Check Connection +Once this is complete run the following comands to make sure the proxmark is being picked up by your computer. + +```sh +sudo dmesg | grep -i usb +``` +It should show up as a CDC device: +```sh +[10416.555108] usb 2-1.2: Product: PM3 +[10416.555111] usb 2-1.2: Manufacturer: proxmark.org +[10416.555871] cdc_acm 2-1.2:1.0: ttyACM0: USB ACM device +``` + +### Flash the BOOTROM & FULLIMAGE + ```sh + client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf +``` +### Change into the client folder + +```sh +cd client +``` +### Run the client + ``` sh +./proxmark3 /dev/pm #press tab on the keyboard for it to detect the proxmark +``` +or + +### Run the client + ```sh +./proxmark3 /dev/ttyACM0 +``` + +### Run a test command + ```sh +hw tune +``` + From 69bcec5208e23d3453dcb7b23ac0363f84baaebf Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+Chrissy-Morgan@users.noreply.github.com> Date: Mon, 8 Apr 2019 00:09:26 +0100 Subject: [PATCH 127/141] Added Kali page link links to Kali instructions --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 47192cb43..67e31b794 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ alt="Yuotube" width="100%" height="auto" border="10" /> |[Why didn't you based it on offical PM3 Master?](#why-didnt-you-based-it-on-offical-pm3-master) |[ParrotOS Installation ](/Installation_Instructions/Parrot-OS-Proxmark3-RDV4-installation.md)|[PM3 GUI](#pm3-gui) |[Notices](#notices)|[Setup and build for Windows](/Installation_Instructions/Windows-Installation-Instructions.md)|| |[Issues](#issues)|[Coverity Scan Config & Run](/Installation_Instructions/Coverity-Scan-Config-%26-Run.md)|| -||| +||[Kali Linux Installation Instructions](/Installation_Instructions/Kali-Installation-Instructions.md)| --- ## Whats changed? From 32de4f8f6fc8fa4bb7991b0a7bd4905e2b16d7de Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+Chrissy-Morgan@users.noreply.github.com> Date: Mon, 8 Apr 2019 00:43:02 +0100 Subject: [PATCH 128/141] Update Kali-Installation-Instructions.md --- .../Kali-Installation-Instructions.md | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/Installation_Instructions/Kali-Installation-Instructions.md b/Installation_Instructions/Kali-Installation-Instructions.md index cd1b6c959..a6b6caf35 100644 --- a/Installation_Instructions/Kali-Installation-Instructions.md +++ b/Installation_Instructions/Kali-Installation-Instructions.md @@ -1,6 +1,6 @@ # Kali Installation Kali users usually must kill their modem manager in order for the proxmark3 to enumerate properly. -''' sudo apt remove modemmanager ''' +```sh sudo apt remove modemmanager``` # Video Installation guide [![Kali Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/Wl9AsrU4igo "ParrotOS Installation Tutorial") @@ -38,14 +38,7 @@ cd proxmark3 git pull ``` -### Make Udev -Iceman has made the udev script which takes care of the blacklist rules. This should take care of the remove modem manager. -The make udev command also create's an alias for the pm3 under /dev which you will use to connect to the proxmark. - -```sh -sudo make udev -``` -if you have any issues: +### Remove Modem Manager ```sh sudo apt remove modemmanager ``` From ef0e53f54b80073a8ff21e7b196d3038f2eae9e0 Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+Chrissy-Morgan@users.noreply.github.com> Date: Mon, 8 Apr 2019 00:53:38 +0100 Subject: [PATCH 129/141] Update Kali-Installation-Instructions.md --- .../Kali-Installation-Instructions.md | 21 ++++++------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/Installation_Instructions/Kali-Installation-Instructions.md b/Installation_Instructions/Kali-Installation-Instructions.md index a6b6caf35..58d783e5b 100644 --- a/Installation_Instructions/Kali-Installation-Instructions.md +++ b/Installation_Instructions/Kali-Installation-Instructions.md @@ -1,6 +1,8 @@ # Kali Installation Kali users usually must kill their modem manager in order for the proxmark3 to enumerate properly. -```sh sudo apt remove modemmanager``` +```sh +sudo apt remove modemmanager +``` # Video Installation guide [![Kali Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/Wl9AsrU4igo "ParrotOS Installation Tutorial") @@ -43,15 +45,6 @@ git pull sudo apt remove modemmanager ``` -> **Note** If you have any issues connecting or during the flash, follow the steps listed [here](https://github.com/RfidResearchGroup/proxmark3/issues/35) and use the command sudo apt remove modemmanager - -Log out and log back in again. And now we are all set to take the next step. - -Enter the proxmark3 folder -```sh -cd proxmark3 -``` - ### Clean and Compile Clean and complete compilation @@ -75,16 +68,14 @@ It should show up as a CDC device: ```sh client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf ``` +> **Note** If you have any issues connecting or during the flash, follow the steps listed [here](https://github.com/RfidResearchGroup/proxmark3/issues/35) and use the command sudo apt remove modemmanager + + ### Change into the client folder ```sh cd client ``` -### Run the client - ``` sh -./proxmark3 /dev/pm #press tab on the keyboard for it to detect the proxmark -``` -or ### Run the client ```sh From ef52cfef9f2f8dab64d9ee4155e9fb7b8da408c9 Mon Sep 17 00:00:00 2001 From: Chrissy Morgan <43700993+Chrissy-Morgan@users.noreply.github.com> Date: Mon, 8 Apr 2019 01:42:29 +0100 Subject: [PATCH 130/141] Added video link - instruction changes Installation steps amended and added kali linux video --- .../Kali-Installation-Instructions.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Installation_Instructions/Kali-Installation-Instructions.md b/Installation_Instructions/Kali-Installation-Instructions.md index 58d783e5b..4d65afead 100644 --- a/Installation_Instructions/Kali-Installation-Instructions.md +++ b/Installation_Instructions/Kali-Installation-Instructions.md @@ -5,7 +5,7 @@ sudo apt remove modemmanager ``` # Video Installation guide -[![Kali Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/Wl9AsrU4igo "ParrotOS Installation Tutorial") +[![Kali Installation tutorial](https://github.com/5w0rdfish/Proxmark3-RDV4-ParrotOS/blob/master/screenshot-www.youtube.com-2019.03.17-20-44-33.png)](https://youtu.be/t5eBPS6lV3E "Kali Linux Installation Tutorial") --- @@ -44,9 +44,18 @@ git pull ```sh sudo apt remove modemmanager ``` +### Reboot Kali +```sh + reboot +``` + +### Change directory back to proxmark3 +```sh +cd proxmark3 +``` ### Clean and Compile -Clean and complete compilation +Clean and complete compile ```sh make clean && make all From a89ae9cb35ded340cfdc777fde225439b3819383 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:08:47 +0200 Subject: [PATCH 131/141] check return value from zlib inflateInit2... --- armsrc/fpgaloader.c | 6 ++++-- armsrc/start.c | 4 +++- client/fpga_compress.c | 4 +++- 3 files changed, 10 insertions(+), 4 deletions(-) diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 0b94bba45..63957067f 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -229,8 +229,10 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s compressed_fpga_stream->zalloc = &fpga_inflate_malloc; compressed_fpga_stream->zfree = &fpga_inflate_free; - inflateInit2(compressed_fpga_stream, 0); - + int res = inflateInit2(compressed_fpga_stream, 0); + if ( res < 0 ) + return false; + fpga_image_ptr = output_buffer; for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) diff --git a/armsrc/start.c b/armsrc/start.c index b5947bdf3..0b48fc601 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -48,7 +48,9 @@ static void uncompress_data_section(void) { data_section.opaque = NULL; // initialize zlib for inflate - inflateInit2(&data_section, 15); + int res = inflateInit2(&data_section, 15); + if ( res < 0 ) + return; // uncompress data segment to RAM inflate(&data_section, Z_FINISH); diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 00e62d74b..cba92a99e 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -206,7 +206,9 @@ int zlib_decompress(FILE *infile, FILE *outfile) { compressed_fpga_stream.opaque = Z_NULL; ret = inflateInit2(&compressed_fpga_stream, 0); - + if ( res < 0 ) + return (EXIT_FAILURE); + do { if (compressed_fpga_stream.avail_in == 0) { compressed_fpga_stream.next_in = inbuf; From 8d2c02878b19514d5dde3fa5388ef2a6fbdc13f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:11:18 +0200 Subject: [PATCH 132/141] simpler branching --- client/cmdlfpyramid.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index e3f2a90b5..0be39300f 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -224,16 +224,15 @@ int CmdPyramidDemod(const char *Cmd) { fc = bytebits_to_byte(bits + 53, 10); cardnum = bytebits_to_byte(bits + 63, 32); PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d, FC: %d, Card: %d - Raw: %08x%08x%08x%08x", fmtLen, fc, cardnum, rawHi3, rawHi2, rawHi, rawLo); + } else if (fmtLen > 32) { + cardnum = bytebits_to_byte(bits + 81, 16); + //code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen-32); + //code2 = bytebits_to_byte(bits+(size-32),32); + PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); } else { cardnum = bytebits_to_byte(bits + 81, 16); - if (fmtLen > 32) { - //code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen-32); - //code2 = bytebits_to_byte(bits+(size-32),32); - PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); - } else { - //code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen); - PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); - } + //code1 = bytebits_to_byte(bits+(size-fmtLen),fmtLen); + PrintAndLogEx(SUCCESS, "Pyramid ID Found - BitLength: %d -unknown BitLength- (%d), Raw: %08x%08x%08x%08x", fmtLen, cardnum, rawHi3, rawHi2, rawHi, rawLo); } PrintAndLogEx(DEBUG, "DEBUG: Pyramid: checksum : 0x%02X - %02X - %s" From 9328a8efbb9475c87b2cd7dec522b7bb3499da4b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:15:28 +0200 Subject: [PATCH 133/141] fix --- client/fpga_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/fpga_compress.c b/client/fpga_compress.c index cba92a99e..4b0350c06 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -206,7 +206,7 @@ int zlib_decompress(FILE *infile, FILE *outfile) { compressed_fpga_stream.opaque = Z_NULL; ret = inflateInit2(&compressed_fpga_stream, 0); - if ( res < 0 ) + if ( ret < 0 ) return (EXIT_FAILURE); do { From 075ccebfd514c62398cacc08c5cff6e644d1d24b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:23:11 +0200 Subject: [PATCH 134/141] unshadow --- client/tinycbor/cborinternal_p.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/tinycbor/cborinternal_p.h b/client/tinycbor/cborinternal_p.h index 65c42cdf4..2464ddeea 100644 --- a/client/tinycbor/cborinternal_p.h +++ b/client/tinycbor/cborinternal_p.h @@ -49,43 +49,43 @@ static inline double decode_half(unsigned short half) { /* software implementation of float-to-fp16 conversions */ static inline unsigned short encode_half(double val) { uint64_t v; - int sign, exp, mant; + int sign, exp1, mant; memcpy(&v, &val, sizeof(v)); sign = v >> 63 << 15; - exp = (v >> 52) & 0x7ff; + exp1 = (v >> 52) & 0x7ff; mant = v << 12 >> 12 >> (53 - 11); /* keep only the 11 most significant bits of the mantissa */ - exp -= 1023; - if (exp == 1024) { + exp1 -= 1023; + if (exp1 == 1024) { /* infinity or NaN */ - exp = 16; + exp1 = 16; mant >>= 1; - } else if (exp >= 16) { + } else if (exp1 >= 16) { /* overflow, as largest number */ - exp = 15; + exp1 = 15; mant = 1023; - } else if (exp >= -14) { + } else if (exp1 >= -14) { /* regular normal */ - } else if (exp >= -24) { + } else if (exp1 >= -24) { /* subnormal */ mant |= 1024; - mant >>= -(exp + 14); - exp = -15; + mant >>= -(exp1 + 14); + exp1 = -15; } else { /* underflow, make zero */ return 0; } /* safe cast here as bit operations above guarantee not to overflow */ - return (unsigned short)(sign | ((exp + 15) << 10) | mant); + return (unsigned short)(sign | ((exp1 + 15) << 10) | mant); } /* this function was copied & adapted from RFC 7049 Appendix D */ static inline double decode_half(unsigned short half) { - int exp = (half >> 10) & 0x1f; + int exp1 = (half >> 10) & 0x1f; int mant = half & 0x3ff; double val; - if (exp == 0) val = ldexp(mant, -24); - else if (exp != 31) val = ldexp(mant + 1024, exp - 25); + if (exp1 == 0) val = ldexp1(mant, -24); + else if (exp1 != 31) val = ldexp1(mant + 1024, exp1 - 25); else val = mant == 0 ? INFINITY : NAN; return (half & 0x8000) ? -val : val; } From 8f2983368cbfaddaeee05b4ca04c5bf338f6ce63 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:26:18 +0200 Subject: [PATCH 135/141] style --- client/crypto/libpcrypto.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 095d16af3..0def5b2f7 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -69,15 +69,15 @@ int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length } int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { - uint8_t cmac[16] = {0}; + uint8_t cmac_tmp[16] = {0}; memset(mac, 0x00, 8); - int res = aes_cmac(iv, key, input, cmac, length); + int res = aes_cmac(iv, key, input, cmac_tmp, length); if (res) return res; for (int i = 0; i < 8; i++) - mac[i] = cmac[i * 2 + 1]; + mac[i] = cmac_tmp[i * 2 + 1]; return 0; } @@ -382,13 +382,13 @@ int ecdsa_nist_test(bool verbose) { res = 1; goto exit; } - if (verbose) + + if (verbose) { printf("passed\n"); - - // random ecdsa test - if (verbose) printf(" ECDSA binary signature create/check test: "); - + } + + // random ecdsa test uint8_t key_d[32] = {0}; uint8_t key_xy[32 * 2 + 2] = {0}; memset(signature, 0x00, sizeof(signature)); From 1815376ef5a6e60dec3a3739351f7bd9c0f5e4dc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:26:30 +0200 Subject: [PATCH 136/141] style --- client/loclass/ikeys.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 16985ccb8..d7c965421 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -679,8 +679,7 @@ static bool readKeyFile(uint8_t key[8]) { if (bytes_read == 8) retval = true; - if (f) - fclose(f); + fclose(f); return retval; } From a2176b722d48fe6c9e41519d9cb1918c64f0c7f2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:28:43 +0200 Subject: [PATCH 137/141] fix --- client/tinycbor/cborinternal_p.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/tinycbor/cborinternal_p.h b/client/tinycbor/cborinternal_p.h index 2464ddeea..d971fa478 100644 --- a/client/tinycbor/cborinternal_p.h +++ b/client/tinycbor/cborinternal_p.h @@ -84,8 +84,8 @@ static inline double decode_half(unsigned short half) { int exp1 = (half >> 10) & 0x1f; int mant = half & 0x3ff; double val; - if (exp1 == 0) val = ldexp1(mant, -24); - else if (exp1 != 31) val = ldexp1(mant + 1024, exp1 - 25); + if (exp1 == 0) val = ldexp(mant, -24); + else if (exp1 != 31) val = ldexp(mant + 1024, exp1 - 25); else val = mant == 0 ? INFINITY : NAN; return (half & 0x8000) ? -val : val; } From ec278e60cc1e744b251c4f4ba8d0646b12af93c6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:34:40 +0200 Subject: [PATCH 138/141] unshadow --- client/util.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/util.c b/client/util.c index b257ea766..f69138947 100644 --- a/client/util.c +++ b/client/util.c @@ -835,11 +835,11 @@ uint32_t reflect(uint32_t v, int b) { } uint64_t HornerScheme(uint64_t num, uint64_t divider, uint64_t factor) { - uint64_t remainder = 0, quotient = 0, result = 0; - remainder = num % divider; + uint64_t remaind = 0, quotient = 0, result = 0; + remaind = num % divider; quotient = num / divider; - if (!(quotient == 0 && remainder == 0)) - result += HornerScheme(quotient, divider, factor) * factor + remainder; + if (!(quotient == 0 && remaind == 0)) + result += HornerScheme(quotient, divider, factor) * factor + remaind; return result; } From daa731309578f39df7f89a89b92caf64514a64ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 08:36:07 +0200 Subject: [PATCH 139/141] unshadow --- common/crapto1/crapto1.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index 417ac1c86..ea496e1c4 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -154,7 +154,7 @@ struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { // allocate memory for out of place bucket_sort bucket_array_t bucket; - for (uint32_t i = 0; i < 2; i++) { + for (i = 0; i < 2; i++) { for (uint32_t j = 0; j <= 0xff; j++) { bucket[i][j].head = malloc(sizeof(uint32_t) << 14); if (!bucket[i][j].head) { @@ -184,7 +184,7 @@ struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) { recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); out: - for (uint32_t i = 0; i < 2; i++) + for (i = 0; i < 2; i++) for (uint32_t j = 0; j <= 0xff; j++) free(bucket[i][j].head); free(odd_head); From 21fd059dc256b31fc5b67e21530ca6ffcace87ef Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 09:08:03 +0200 Subject: [PATCH 140/141] unshadow --- client/cmdhfmfhard.c | 132 +++++++++++++++++++++---------------------- 1 file changed, 65 insertions(+), 67 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 12aec1cb2..99afc6b01 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1365,9 +1365,8 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ bool field_off = false; hardnested_stage = CHECK_1ST_BYTES; bool acquisition_completed = false; - uint32_t flags = 0; uint8_t write_buf[9]; - uint32_t total_num_nonces = 0; + //uint32_t total_num_nonces = 0; float brute_force_depth; bool reported_suma8 = false; char progress_text[80]; @@ -1379,7 +1378,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ clearCommandBuffer(); do { - flags = 0; + uint32_t flags = 0; flags |= initialize ? 0x0001 : 0; flags |= slow ? 0x0002 : 0; flags |= field_off ? 0x0004 : 0; @@ -1394,9 +1393,9 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ if (initialize) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { //strange second call (iceman) - UsbCommand c = {CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4}}; + UsbCommand c1 = {CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4}}; clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c1); return 1; } if (resp.arg[0]) return resp.arg[0]; // error during nested_hard @@ -1438,7 +1437,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ } bufp += 9; } - total_num_nonces += num_sampled_nonces; + //total_num_nonces += num_sampled_nonces; if (first_byte_num == 256) { if (hardnested_stage == CHECK_1ST_BYTES) { @@ -1651,7 +1650,8 @@ static uint_fast8_t reverse(uint_fast8_t b) { static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even) { - uint32_t masks[2][8] = {{0x00fffff0, 0x00fffff8, 0x00fffff8, 0x00fffffc, 0x00fffffc, 0x00fffffe, 0x00fffffe, 0x00ffffff}, + uint32_t masks[2][8] = { + {0x00fffff0, 0x00fffff8, 0x00fffff8, 0x00fffffc, 0x00fffffc, 0x00fffffe, 0x00fffffe, 0x00ffffff}, {0x00fffff0, 0x00fffff0, 0x00fffff8, 0x00fffff8, 0x00fffffc, 0x00fffffc, 0x00fffffe, 0x00fffffe} }; @@ -1663,6 +1663,7 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even bool found_match = false; for (uint8_t remaining_bits = 0; remaining_bits <= (~mask & 0xff); remaining_bits++) { if (remaining_bits_match(num_common, bytes_diff, state, (state & mask) | remaining_bits, odd_even)) { + #ifdef DEBUG_KEY_ELIMINATION if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even, true)) { #else @@ -1673,7 +1674,9 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even } } } + if (!found_match) { + #ifdef DEBUG_KEY_ELIMINATION if (known_target_key != -1 && state == test_state[odd_even]) { PrintAndLogEx(NORMAL, "all_bitflips_match() 1st Byte: %s test state (0x%06x): Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", @@ -1693,7 +1696,6 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even return true; } - static void bitarray_to_list(uint8_t byte, uint32_t *bitarray, uint32_t *state_list, uint32_t *len, odd_even_t odd_even) { uint32_t *p = state_list; for (uint32_t state = next_state(bitarray, -1L); state < (1 << 24); state = next_state(bitarray, state)) { @@ -1715,7 +1717,7 @@ static void add_cached_states(statelist_t *candidates, uint16_t part_sum_a0, uin static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, uint8_t part_sum_a8, odd_even_t odd_even) { - uint32_t worstcase_size = 1 << 20; + const uint32_t worstcase_size = 1 << 20; candidates->states[odd_even] = (uint32_t *)malloc(sizeof(uint32_t) * worstcase_size); if (candidates->states[odd_even] == NULL) { PrintAndLogEx(WARNING, "Out of memory error in add_matching_states() - statelist.\n"); @@ -1772,28 +1774,26 @@ static statelist_t *add_more_candidates(void) { return new_candidates; } - static void add_bitflip_candidates(uint8_t byte) { - statelist_t *candidates = add_more_candidates(); + statelist_t *candidates1 = add_more_candidates(); for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { uint32_t worstcase_size = nonces[byte].num_states_bitarray[odd_even] + 1; - candidates->states[odd_even] = (uint32_t *)malloc(sizeof(uint32_t) * worstcase_size); - if (candidates->states[odd_even] == NULL) { + candidates1->states[odd_even] = (uint32_t *)malloc(sizeof(uint32_t) * worstcase_size); + if (candidates1->states[odd_even] == NULL) { PrintAndLogEx(WARNING, "Out of memory error in add_bitflip_candidates().\n"); exit(4); } - bitarray_to_list(byte, nonces[byte].states_bitarray[odd_even], candidates->states[odd_even], &(candidates->len[odd_even]), odd_even); + bitarray_to_list(byte, nonces[byte].states_bitarray[odd_even], candidates1->states[odd_even], &(candidates1->len[odd_even]), odd_even); - if (candidates->len[odd_even] + 1 < worstcase_size) { - candidates->states[odd_even] = realloc(candidates->states[odd_even], sizeof(uint32_t) * (candidates->len[odd_even] + 1)); + if (candidates1->len[odd_even] + 1 < worstcase_size) { + candidates1->states[odd_even] = realloc(candidates1->states[odd_even], sizeof(uint32_t) * (candidates1->len[odd_even] + 1)); } } return; } - static bool TestIfKeyExists(uint64_t key) { struct Crypto1State *pcs; pcs = crypto1_create(key); @@ -1839,7 +1839,6 @@ static bool TestIfKeyExists(uint64_t key) { return false; } - static work_status_t book_of_work[NUM_PART_SUMS][NUM_PART_SUMS][NUM_PART_SUMS][NUM_PART_SUMS]; static void init_book_of_work(void) { @@ -2013,12 +2012,12 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { // create and run worker threads pthread_t thread_id[NUM_REDUCTION_WORKING_THREADS]; - uint16_t sums[NUM_REDUCTION_WORKING_THREADS][3]; + uint16_t sums1[NUM_REDUCTION_WORKING_THREADS][3]; for (uint16_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { - sums[i][0] = sum_a0_idx; - sums[i][1] = sum_a8_idx; - sums[i][2] = i + 1; - pthread_create(thread_id + i, NULL, generate_candidates_worker_thread, sums[i]); + sums1[i][0] = sum_a0_idx; + sums1[i][1] = sum_a8_idx; + sums1[i][2] = i + 1; + pthread_create(thread_id + i, NULL, generate_candidates_worker_thread, sums1[i]); } // wait for threads to terminate: @@ -2045,7 +2044,6 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { hardnested_print_progress(num_acquired_nonces, "Apply Sum(a8) and all bytes bitflip properties", nonces[best_first_bytes[0]].expected_num_brute_force, 0); } - static void free_candidates_memory(statelist_t *sl) { if (sl == NULL) return; @@ -2054,7 +2052,6 @@ static void free_candidates_memory(statelist_t *sl) { free(sl); } - static void pre_XOR_nonces(void) { // prepare acquired nonces for faster brute forcing. @@ -2085,56 +2082,51 @@ static uint16_t SumProperty(struct Crypto1State *s) { return (sum_odd * (16 - sum_even) + (16 - sum_odd) * sum_even); } - static void Tests() { - if (known_target_key != -1) { - for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - uint32_t *bitset = nonces[best_first_bytes[0]].states_bitarray[odd_even]; - if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", - odd_even == EVEN_STATE ? "even" : "odd ", - best_first_bytes[0]); - } + + if (known_target_key == -1) + return; + + for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { + uint32_t *bitset = nonces[best_first_bytes[0]].states_bitarray[odd_even]; + if (!test_bit24(bitset, test_state[odd_even])) { + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", + odd_even == EVEN_STATE ? "even" : "odd ", + best_first_bytes[0]); } } - - if (known_target_key != -1) { - for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - uint32_t *bitset = all_bitflips_bitarray[odd_even]; - if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", - odd_even == EVEN_STATE ? "even" : "odd "); - } + for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { + uint32_t *bitset = all_bitflips_bitarray[odd_even]; + if (!test_bit24(bitset, test_state[odd_even])) { + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", + odd_even == EVEN_STATE ? "even" : "odd "); } } } - static void Tests2(void) { - if (known_target_key != -1) { - for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - uint32_t *bitset = nonces[best_first_byte_smallest_bitarray].states_bitarray[odd_even]; - if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", - odd_even == EVEN_STATE ? "even" : "odd ", - best_first_byte_smallest_bitarray); - } + + if (known_target_key == -1) + return; + + for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { + uint32_t *bitset = nonces[best_first_byte_smallest_bitarray].states_bitarray[odd_even]; + if (!test_bit24(bitset, test_state[odd_even])) { + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", + odd_even == EVEN_STATE ? "even" : "odd ", + best_first_byte_smallest_bitarray); } } - - if (known_target_key != -1) { - for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - uint32_t *bitset = all_bitflips_bitarray[odd_even]; - if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", - odd_even == EVEN_STATE ? "even" : "odd "); - } + + for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { + uint32_t *bitset = all_bitflips_bitarray[odd_even]; + if (!test_bit24(bitset, test_state[odd_even])) { + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", + odd_even == EVEN_STATE ? "even" : "odd "); } } - } - static uint16_t real_sum_a8 = 0; static void set_test_state(uint8_t byte) { @@ -2147,7 +2139,6 @@ static void set_test_state(uint8_t byte) { crypto1_destroy(pcs); } - int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) { char progress_text[80]; char instr_set[12] = {0}; @@ -2175,6 +2166,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc hardnested_print_progress(0, progress_text, (float)(1LL << 47), 0); sprintf(progress_text, "Starting Test #%" PRIu32 " ...", i + 1); hardnested_print_progress(0, progress_text, (float)(1LL << 47), 0); + if (trgkey != NULL) { known_target_key = bytes_to_num(trgkey, 6); } else { @@ -2256,9 +2248,18 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc } } #ifdef DEBUG_KEY_ELIMINATION - fprintf(fstats, "%1.1f;%1.0f;%d;%s\n", log(num_keys_tested) / log(2.0), (float)num_keys_tested / brute_force_per_second, key_found, failstr); + fprintf(fstats, "%1.1f;%1.0f;%c;%s\n", + log(num_keys_tested) / log(2.0), + (float)num_keys_tested / brute_force_per_second, + key_found ? 'Y' : 'N', + failstr + ); #else - fprintf(fstats, "%1.0f;%d\n", log(num_keys_tested) / log(2.0), (float)num_keys_tested / brute_force_per_second, key_found); + fprintf(fstats, "%1.0f;%d\n", + log(num_keys_tested) / log(2.0), + (float)num_keys_tested / brute_force_per_second, + key_found + ); #endif free_nonces_memory(); @@ -2303,7 +2304,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_bitarray(all_bitflips_bitarray[EVEN_STATE]); free_sum_bitarrays(); free_part_sum_bitarrays(); - return is_OK; } } @@ -2372,7 +2372,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc // and calculate new expected number of brute forces update_expected_brute_force(best_first_bytes[0]); } - } } @@ -2382,6 +2381,5 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_sum_bitarrays(); free_part_sum_bitarrays(); } - return 0; } From 55cbedc600dcac11174237d36183518338172338 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 8 Apr 2019 09:24:31 +0200 Subject: [PATCH 141/141] styles --- client/cmdsmartcard.c | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index a930d3be5..6d99dc98c 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -195,7 +195,7 @@ 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; + uint8_t T1len = 0, TD1len = 0, TDilen = 0; bool protocol_T0_present = true; bool protocol_T15_present = false; @@ -215,7 +215,7 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { } if (T0 & 0x80) { - TD1 = atr[2 + T1len]; + uint8_t 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) { @@ -659,9 +659,7 @@ int CmdSmartUpgrade(const char *Cmd) { } size_t firmware_size = fread(dump, 1, fsize, f); - if (f) { - fclose(f); - } + fclose(f); // load sha512 file f = fopen(sha512filename, "rb"); @@ -694,24 +692,23 @@ int CmdSmartUpgrade(const char *Cmd) { size_t bytes_read = fread(hashstring, 1, 128, f); hashstring[128] = '\0'; - if (f) - fclose(f); + fclose(f); - uint8_t hash1[64]; - if (bytes_read != 128 || param_gethex(hashstring, 0, hash1, 128)) { + uint8_t hash_1[64]; + if (bytes_read != 128 || param_gethex(hashstring, 0, hash_1, 128)) { PrintAndLogEx(FAILED, "Couldn't read SHA-512 file"); free(dump); return 1; } - uint8_t hash2[64]; - if (sha512hash(dump, firmware_size, hash2)) { + uint8_t hash_2[64]; + if (sha512hash(dump, firmware_size, hash_2)) { PrintAndLogEx(FAILED, "Couldn't calculate SHA-512 of firmware"); free(dump); return 1; } - if (memcmp(hash1, hash2, 64)) { + if (memcmp(hash_1, hash_2, 64)) { PrintAndLogEx(FAILED, "Couldn't verify integrity of firmware file " _RED_("(wrong SHA-512 hash)")); free(dump); return 1; @@ -951,7 +948,6 @@ static void smart_brute_prim() { if (!buf) return; - int len = 0; uint8_t get_card_data[] = { 0x80, 0xCA, 0x9F, 0x13, 0x00, 0x80, 0xCA, 0x9F, 0x17, 0x00, @@ -959,27 +955,25 @@ static void smart_brute_prim() { 0x80, 0xCA, 0x9F, 0x4f, 0x00 }; - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, 5, 0}}; - PrintAndLogEx(INFO, "Reading primitives"); + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, 5, 0}}; + for (int i = 0; i < sizeof(get_card_data); i += 5) { memcpy(c.d.asBytes, get_card_data + i, 5); clearCommandBuffer(); SendCommand(&c); - len = smart_responseEx(buf, true); + int len = smart_responseEx(buf, true); if (len > 2) { - // if ( decodeTLV ) { // if (!TLVPrintFromBuffer(buf, len-2)) { PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); // } // } } - len = 0; } free(buf); } @@ -990,7 +984,7 @@ static int smart_brute_sfi(bool decodeTLV) { if (!buf) return 1; - int len = 0; + int len; // READ RECORD uint8_t READ_RECORD[] = {0x00, 0xB2, 0x00, 0x00, 0x00}; UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}};