diff --git a/armsrc/appmain.c b/armsrc/appmain.c index ec6ebb2c0..b0a78ccb1 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -49,6 +49,7 @@ #include "commonutil.h" #include "crc16.h" + #ifdef WITH_LCD #include "LCD_disabled.h" #endif @@ -1084,7 +1085,7 @@ static void PacketReceived(PacketCommandNG *packet) { break; } case CMD_LF_HITAG_SIMULATE: { // Simulate Hitag tag, args = memory content - SimulateHitag2((bool)packet->oldarg[0], packet->data.asBytes); + SimulateHitag2(); break; } case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function @@ -1111,6 +1112,18 @@ static void PacketReceived(PacketCommandNG *packet) { } break; } + case CMD_LF_HITAG_ELOAD: { + /* + struct p { + uint16_t len; + uint8_t *data; + } PACKED; + struct p *payload = (struct p *) packet->data.asBytes; + uint8_t *mem = BigBuf_get_EM_addr(); + memcpy((uint8_t *)mem.sectors, payload->data, payload->len); + */ + break; + } #endif #ifdef WITH_EM4x50 diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index c2916bfe2..b7db20919 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -106,15 +106,13 @@ static int16_t blocknr; static size_t flipped_bit = 0; static uint32_t byte_value = 0; -static int hitag2_reset(void) { +static void hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; - return 0; } -static int hitag2_init(void) { +static void hitag2_init(void) { hitag2_reset(); - return 0; } // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) @@ -126,14 +124,14 @@ static int hitag2_init(void) { #endif #define HITAG_FRAME_LEN 20 -#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ -#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ -#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ +#define HITAG_T_STOP 37 /* T_EOF should be > 36 */ +#define HITAG_T_LOW 4 /* T_LOW should be 4..10 */ +#define HITAG_T_0_MIN 17 /* T[0] should be 18..22 */ #define HITAG_T_0 20 /* T[0] should be 18..22 */ #define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ #define HITAG_T_1 30 /* T[1] should be 26..30 */ //#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ -#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ +#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ #define HITAG_T_WAIT_1_MIN 199 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_2_MIN 90 /* T_wait2 should be at least 90 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ @@ -987,84 +985,330 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t return true; } +void EloadHitag(uint8_t *data, uint16_t len) { + memcpy(tag.sectors, data, sizeof(tag.sectors)); +} + // Hitag2 Sniffing + +// T0 18-22 fc (total time ZERO) +// T1 26-32 fc (total time ONE) +// Tstop 36 > fc (high field stop limit) +// Tlow 4-10 fc (reader field low time) void SniffHitag2(void) { + DbpString("Starting Hitag2 sniffing"); + LED_D_ON(); + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - auth_table_len = 0; - auth_table_pos = 0; - - auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - - DbpString("Starting Hitag2 sniffing"); - LED_D_ON(); - +/* lf_init(false, false); - g_logging = false; + // no logging of the raw signal + g_logging = lf_get_reader_modulation(); + uint32_t total_count = 0; - uint8_t periods_bytes[4]; - -// int16_t checked = 0; - - /*bool waiting_for_first_edge = true;*/ - LED_C_ON(); - - uint32_t signal_size = 10000; + uint8_t rx[20 * 8 * 2]; while (BUTTON_PRESS() == false) { - // use malloc - initSampleBufferEx(&signal_size, false); + lf_reset_counter(); WDT_HIT(); - /* - // only every 1000th times, in order to save time when collecting samples. - if (checked == 1000) { - if (data_available()) { - checked = -1; - break; - } else { - checked = 0; - } - } - ++checked; - */ + size_t periods = 0; + uint16_t rxlen = 0; + memset(rx, 0x00, sizeof(rx)); + // Use the current modulation state as starting point + uint8_t mod_state = lf_get_reader_modulation(); - // Receive frame, watch for at most T0*EOF periods -// lf_reset_counter(); - - // Wait "infinite" for reader modulation - size_t periods = lf_detect_gap(10000); - - // Test if we detected the first reader modulation edge - if (periods != 0) { - if (g_logging == false) { - g_logging = true; - LED_D_ON(); + while (rxlen < sizeof(rx)) { + periods = lf_count_edge_periods(64); + // Evaluate the number of periods before the next edge + if (periods >= 24 && periods < 64) { + // Detected two sequential equal bits and a modulation switch + // NRZ modulation: (11 => --|) or (11 __|) + rx[rxlen++] = mod_state; + rx[rxlen++] = mod_state; + // toggle tag modulation state + mod_state ^= 1; + } else if (periods > 0 && periods < 24) { + // Detected one bit and a modulation switch + // NRZ modulation: (1 => -|) or (0 _|) + rx[rxlen++] = mod_state; + mod_state ^= 1; + } else { + mod_state ^= 1; + break; } } + + if (rxlen == 0) + continue; - /*lf_count_edge_periods(10000);*/ - while ((periods = lf_detect_gap(64)) != 0) { - num_to_bytes(periods, 4, periods_bytes); - LogTrace(periods_bytes, 4, 0, 0, NULL, true); + // tag sends 11111 + uid, + bool got_tag = ((memcmp(rx, "\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00", 10) == 0)); + + if (got_tag) { + // mqnchester decode + bool bad_man = false; + uint16_t bitnum = 0; + for (uint16_t i = 0; i < rxlen; i += 2) { + if (rx[i] == 1 && (rx[i + 1] == 0)) { + rx[bitnum++] = 0; + } else if ((rx[i] == 0) && rx[i + 1] == 1) { + rx[bitnum++] = 1; + } else { + bad_man = true; + } + } + + if (bad_man) { + DBG DbpString("bad manchester"); + continue; + } + + if (bitnum < 5) { + DBG DbpString("too few bits"); + continue; + } + + // skip header 11111 + uint16_t i = 0; + if (got_tag) { + i = 5; + } + + // Pack the response into a byte array + rxlen = 0; + for (; i < bitnum; i++) { + uint8_t b = rx[i]; + rx[rxlen >> 3] |= b << (7 - (rxlen % 8)); + rxlen++; + } + + // skip spurious bit + if (rxlen % 8 == 1) { + rxlen--; + } + + // nothing to log + if (rxlen == 0) + continue; + + LogTrace(rx, nbytes(rxlen), 0, 0, NULL, false); + total_count += nbytes(rxlen); + } else { + // decode reader comms + LogTrace(rx, rxlen, 0, 0, NULL, true); + total_count += rxlen; + // Pack the response into a byte array + + // LogTrace(rx, nbytes(rdr), 0, 0, NULL, true); + // total_count += nbytes(rdr); } + LED_A_INV(); } lf_finalize(); - DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations"); + Dbprintf("Collected %u bytes", total_count); + + */ + + // 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 + 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; + + // Disable modulation, we are going to eavesdrop, not modulate ;) + LOW(GPIO_SSC_DOUT); + + // 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_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 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; + + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + int frame_count = 0, response = 0, overflow = 0, lastbit = 1, tag_sof = 4; + bool rising_edge = false, reader_frame = false, bSkip = true; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + + auth_table_len = 0; + auth_table_pos = 0; + + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + + auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); + memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + + while(BUTTON_PRESS() == false) { + + WDT_HIT(); + memset(rx, 0x00, sizeof(rx)); + + // Receive frame, watch for at most T0 * EOF periods + while (AT91C_BASE_TC1->TC_CV < (HITAG_T0 * HITAG_T_EOF) ) { + // Check if rising edge in modulation is detected + if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0); + + // Find out if we are dealing with a rising or falling edge + rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + + // Shorter periods will only happen with reader frames + if (reader_frame == false && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { + // Switch from tag to reader capture + LED_C_OFF(); + reader_frame = true; + rxlen = 0; + } + + // Only handle if reader frame and rising edge, or tag frame and falling edge + if (reader_frame == rising_edge) { + overflow += ra; + continue; + } + + // Add the buffered timing values of earlier captured edges which were skipped + ra += overflow; + overflow = 0; + + if (reader_frame) { + LED_B_ON(); + // Capture reader frame + if(ra >= HITAG_T_STOP) { +// if (rxlen != 0) { + //DbpString("wierd0?"); +// } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if(ra >= HITAG_T_1_MIN ) { + // '1' bit + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if(ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + } + + } else { + LED_C_ON(); + // Capture tag frame (manchester decoding using only falling edges) + if(ra >= HITAG_T_EOF) { +// if (rxlen != 0) { + //DbpString("wierd1?"); +// } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; + + } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + + } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (bSkip == false) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + + } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } + } + } + } + + // Check if frame was captured + if(rxlen) { + frame_count++; + LogTrace(rx, nbytes(rxlen), response, 0, NULL, reader_frame); + + // Check if we recognize a valid authentication attempt + if (nbytes(rxlen) == 8) { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH - 8)) { + memcpy(auth_table + auth_table_len, rx, 8); + auth_table_len += 8; + } + } + + // Reset the received frame and response timing info + memset(rx, 0x00, sizeof(rx)); + response = 0; + reader_frame = false; + lastbit = 1; + bSkip = true; + tag_sof = 4; + overflow = 0; + + LED_B_OFF(); + LED_C_OFF(); + } else { + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); + } + // Reset the frame length + rxlen = 0; + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } + + 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); + + Dbprintf("frame received: %d",frame_count); + Dbprintf("Authentication Attempts: %d",(auth_table_len / 8)); + } // Hitag2 simulation -void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { +void SimulateHitag2() { BigBuf_free(); BigBuf_Clear_ext(false); @@ -1092,12 +1336,6 @@ void SimulateHitag2(bool tag_mem_supplied, uint8_t *data) { // hitag2 state machine? hitag2_init(); - // copy user supplied emulation data - if (tag_mem_supplied) { - DbpString("Loading hitag2 memory..."); - memcpy((uint8_t *)tag.sectors, data, 48); - } - // printing uint32_t block = 0; for (size_t i = 0; i < 12; i++) { diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h index ec3d0d7f3..ef92f0560 100644 --- a/armsrc/hitag2.h +++ b/armsrc/hitag2.h @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // (c) 2012 Roel Verdult +// modified 2021 Iceman // // 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 @@ -15,8 +16,8 @@ #include "hitag.h" void SniffHitag2(void); -void SimulateHitag2(bool tag_mem_supplied, uint8_t *data); +void SimulateHitag2(void); void ReaderHitag(hitag_function htf, hitag_data *htd); void WriterHitag(hitag_function htf, hitag_data *htd, int page); - +void EloadHitag(uint8_t *data, uint16_t len); #endif