diff --git a/armsrc/Makefile b/armsrc/Makefile index beb19c243..12819c3d0 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -23,7 +23,7 @@ APP_CFLAGS = $(PLATFORM_DEFS) \ -DON_DEVICE \ -fno-strict-aliasing -ffunction-sections -fdata-sections -SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c +SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c lfadc.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c #UNUSED: mifaresniff.c desfire_crypto.c diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 3531ac9ea..6efe5808d 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -17,6 +17,8 @@ //----------------------------------------------------------------------------- // Piwi, 2019 // Iceman, 2019 +// Anon, 2019 +// Doegos, 2020 #include "hitag2.h" #include "hitag2_crypto.h" @@ -28,12 +30,18 @@ #include "ticks.h" #include "dbprint.h" #include "util.h" +#include "lfadc.h" +#include "lfsampling.h" +#include "lfdemod.h" +#include "commonutil.h" // Successful crypto auth static bool bCrypto; // Is in auth stage static bool bAuthenticating; // Successful password auth +bool bSelecting; +bool bCollision; static bool bPwd; static bool bSuccessful; @@ -52,6 +60,7 @@ static struct hitag2_tag tag = { [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC + // up to index 15 reserved for HITAG1/HITAGS public data }, }; @@ -73,6 +82,9 @@ static uint8_t password[4]; static uint8_t NrAr[8]; static uint8_t key[8]; static uint8_t writedata[4]; +uint8_t logdata_0[4], logdata_1[4]; +uint8_t nonce[4]; +bool key_no; static uint64_t cipher_state; static int hitag2_reset(void) { @@ -90,19 +102,21 @@ static int hitag2_init(void) { // 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 +#ifndef HITAG_T0 +#define HITAG_T0 192 #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_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_WAIT_1 200 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ +#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 */ #define HITAG_T_PROG 614 @@ -128,15 +142,15 @@ static void hitag_send_bit(int bit) { if (bit == 0) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD); HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD); } else { // Manchester: Loaded, then unloaded |--__| HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_HALF_PERIOD); LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD); + while (AT91C_BASE_TC0->TC_CV < HITAG_T0 * HITAG_T_TAG_FULL_PERIOD); } LED_A_OFF(); } @@ -286,52 +300,289 @@ static void hitag2_handle_reader_command(uint8_t *rx, const size_t rxlen, uint8_ } // sim -static void hitag_reader_send_bit(int bit) { +static uint32_t hitag_reader_send_bit(int bit) { + uint32_t wait = 0; LED_A_ON(); - // 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 + // Binary pulse 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 field - HIGH(GPIO_SSC_DOUT); + lf_modulation(true); // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + lf_wait_periods(8); // wait for 4-10 times the carrier period + wait += 8; // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + lf_modulation(false); if (bit == 0) { // Zero bit: |_-| - while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - + lf_wait_periods(HITAG_T_0-HITAG_T_LOW); // wait for 18-22 times the carrier period + wait += HITAG_T_0-HITAG_T_LOW; } else { // One bit: |_--| - while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; + lf_wait_periods(HITAG_T_1-HITAG_T_LOW); // wait for 26-32 times the carrier period + wait += HITAG_T_1-HITAG_T_LOW; } + /*lf_wait_periods(10);*/ LED_A_OFF(); + return wait; } // sim -static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { +static uint32_t hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { + uint32_t wait = 0; // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { - hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + wait += hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } - // Send EOF - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Enable modulation, which means, drop the field - HIGH(GPIO_SSC_DOUT); + lf_modulation(true); // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + lf_wait_periods(HITAG_T_LOW); + wait += HITAG_T_LOW; // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + lf_modulation(false); + + // t_stop, high field for stop condition (> 36) + lf_wait_periods(HITAG_T_STOP); + wait += HITAG_T_STOP; + return wait; } size_t blocknr; +uint8_t hitag_crc(uint8_t *data, size_t length) { + uint8_t crc = 0xff; + unsigned int byte, bit; + for (byte = 0; byte < ((length + 7) / 8); byte++) { + crc ^= *(data + byte); + bit = length < (8 * (byte + 1)) ? (length % 8) : 8; + while (bit--) { + if (crc & 0x80) { + crc <<= 1; + crc ^= 0x1d; + } else { + crc <<= 1; + } + } + } + return crc; +} + +#define test_bit(data, i) (*(data+(i/8)) >> (7-(i%8))) & 1 +#define set_bit(data, i) *(data+(i/8)) |= (1 << (7-(i%8))) +#define clear_bit(data, i) *(data+(i/8)) &= ~(1 << (7-(i%8))) +#define flip_bit(data, i) *(data+(i/8)) ^= (1 << (7-(i%8))) +void fix_ac_decoding(uint8_t *input, size_t len) { + // Reader routine tries to decode AC data after Manchester decoding + // AC has double the bitrate, extract data from bit-pairs + uint8_t temp[len / 16]; + memset(temp, 0, sizeof(temp)); + + for (size_t i = 1; i < len; i += 2) { + if (test_bit(input, i) && test_bit(input, (i + 1))) { + set_bit(temp, (i / 2)); + } + } + memcpy(input, temp, sizeof(temp)); +} + +bool hitag_plain(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen, bool hitag_s) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if (!bCollision) blocknr--; + if (blocknr < 0) { + blocknr = 0; + } + if (!hitag_s) { + if (blocknr > 1 && blocknr < 31) { + blocknr = 31; + } + } + bCollision = true; + return true; + } + case 32: { + if (bCollision) { + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx, 37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + } else { + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + if (!hitag_s) { + if (blocknr > 1 && blocknr < 31) { + blocknr = 31; + } + } + if (blocknr > 63) { + DbpString("Read succesful!"); + *txlen = 0; + bSuccessful = true; + return false; + } + // read next page of card until done + Dbprintf("Reading page %02u", blocknr); + tx[0] = 0xc0 | blocknr >> 4; // RDPPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + } + } + break; + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } + break; + } + return true; +} + +size_t flipped_bit = 0; + +uint32_t byte_value = 0; +bool hitag1_authenticate(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { + uint8_t crc; + *txlen = 0; + switch (rxlen) { + case 0: { + // retry waking up card + /*tx[0] = 0xb0; // Rev 3.0*/ + tx[0] = 0x30; // Rev 2.0 + *txlen = 5; + if (bCrypto && byte_value <= 0xff) { + // to retry + bCrypto = false; + } + if (!bCollision) blocknr--; + if (blocknr < 0) { + blocknr = 0; + } + bCollision = true; + // will receive 32-bit UID + } + break; + case 2: { + if (bAuthenticating) { + // received Auth init ACK, send nonce + // TODO Roel, bit-manipulation goes here + /*nonce[0] = 0x2d;*/ + /*nonce[1] = 0x74;*/ + /*nonce[2] = 0x80;*/ + /*nonce[3] = 0xa5;*/ + nonce[0] = byte_value; + byte_value++; + /*set_bit(nonce,flipped_bit);*/ + memcpy(tx, nonce, 4); + *txlen = 32; + // will receive 32 bit encrypted Logdata + } else if (bCrypto) { + // authed, start reading + tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + // will receive 32-bit encrypted page + } + } + break; + case 32: { + if (bCollision) { + // Select card by serial from response + tx[0] = 0x00 | rx[0] >> 5; + tx[1] = rx[0] << 3 | rx[1] >> 5; + tx[2] = rx[1] << 3 | rx[2] >> 5; + tx[3] = rx[2] << 3 | rx[3] >> 5; + tx[4] = rx[3] << 3; + crc = hitag_crc(tx, 37); + tx[4] |= crc >> 5; + tx[5] = crc << 3; + *txlen = 45; + bCollision = false; + bSelecting = true; + // will receive 32-bit configuration page + } else if (bSelecting) { + // Initiate auth + tx[0] = 0xa0 | key_no >> 4; // WRCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + bSelecting = false; + bAuthenticating = true; + // will receive 2-bit ACK + } else if (bAuthenticating) { + // received 32-bit logdata 0 + // TODO decrypt logdata 0, verify against logdata_0 + memcpy(tag.sectors[0], rx, 4); + memcpy(tag.sectors[1], tx, 4); + Dbprintf("%02x%02x%02x%02x %02x%02x%02x%02x", rx[0], rx[1], rx[2], rx[3], tx[0], tx[1], tx[2], tx[3]); + // TODO replace with secret data stream + // TODO encrypt logdata_1 + memcpy(tx, logdata_1, 4); + *txlen = 32; + bAuthenticating = false; + bCrypto = true; + // will receive 2-bit ACK + } else if (bCrypto) { + // received 32-bit encrypted page + // TODO decrypt rx + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + if (blocknr > 63) { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } + + // TEST + Dbprintf("Succesfully authenticated with logdata:"); + Dbhexdump(4, logdata_1, false); + bSuccessful = true; + return false; + + // read next page of card until done + tx[0] = 0xe0 | blocknr >> 4; // RDCPAGE + tx[1] = blocknr << 4; + crc = hitag_crc(tx, 12); + tx[1] |= crc >> 4; + tx[2] = crc << 4; + *txlen = 20; + } + } + break; + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } + break; + } + + return true; +} + //----------------------------------------------------------------------------- // Hitag2 operations //----------------------------------------------------------------------------- @@ -686,9 +937,11 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Store the received block memcpy(tag.sectors[blocknr], rx, 4); blocknr++; + + Dbhexdump(4, rx, false); } if (blocknr > 0) { - // DbpString("Read successful!"); + DbpString("Read successful!"); bSuccessful = true; return false; } @@ -707,19 +960,9 @@ static bool hitag2_read_uid(uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t // Hitag2 Sniffing void SniffHitag(void) { + LEDsoff(); StopTicks(); - // int frame_count; - int response; - int overflow; - bool rising_edge; - bool reader_frame; - int lastbit; - bool bSkip; - int tag_sof; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); BigBuf_free(); BigBuf_Clear_ext(false); @@ -735,188 +978,62 @@ void SniffHitag(void) { 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, LF_DIVISOR_125); - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + lf_init(false); + logging = false; - // 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; + size_t periods = 0; + uint8_t periods_bytes[4]; - // 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; - - // 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_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 TC1 returned to zero - - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - // frame_count = 0; - response = 0; - overflow = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; + /*bool waiting_for_first_edge = true;*/ + LED_C_ON(); while (!BUTTON_PRESS() && !data_available()) { - // Watchdog hit + WDT_HIT(); // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < 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 / T0); + lf_reset_counter(); - // Find out if we are dealing with a rising or falling edge - rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + // Wait "infinite" for reader modulation + periods = lf_detect_gap(20000); - // Shorter periods will only happen with reader frames - if (!reader_frame && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { - // Switch from tag to reader capture - LED_C_OFF(); - reader_frame = true; - memset(rx, 0x00, sizeof(rx)); - 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 { - // Ignore wierd value, is to small to mean anything - } - } 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) { - 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++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } + // Test if we detected the first reader modulation edge + if (periods != 0) { + if (logging == false) { + logging = true; + LED_D_ON(); } } - // Check if frame was captured - if (rxlen > 0) { - // 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 / T0); + /*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); } - // Reset the frame length - rxlen = 0; - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + + + /* + // Check if frame was captured + if (rxlen > 0) { + // 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; + } + } + */ } - LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + lf_finalize(); - // release allocated memory from BigBuff. - BigBuf_free(); StartTicks(); - DbpString("Hitag2 sniffing end, use `lf hitag list` for annotations"); + DbpString("Hitag2 sniffing finish. Use `lf hitag list` for annotations"); } // Hitag2 simulation @@ -1007,11 +1124,11 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { WDT_HIT(); // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) { + 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 / T0) + overflow; + int ra = (AT91C_BASE_TC1->TC_RA / HITAG_T0) + overflow; overflow = 0; // Reset timer every frame, we have to capture the last edge for timing @@ -1056,7 +1173,7 @@ void SimulateHitagTag(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 < HITAG_T0 * (HITAG_T_WAIT_1_MIN - HITAG_T_LOW)); // Send and store the tag answer (if there is any) if (txlen) { @@ -1075,7 +1192,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { // Reset the frame length rxlen = 0; // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / T0); + overflow += (AT91C_BASE_TC1->TC_CV / HITAG_T0); // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } @@ -1098,24 +1215,67 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { StopTicks(); - // int frame_count = 0; - int response = 0; + int frame_count = 0; + uint32_t command_start = 0; + uint32_t command_duration = 0; + uint32_t response_start = 0; + uint32_t response_duration = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; - int lastbit = 1; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; + int t_wait_1; + int t_wait_1_guard = 8; + int t_wait_2; + size_t tag_size; bool bStop = false; + // Raw demodulation/decoding by sampling edge periods + size_t periods = 0; + + // Reset the return status bSuccessful = false; + bCrypto = false; + + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + DbpString("Starting Hitag reader family"); // Check configuration switch (htf) { + case RHT1F_PLAIN: { + Dbprintf("Read public blocks in plain mode"); + // this part will be unreadable + memset(tag.sectors + 2, 0x0, 30); + blocknr = 0; + } + break; + + case RHT1F_AUTHENTICATE: { + Dbprintf("Read all blocks in authed mode"); + memcpy(nonce, htd->ht1auth.nonce, 4); + memcpy(key, htd->ht1auth.key, 4); + memcpy(logdata_0, htd->ht1auth.logdata_0, 4); + memcpy(logdata_1, htd->ht1auth.logdata_1, 4); + // TEST + memset(nonce, 0x0, 4); + memset(logdata_1, 0x00, 4); + byte_value = 0; + key_no = htd->ht1auth.key_no; + Dbprintf("Authenticating using key #%d:", key_no); + Dbhexdump(4, key, false); + DbpString("Nonce:"); + Dbhexdump(4, nonce, false); + DbpString("Logdata_0:"); + Dbhexdump(4, logdata_0, false); + DbpString("Logdata_1:"); + Dbhexdump(4, logdata_1, false); + blocknr = 0; + } + break; case RHT2F_PASSWORD: { Dbprintf("List identifier in password mode"); memcpy(password, htd->pwd.password, 4); @@ -1136,6 +1296,9 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { DbpString("Authenticating using key:"); memcpy(key, htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. Dbhexdump(6, key, false); + DbpString("Nonce:"); + Dbhexdump(4, nonce, false); + memcpy(nonce, htd->crypto.data, 4); blocknr = 0; bCrypto = false; bAuthenticating = false; @@ -1162,85 +1325,64 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - BigBuf_free(); - clear_trace(); - set_tracing(true); - LED_D_ON(); + hitag2_init(); + // init as reader + lf_init(true); - // 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, LF_DIVISOR_125); //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; - - // 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); - - // 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; - - // 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; - - // 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; - - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0) {}; // wait until TC0 returned to zero + uint8_t attempt_count = 0; // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + /*tag_size = 256;*/ + flipped_bit = 0; + tag_size = 8; + DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + tag_size = 256; + flipped_bit = 0; + DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings - reset_sof = 4; - t_wait = HITAG_T_WAIT_2; + t_wait_1 = HITAG_T_WAIT_1_MIN; + t_wait_2 = HITAG_T_WAIT_2_MIN; + tag_size = 48; + DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); - goto out; + return; } - uint8_t attempt_count = 0; + + uint8_t tag_modulation; + size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit + uint8_t nrz_samples[max_nrzs]; + size_t nrzs = 0; while (!bStop && !BUTTON_PRESS() && !data_available()) { WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - } - // By default reset the transmission buffer tx = txbuf; switch (htf) { + case RHT1F_PLAIN: { + bStop = !hitag_plain(rx, rxlen, tx, &txlen, false); + } + break; + + case RHT1F_AUTHENTICATE: { + bStop = !hitag1_authenticate(rx, rxlen, tx, &txlen); + } + break; + case RHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, false); break; @@ -1271,138 +1413,212 @@ void ReaderHitag(hitag_function htf, hitag_data *htd) { } } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred 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))); + // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, + lf_wait_periods(t_wait_2); + command_start += t_wait_2; // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + command_duration = hitag_reader_send_frame(tx, txlen); + response_start = command_start + command_duration; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Let the antenna and ADC values settle + // And find the position where edge sampling should start + lf_wait_periods(t_wait_1 - t_wait_1_guard); + response_start += t_wait_1 - t_wait_1_guard; - // Add transmitted frame to total count + // Keep administration of the first edge detection + bool waiting_for_first_edge = true; + + // Did we detected any modulaiton at all + bool detected_tag_modulation = false; + + // Use the current modulation state as starting point + tag_modulation = lf_get_tag_modulation(); + + // Reset the number of NRZ samples and use edge detection to detect them + nrzs = 0; + while (nrzs < max_nrzs) { + // Get the timing of the next edge in number of wave periods + periods = lf_count_edge_periods(128); + + // Are we dealing with the first incoming edge + if (waiting_for_first_edge) { + // Just break out of loop after an initial time-out (tag is probably not available) + if (periods == 0) break; + if (tag_modulation == 0) { + // hitag replies always start with 11111 == 1010101010, if we see 0 + // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal + // so let's add it: + nrz_samples[nrzs++] = tag_modulation ^ 1; + // Register the number of periods that have passed + // we missed the begin of response but we know it happened one period of 16 earlier + response_start += periods - 16; + response_duration = response_start; + } else { + // Register the number of periods that have passed + response_start += periods; + response_duration = response_start; + } + // Indicate that we have dealt with the first edge + waiting_for_first_edge = false; + // The first edge is always a single NRZ bit, force periods on 16 + periods = 16; + // We have received more than 0 periods, so we have detected a tag response + detected_tag_modulation = true; + } else { + // The function lf_count_edge_periods() returns 0 when a time-out occurs + if (periods == 0) { + //Dbprintf("Detected timeout after [%d] nrz samples", nrzs); + break; + } + } + // 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 __|) + nrz_samples[nrzs++] = tag_modulation; + nrz_samples[nrzs++] = tag_modulation; + response_duration += periods; + // Invert tag modulation state + tag_modulation ^= 1; + } else if (periods > 0 && periods <= 24) { + // Detected one bit and a modulation switch + // NRZ modulation: (1 => -|) or (0 _|) + nrz_samples[nrzs++] = tag_modulation; + response_duration += periods; + tag_modulation ^= 1; + } else { + // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods + //Dbprintf("Detected unexpected period count: %d", periods); + break; + } + } + + // Store the TX frame, we do this now at this point, to avoid delay in processing + // and to be able to overwrite the first samples with the trace (since they currently + // still use the same memory space) if (txlen > 0) { - // frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + frame_count++; + LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); } // Reset values for receiving frames memset(rx, 0x00, sizeof(rx)); rxlen = 0; - lastbit = 1; - 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) { + // If there is no response, just repeat the loop + if (!detected_tag_modulation) continue; - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); + // Make sure we always have an even number of samples. This fixes the problem + // of ending the manchester decoding with a zero. See the example below where + // the '|' character is end of modulation + // One at the end: ..._-|_____... + // Zero at the end: ...-_|_____... + // The last modulation change of a zero is not detected, but we should take + // the half period in account, otherwise the demodulator will fail. + if ((nrzs % 2) != 0) { + nrz_samples[nrzs++] = tag_modulation; + } - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + LED_B_ON(); - LED_B_ON(); + // decode bitstream + manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - // 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) { - 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++; - } - } else { - errorCount++; - // Ignore wierd value, is to small to mean anything + // decode frame + + // Verify if the header consists of five consecutive ones + if (nrzs < 5) { + //Dbprintf("Detected unexpected number of manchester decoded samples [%d]", nrzs); + break; + } else { + size_t i; + for (i = 0; i < 5; i++) { + if (nrz_samples[i] != 1) { + Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i); + break; } } - //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; + if (i < 5) break; + } + + // Pack the response into a byte array + for (size_t i = 5; i < nrzs; i++) { + uint8_t bit = nrz_samples[i]; + if (bit > 1) { // When Manchester detects impossible symbol it writes "7" + //Dbprintf("Error in Manchester decoding, abort"); + break; } + rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); + rxlen++; + } + if (rxlen % 8 == 1) // skip spurious bit + rxlen--; + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; +// if (bCollision){ +// // AC decoding hack +// fix_ac_decoding(rx, 64); +// rxlen = 32; +// } + + LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); +// TODO when using cumulative time for command_start, pm3 doesn't reply anymore, e.g. on lf hitag read 23 4F4E4D494B52 + command_start = response_start + response_duration; +// command_start = 0; + // Dbhexdump(nbytes(rxlen), rx, false); } } 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; + lf_finalize(); + Dbprintf("TX/RX frames recorded: %u", frame_count); // release allocated memory from BigBuff. BigBuf_free(); StartTicks(); if (bSuccessful) - reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); + reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); else - reply_old(CMD_ACK, bSuccessful, 0, 0, 0, 0); + reply_mix(CMD_ACK, bSuccessful, 0, 0, 0, 0); } void WriterHitag(hitag_function htf, hitag_data *htd, int page) { StopTicks(); - // int frame_count = 0; - int response = 0; + int frame_count = 0; + uint32_t command_start = 0; + uint32_t command_duration = 0; + uint32_t response_start = 0; + uint32_t response_duration = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; uint8_t *tx = txbuf; size_t txlen = 0; - int lastbit; - int reset_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop; + int t_wait_1; + int t_wait_1_guard = 8; + int t_wait_2; + size_t tag_size; + bool bStop = false; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - set_tracing(true); - clear_trace(); + // Raw demodulation/decoding by sampling edge periods + size_t periods = 0; // Reset the return status bSuccessful = false; + bCrypto = false; + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + + DbpString("Starting Hitag writer family"); + // Check configuration switch (htf) { case WHT2F_CRYPTO: { @@ -1436,221 +1652,227 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } 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, LF_DIVISOR_125); //125kHz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - - // 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); - - 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, - // 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_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 - lastbit = 1; - bStop = false; - + // init as reader + lf_init(true); + // Tag specific configuration settings (sof, timings, etc.) if (htf < 10) { // hitagS settings - reset_sof = 1; - t_wait = 200; + t_wait_1 = 204; + t_wait_2 = 128; + /*tag_size = 256;*/ + flipped_bit = 0; + tag_size = 8; + DbpString("Configured for hitagS writer"); } else if (htf < 20) { - // hitag1 settings - reset_sof = 1; - t_wait = 200; + // hitag1 settings + t_wait_1 = 204; + t_wait_2 = 128; + tag_size = 256; + flipped_bit = 0; + DbpString("Configured for hitag1 writer"); } else if (htf < 30) { - // hitag2 settings - reset_sof = 4; - t_wait = HITAG_T_WAIT_2; + // hitag2 settings + t_wait_1 = HITAG_T_WAIT_1_MIN; + t_wait_2 = HITAG_T_WAIT_2_MIN; + tag_size = 48; + DbpString("Configured for hitag2 writer"); } else { - Dbprintf("Error, unknown hitag reader type: %d", htf); + Dbprintf("Error, unknown hitag writer type: %d", htf); return; } + uint8_t tag_modulation; + size_t max_nrzs = (8 * HITAG_FRAME_LEN + 5) * 2; // up to 2 nrzs per bit + uint8_t nrz_samples[max_nrzs]; + size_t nrzs = 0; + while (!bStop && !BUTTON_PRESS() && !data_available()) { WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - // frame_count++; - LogTrace(rx, nbytes(rxlen), response, response, NULL, false); - } - // By default reset the transmission buffer tx = txbuf; switch (htf) { case WHT2F_CRYPTO: { bStop = !hitag2_crypto(rx, rxlen, tx, &txlen, true); + break; } - break; case WHT2F_PASSWORD: { bStop = !hitag2_password(rx, rxlen, tx, &txlen, true); + break; } - break; default: { Dbprintf("Error, unknown function: %d", htf); - return; + goto out; } - break; } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occurred 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))) {}; + // Wait for t_wait_2 carrier periods after the last tag bit before transmitting, + lf_wait_periods(t_wait_2); + command_start += t_wait_2; // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + command_duration = hitag_reader_send_frame(tx, txlen); + + response_start = command_start + command_duration; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Let the antenna and ADC values settle + // And find the position where edge sampling should start + lf_wait_periods(t_wait_1 - t_wait_1_guard); + response_start += t_wait_1 - t_wait_1_guard; - // Add transmitted frame to total count + // Keep administration of the first edge detection + bool waiting_for_first_edge = true; + + // Did we detected any modulaiton at all + bool detected_tag_modulation = false; + + // Use the current modulation state as starting point + tag_modulation = lf_get_tag_modulation(); + + // Reset the number of NRZ samples and use edge detection to detect them + nrzs = 0; + while (nrzs < max_nrzs) { + // Get the timing of the next edge in number of wave periods + periods = lf_count_edge_periods(128); + + // Are we dealing with the first incoming edge + if (waiting_for_first_edge) { + // Just break out of loop after an initial time-out (tag is probably not available) + if (periods == 0) break; + if (tag_modulation == 0) { + // hitag replies always start with 11111 == 1010101010, if we see 0 + // it means we missed the first period, e.g. if the signal never crossed 0 since reader signal + // so let's add it: + nrz_samples[nrzs++] = tag_modulation ^ 1; + // Register the number of periods that have passed + // we missed the begin of response but we know it happened one period of 16 earlier + response_start += periods - 16; + response_duration = response_start; + } else { + // Register the number of periods that have passed + response_start += periods; + response_duration = response_start; + } + // Indicate that we have dealt with the first edge + waiting_for_first_edge = false; + // The first edge is always a single NRZ bit, force periods on 16 + periods = 16; + // We have received more than 0 periods, so we have detected a tag response + detected_tag_modulation = true; + } else { + // The function lf_count_edge_periods() returns 0 when a time-out occurs + if (periods == 0) { + //Dbprintf("Detected timeout after [%d] nrz samples", nrzs); + break; + } + } + // 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 __|) + nrz_samples[nrzs++] = tag_modulation; + nrz_samples[nrzs++] = tag_modulation; + response_duration += periods; + // Invert tag modulation state + tag_modulation ^= 1; + } else if (periods > 0 && periods <= 24) { + // Detected one bit and a modulation switch + // NRZ modulation: (1 => -|) or (0 _|) + nrz_samples[nrzs++] = tag_modulation; + response_duration += periods; + tag_modulation ^= 1; + } else { + // The function lf_count_edge_periods() returns > 64 periods, this is not a valid number periods + //Dbprintf("Detected unexpected period count: %d", periods); + break; + } + } + + // Wait some extra time for flash to be programmed + // + + // Store the TX frame, we do this now at this point, to avoid delay in processing + // and to be able to overwrite the first samples with the trace (since they currently + // still use the same memory space) if (txlen > 0) { - // frame_count++; - LogTrace(tx, nbytes(txlen), HITAG_T_WAIT_2, HITAG_T_WAIT_2, NULL, true); + frame_count++; + LogTrace(tx, nbytes(txlen), command_start, command_start + command_duration, NULL, true); } // Reset values for receiving frames memset(rx, 0x00, sizeof(rx)); rxlen = 0; - lastbit = 1; - bool bSkip = true; - int 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) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); + // If there is no response, just repeat the loop + if (!detected_tag_modulation) continue; - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - - LED_B_ON(); - - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //Dbprintf("DEBUG: 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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) { - 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) - - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - 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++; - } - } else { - // Dbprintf("DEBUG: Wierd2"); - errorCount++; - // Ignore wierd value, is to small to mean anything - } - } - // 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; - } + // Make sure we always have an even number of samples. This fixes the problem + // of ending the manchester decoding with a zero. See the example below where + // the '|' character is end of modulation + // One at the end: ..._-|_____... + // Zero at the end: ...-_|_____... + // The last modulation change of a zero is not detected, but we should take + // the half period in account, otherwise the demodulator will fail. + if ((nrzs % 2) != 0) { + nrz_samples[nrzs++] = tag_modulation; } - // Wait some extra time for flash to be programmed - if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) { - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_PROG - HITAG_T_WAIT_MAX)); + LED_B_ON(); + + // decode bitstream + manrawdecode((uint8_t *)nrz_samples, &nrzs, true, 0); + + // decode frame + + // Verify if the header consists of five consecutive ones + if (nrzs < 5) { + break; + } else { + size_t i; + for (i = 0; i < 5; i++) { + if (nrz_samples[i] != 1) { + Dbprintf("Detected incorrect header, the bit [%d] is zero instead of one, abort", i); + break; + } + } + if (i < 5) break; + } + + // Pack the response into a byte array + for (size_t i = 5; i < nrzs; i++) { + uint8_t bit = nrz_samples[i]; + if (bit > 1) { // When Manchester detects impossible symbol it writes "7" + break; + } + rx[rxlen / 8] |= bit << (7 - (rxlen % 8)); + rxlen++; + } + + if (rxlen % 8 == 1) // skip spurious bit + rxlen--; + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + + LogTrace(rx, nbytes(rxlen), response_start, response_start + response_duration, NULL, false); + command_start = 0; } } - 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; +out: + lf_finalize(); + Dbprintf("TX/RX frames recorded: %u", frame_count); + // release allocated memory from BigBuff. + BigBuf_free(); StartTicks(); - - reply_old(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, 48); + + reply_mix(CMD_ACK, bSuccessful, 0, 0, (uint8_t *)tag.sectors, tag_size); } diff --git a/armsrc/hitag2crack.c b/armsrc/hitag2crack.c new file mode 100644 index 000000000..c6b61b019 --- /dev/null +++ b/armsrc/hitag2crack.c @@ -0,0 +1,923 @@ +//----------------------------------------------------------------------------- +// Kevin Sheldrake , Aug 2018 +// +// 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. +// +// iceman, Jan, 2020 +// doegox, Jan, 2020 +//----------------------------------------------------------------------------- +// hitag2 attack functions +//----------------------------------------------------------------------------- + +#include "hitagcrypto.h" +#include "hitag2crack.h" + +#define READP0CMD "1100000111" +#define ERROR_RESPONSE "F402889C" + +extern const uint8_t Hitag2Sync[5]; +extern bool CryptoActive; +extern Hitag_State Hitag_Crypto_State; + +// hitag2_crack implements the first crack algorithm described in the paper, +// Gone In 360 Seconds by Verdult, Garcia and Balasch. +// response is a multi-line text response containing the 8 pages of the +// cracked tag; +// nrarhex is a string containing hex representations of the 32 bit nR and aR +// values (separated by a space) snooped using SNIFF-PWM. +bool hitag2_crack(uint8_t *response, uint8_t *nrarhex) { + uint8_t uidhex[9]; + uint8_t uid[32]; + uint8_t nrar[64]; + uint8_t e_firstcmd[10]; + uint8_t e_page0cmd[10]; + uint8_t keybits[42]; + uint8_t pagehex[9]; + uint8_t temp[20]; + int i; + uint8_t *spaceptr = NULL; + + // get uid as hexstring + if(!hitag2_get_uid(uidhex)) + { + UserMessage("Cannot get UID\r\n"); + return false; + } + + // convert uid hexstring to binarray + hextobinarray(uid, uidhex); + + // convert nR and aR hexstrings to binarray + spaceptr = strchr(nrarhex, ' '); + if (!spaceptr) + { + UserMessage("Please supply a valid nR aR pair\r\n"); + return false; + } + *spaceptr = 0x00; + + if (hextobinarray(nrar, nrarhex) != 32) + { + UserMessage("nR is not 32 bits long\r\n"); + return false; + } + + if (hextobinarray(nrar + 32, spaceptr + 1) != 32) + { + UserMessage("aR is not 32 bits long\r\n"); + return false; + } + + // find a valid encrypted command + if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) + { + UserMessage("Cannot find a valid encrypted command\r\n"); + return false; + } + + // find the 'read page 0' command and recover key stream + if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) + { + UserMessage("Cannot find encrypted 'read page0' command\r\n"); + return false; + } + + // empty the response string + response[0] = 0x00; + + // read all pages using key stream + for (i=0; i<8; i++) + { + if (hitag2crack_read_page(pagehex, i, nrar, keybits)) + { + sprintf(temp, "%1d: %s\r\n", i, pagehex); + } + else + { + sprintf(temp, "%1d:\r\n", i); + } + // add page string to response + strcat(response, temp); + } + + return true; +} + +// hitag2crack_find_valid_e_cmd repeatedly replays the auth protocol each +// with a different sequential encrypted command value in order to find one +// that returns a valid response. +// e_cmd is the returned binarray of the valid encrypted command; +// nrar is the binarray of the 64 bit nR aR pair. +bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]) { + uint8_t guess[10]; + uint8_t responsestr[9]; + +// UserMessage("Finding valid encrypted command:"); + // we're going to hold bits 5, 7, 8 and 9 and brute force the rest + // e.g. x x x x x 0 x 0 0 0 + for (uint8_t a=0; a<2; a++) { + for (uint8_t b=0; b<2; b++) { + for (uint8_t c=0; c<2; c++) { + for (uint8_t d=0; d<2; d++) { + for (uint8_t e=0; e<2; e++) { + for (uint8_t g=0; g<2; g++) { + // build binarray + guess[0] = a; + guess[1] = b; + guess[2] = c; + guess[3] = d; + guess[4] = e; + guess[5] = 0; + guess[6] = g; + guess[7] = 0; + guess[8] = 0; + guess[9] = 0; + + // send guess + if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) { + // check if it was valid + if (strcmp(responsestr, ERROR_RESPONSE) != 0) { + // return the guess as the encrypted command + memcpy(e_cmd, guess, 10); + return true; + } + } else { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_find_valid_e_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); +#endif + } + UserMessage("."); + } + } + } + } + } + } +// UserMessage("hitag2crack_find_valid_e_cmd:\r\n no valid encrypted command found\r\n"); + return false; +} + +// hitag2crack_find_e_page0_cmd tries all bit-flipped combinations of the +// valid encrypted command and tests the results by attempting an extended +// command version of the command to see if that produces a valid response. +// keybits is the returned binarray of the recovered key stream; +// e_page0cmd is the returned binarray of the encrypted 'read page 0' command; +// e_firstcmd is the binarray of the first valid encrypted command found; +// nrar is the binarray of the 64 bit nR aR pair; +// uid is the binarray of the 32 bit UID. +bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]) { + uint8_t a, b, c, d; + uint8_t guess[10]; + uint8_t responsestr[9]; + uint8_t e_uid[32]; + + UserMessage("Finding 'read page 0' command:"); + // we're going to brute the missing 4 bits of the valid encrypted command + for (a=0; a<2; a++) + { + for (b=0; b<2; b++) + { + for (c=0; c<2; c++) + { + for (d=0; d<2; d++) + { + // create our guess by bit flipping the pattern of bits + // representing the inverted bit and the 3 page bits + // in both the non-inverted and inverted parts of the + // encrypted command. + memcpy(guess, e_firstcmd, 10); + if (a) + { + guess[5] = !guess[5]; + guess[0] = !guess[0]; + } + if (b) + { + guess[7] = !guess[7]; + guess[2] = !guess[2]; + } + if (c) + { + guess[8] = !guess[8]; + guess[3] = !guess[3]; + } + if (d) + { + guess[9] = !guess[9]; + guess[4] = !guess[4]; + } + + // try the guess + if (hitag2crack_send_e_cmd(responsestr, nrar, guess, 10)) + { + // check if it was valid + if (strcmp(responsestr, ERROR_RESPONSE) != 0) + { + // convert response to binarray + hextobinarray(e_uid, responsestr); + // test if the guess was 'read page 0' command + if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) + { + + return true; + } + } + else + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); +#endif + } + } + else + { + #ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_find_e_page0_cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); +#endif + } + UserMessage("."); + } + } + } + } + UserMessage("hitag2crack_find_e_page0_cmd:\r\n could not find encrypted 'read page 0' command\r\n"); + return false; +} + +// hitag2crack_test_e_p0cmd XORs the message (command + response) with the +// encrypted version to retrieve the key stream. It then uses this key stream +// to encrypt an extended version of the READP0CMD and tests if the response +// is valid. +// keybits is the returned binarray of the key stream; +// nrar is the 64 bit binarray of nR aR pair; +// e_cmd is the binarray of the encrypted command; +// uid is the binarray of the card UID; +// e_uid is the binarray of the encrypted version of the UID. +bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid) { + uint8_t cipherbits[42]; + uint8_t plainbits[42]; + uint8_t ext_cmd[40]; + uint8_t e_ext_cmd[40]; + uint8_t responsestr[9]; + int i; + + // copy encrypted cmd to cipherbits + memcpy(cipherbits, e_cmd, 10); + + // copy encrypted uid to cipherbits + memcpy(cipherbits + 10, e_uid, 32); + + // copy cmd to plainbits + binstringtobinarray(plainbits, READP0CMD); + + // copy uid to plainbits + memcpy(plainbits + 10, uid, 32); + + // xor the plainbits with the cipherbits to get keybits + hitag2crack_xor(keybits, plainbits, cipherbits, 42); + + // create extended cmd -> 4 * READP0CMD = 40 bits + for (i=0; i<4; i++) + { + binstringtobinarray(ext_cmd + (i * 10), READP0CMD); + } + + // xor extended cmd with keybits + hitag2crack_xor(e_ext_cmd, ext_cmd, keybits, 40); + + // send extended encrypted cmd + if (hitag2crack_send_e_cmd(responsestr, nrar, e_ext_cmd, 40)) + { + // test if it was valid + if (strcmp(responsestr, ERROR_RESPONSE) != 0) + { + return true; + } + } + else + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_test_e_p0cmd:\r\n hitag2crack_send_e_cmd failed\r\n"); +#endif + } + + return false; + +} + +// hitag2crack_xor XORs the source with the pad to produce the target. +// source, target and pad are binarrays of length len. +void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len) { + + for (int i=0; i 7)) + { + UserMessage("hitag2crack_read_page:\r\n invalid pagenum\r\n"); + return false; + } + + // create cmd + binstringtobinarray(cmd, READP0CMD); + if (pagenum & 0x1) + { + cmd[9] = !cmd[9]; + cmd[4] = !cmd[4]; + } + if (pagenum & 0x2) + { + cmd[8] = !cmd[8]; + cmd[3] = !cmd[3]; + } + if (pagenum & 0x4) + { + cmd[7] = !cmd[7]; + cmd[2] = !cmd[2]; + } + + // encrypt command + hitag2crack_xor(e_cmd, cmd, keybits, 10); + + // send encrypted command + if (hitag2crack_send_e_cmd(e_responsestr, nrar, e_cmd, 10)) + { + // check if it is valid + if (strcmp(e_responsestr, ERROR_RESPONSE) != 0) + { + // convert to binarray + hextobinarray(e_response, e_responsestr); + // decrypt response + hitag2crack_xor(response, e_response, keybits + 10, 32); + // convert to hexstring + binarraytohex(responsestr, response, 32); + return true; + } + else + { + UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd returned ERROR_RESPONSE\r\n"); + } + } + else + { + UserMessage("hitag2crack_read_page:\r\n hitag2crack_send_e_cmd failed\r\n"); + } + + return false; +} + +// hitag2crack_send_e_cmd replays the auth and sends the given encrypted +// command. +// responsestr is the hexstring of the response to the command; +// nrar is the 64 bit binarray of the nR aR pair; +// cmd is the binarray of the encrypted command to send; +// len is the length of the encrypted command. +bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len) { + uint8_t tmp[37]; + uint8_t uid[9]; + uint8_t e_page3str[9]; + int ret = 0; + + // get the UID + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID\r\n"); + return false; + } + + // START_AUTH kills active crypto session + CryptoActive = false; + + // get the UID again + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_e_cmd:\r\n cannot get UID (2nd time)\r\n"); + return false; + } + + // send nrar and receive (useless) encrypted page 3 value + if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) + { + UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx nrar failed\r\n"); + return false; + } + + // send encrypted command + if (!hitag2crack_tx_rx(responsestr, cmd, len, RWD_STATE_WAKING, false)) + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_send_e_cmd:\r\n tx/rx cmd failed\r\n"); +#endif + return false; + } + + return true; +} + +// hitag2crack_tx_rx transmits a message and receives a response. +// responsestr is the hexstring of the response; +// msg is the binarray of the message to send; +// state is the RWD state; +// reset indicates whether to reset RWD state after. +bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset) { + uint8_t tmp[37]; + int ret = 0; + + // START_AUTH kills active crypto session + CryptoActive= false; + + if(!rwd_send(msg, len, reset, BLOCK, state, RFIDlerConfig.FrameClock, 0, RFIDlerConfig.RWD_Wait_Switch_RX_TX, RFIDlerConfig.RWD_Zero_Period, RFIDlerConfig.RWD_One_Period, RFIDlerConfig.RWD_Gap_Period, RFIDlerConfig.RWD_Wait_Switch_TX_RX)) + { + UserMessage("hitag2crack_tx_rx: rwd_send failed\r\n"); + return false; + } + + // skip 1/2 bit to synchronise manchester + HW_Skip_Bits = 1; + ret = read_ask_data(RFIDlerConfig.FrameClock, RFIDlerConfig.DataRate, tmp, 37, RFIDlerConfig.Sync, RFIDlerConfig.SyncBits, RFIDlerConfig.Timeout, ONESHOT_READ, BINARY); + + // check if response was a valid length (5 sync bits + 32 bits response) + if (ret == 37) + { + // check sync bits + if (memcmp(tmp, Hitag2Sync, 5) != 0) + { + UserMessage("hitag2crack_tx_rx: no sync\r\n"); + return false; + } + + // convert response to hexstring + binarraytohex(responsestr, tmp + 5, 32); + return true; + } + else + { +#ifdef RFIDLER_DEBUG + UserMessage("hitag2crack_tx_rx: wrong rx len\r\n"); +#endif + return false; + } + return false; +} + + +bool hitag2crack_rng_init(uint8_t *response, uint8_t *input) { + uint64_t sharedkey; + uint32_t serialnum; + uint32_t initvector; + uint8_t *spaceptr; + uint8_t *dataptr; + + // extract vals from input + dataptr = input; + spaceptr = strchr(dataptr, ' '); + if (!spaceptr) + { + UserMessage("/r/nformat is 'sharedkey UID nR' in hex\r\n"); + return false; + } + + *spaceptr = 0x00; + + if (strlen(dataptr) != 12) + { + UserMessage("/r/nsharedkey should be 48 bits long (12 hexchars)\r\n"); + return false; + } + + sharedkey = rev64(hexreversetoulonglong(dataptr)); + + dataptr = spaceptr+1; + spaceptr = strchr(dataptr, ' '); + if (!spaceptr) + { + UserMessage("/r/nno UID\r\n"); + return false; + } + + *spaceptr = 0x00; + if (strlen(dataptr) != 8) + { + UserMessage("/r/nUID should be 32 bits long (8 hexchars)\r\n"); + return false; + } + + serialnum = rev32(hexreversetoulong(dataptr)); + + dataptr = spaceptr+1; + + if (strlen(dataptr) != 8) + { + UserMessage("/r/nnR should be 32 bits long (8 hexchars)\r\n"); + return false; + } + + initvector = rev32(hexreversetoulong(dataptr)); + + // start up crypto engine + hitag2_init(&Hitag_Crypto_State, sharedkey, serialnum, initvector); + + strcpy(response, "Success\r\n"); + + return true; +} + +bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex) { + uint8_t bin[32]; + uint8_t binhex[9]; + uint8_t binstr[33]; + uint32_t binulong; + + if (strlen(hex) != 8) + { + UserMessage("/r/nhex must be 32bits (8 hex chars)\r\n"); + return false; + } + + binulong = hextoulong(hex); + + ulongtobinarray(bin, hitag2_crypt(binulong, 32), 32); + binarraytobinstring(binstr, bin, 32); + binarraytohex(binhex, bin, 32); +// UserMessage("ar = %s\r\n", binstr); +// UserMessage("arhex = %s\r\n", binhex); + + strcpy(response, binhex); + return true; +} + +bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *e_binstr) { + uint8_t bin[32]; + uint8_t e_bin[32]; + uint8_t binstr[33]; + uint32_t binulong; + int len; + + len = strlen(e_binstr); + if (len > 32) + { + UserMessage("\r\nbinary string must be <= 32 bits\r\n"); + return false; + } + + binstringtobinarray(e_bin, e_binstr); + binulong = binarraytoulong(e_bin, len); + + ulongtobinarray(bin, hitag2_crypt(binulong, len), len); + binarraytobinstring(binstr, bin, len); + strcpy(response, binstr); + return true; +} + +bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex) { + // XOR pad so encrypt == decrypt :) + return hitag2crack_decrypt_hex(response, hex); +} + +bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *e_binstr) { + return hitag2crack_decrypt_bin(response, e_binstr); +} + +// hitag2_keystream uses the first crack algorithm described in the paper, +// Gone In 360 Seconds by Verdult, Garcia and Balasch, to retrieve 2048 bits +// of keystream. +// response is a multi-line text response containing the hex of the keystream; +// nrarhex is a string containing hex representations of the 32 bit nR and aR +// values (separated by a space) snooped using SNIFF-PWM. +bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex) { + uint8_t uidhex[9]; + uint8_t uid[32]; + uint8_t nrar[64]; + uint8_t e_firstcmd[10]; + uint8_t e_page0cmd[10]; +// uint8_t keybits[2080]; + uint8_t *keybits = DataBuff; + uint8_t keybitshex[67]; + int kslen; + int ksoffset; + uint8_t pagehex[9]; + uint8_t temp[20]; + int i; + uint8_t *spaceptr = NULL; + +/* + keybits = malloc(2080); + if (!keybits) { + UserMessage("cannot malloc keybits\r\n"); + return false; + } +*/ + + // get uid as hexstring + if(!hitag2_get_uid(uidhex)) + { + UserMessage("Cannot get UID\r\n"); + return false; + } + + // convert uid hexstring to binarray + hextobinarray(uid, uidhex); + + // convert nR and aR hexstrings to binarray + spaceptr = strchr(nrarhex, ' '); + if (!spaceptr) + { + UserMessage("Please supply a valid nR aR pair\r\n"); + return false; + } + *spaceptr = 0x00; + + if (hextobinarray(nrar, nrarhex) != 32) + { + UserMessage("nR is not 32 bits long\r\n"); + return false; + } + + if (hextobinarray(nrar + 32, spaceptr + 1) != 32) + { + UserMessage("aR is not 32 bits long\r\n"); + return false; + } + + // find a valid encrypted command + if (!hitag2crack_find_valid_e_cmd(e_firstcmd, nrar)) + { + UserMessage("Cannot find a valid encrypted command\r\n"); + return false; + } + + // find the 'read page 0' command and recover key stream + if (!hitag2crack_find_e_page0_cmd(keybits, e_firstcmd, nrar, uid)) + { + UserMessage("Cannot find encrypted 'read page0' command\r\n"); + return false; + } + + // using the 40 bits of keystream in keybits, sending commands with ever + // increasing lengths to acquire 2048 bits of key stream. + kslen = 40; + + while (kslen < 2048) + { + ksoffset = 0; + if (!hitag2crack_send_auth(nrar)) + { + UserMessage("hitag2crack_send_auth failed\r\n"); + return false; + } + // while we have at least 52 bits of keystream, consume it with + // extended read page 0 commands. 52 = 10 (min command len) + + // 32 (response) + 10 (min command len we'll send) + while ((kslen - ksoffset) >= 52) + { + // consume the keystream, updating ksoffset as we go + if (!hitag2crack_consume_keystream(keybits, kslen, &ksoffset, nrar)) + { + UserMessage("hitag2crack_consume_keystream failed\r\n"); + return false; + } + } + // send an extended command to retrieve more keystream, updating kslen + // as we go + if (!hitag2crack_extend_keystream(keybits, &kslen, ksoffset, nrar, uid)) + { + UserMessage("hitag2crack_extend_keystream failed\r\n"); + return false; + } + UserMessage("Recovered %d bits of keystream\r\n", kslen); + + } + + for (i=0; i<2048; i+=256) + { + binarraytohex(keybitshex, keybits + i, 256); + UserMessage("%s\r\n", keybitshex); + } + + response[0] = 0x00; + + return true; +} + +// hitag2crack_send_auth replays the auth and returns. +// nrar is the 64 bit binarray of the nR aR pair; +bool hitag2crack_send_auth(uint8_t *nrar) { + uint8_t uid[9]; + uint8_t e_page3str[9]; + + // get the UID + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_auth:\r\n cannot get UID\r\n"); + return false; + } + + // START_AUTH kills active crypto session + CryptoActive = false; + + // get the UID again + if(!hitag2_get_uid(uid)) + { + UserMessage("hitag2crack_send_auth:\r\n cannot get UID (2nd time)\r\n"); + return false; + } + + // send nrar and receive (useless) encrypted page 3 value + if (!hitag2crack_tx_rx(e_page3str, nrar, 64, RWD_STATE_WAKING, false)) + { + UserMessage("hitag2crack_send_auth:\r\n tx/rx nrar failed\r\n"); + return false; + } + return true; +} + +// hitag2crack_consume_keystream sends an extended command (up to 510 bits in +// length) to consume keystream. +// keybits is the binarray of keystream bits; +// kslen is the length of keystream; +// ksoffset is a pointer to the current keystream offset (updated by this fn); +// nrar is the 64 bit binarray of the nR aR pair. +bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar) { + int conlen; + int numcmds; + int i; + uint8_t ext_cmd[510]; + uint8_t e_ext_cmd[510]; + uint8_t responsestr[9]; + + // calculate the length of keybits to consume with the extended command. + // 42 = 32 bit response + 10 bit command reserved for next command. conlen + // cannot be longer than 510 bits to fit into the small RWD buffer. + conlen = kslen - *ksoffset - 42; + if (conlen < 10) + { + UserMessage("hitag2crack_consume_keystream:\r\n conlen < 10\r\n"); + return false; + } + + // sanitise conlen + if (conlen > 510) + { + conlen = 510; + } + + // calculate how many repeated commands to send in this extended command. + numcmds = conlen / 10; + + // build extended command + for (i=0; i, Aug 2018 +// +// 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. +//----------------------------------------------------------------------------- +// Definitions hitag2 attack functions +//----------------------------------------------------------------------------- + +bool hitag2_crack(uint8_t *response, uint8_t *nrarhex); +bool hitag2crack_find_valid_e_cmd(uint8_t e_cmd[], uint8_t nrar[]); +bool hitag2crack_find_e_page0_cmd(uint8_t keybits[], uint8_t e_firstcmd[], uint8_t nrar[], uint8_t uid[]); +bool hitag2crack_test_e_p0cmd(uint8_t *keybits, uint8_t *nrar, uint8_t *e_cmd, uint8_t *uid, uint8_t *e_uid); +void hitag2crack_xor(uint8_t *target, uint8_t *source, uint8_t *pad, unsigned int len); +bool hitag2crack_read_page(uint8_t *responsestr, uint8_t pagenum, uint8_t *nrar, uint8_t *keybits); +bool hitag2crack_send_e_cmd(uint8_t *responsestr, uint8_t *nrar, uint8_t *cmd, int len); +bool hitag2crack_tx_rx(uint8_t *responsestr, uint8_t *msg, int len, int state, bool reset); + +bool hitag2crack_rng_init(uint8_t *response, uint8_t *input); +bool hitag2crack_decrypt_hex(uint8_t *response, uint8_t *hex); +bool hitag2crack_decrypt_bin(uint8_t *response, uint8_t *hex); +bool hitag2crack_encrypt_hex(uint8_t *response, uint8_t *hex); +bool hitag2crack_encrypt_bin(uint8_t *response, uint8_t *hex); + +bool hitag2_keystream(uint8_t *response, uint8_t *nrarhex); +bool hitag2crack_send_auth(uint8_t *nrar); +bool hitag2crack_consume_keystream(uint8_t *keybits, int kslen, int *ksoffset, uint8_t *nrar); +bool hitag2crack_extend_keystream(uint8_t *keybits, int *kslen, int ksoffset, uint8_t *nrar, uint8_t *uid); + +bool hitag2_reader(uint8_t *response, uint8_t *key, bool interactive); diff --git a/armsrc/lfadc.c b/armsrc/lfadc.c index d59fae07d..3e15fdc0b 100644 --- a/armsrc/lfadc.c +++ b/armsrc/lfadc.c @@ -22,7 +22,7 @@ // as a counting signal. TIMER_CLOCK3 = MCK/32, MCK is running at 48 MHz, so the timer is running at 48/32 = 1500 kHz // Carrier period (T0) have duration of 8 microseconds (us), which is 1/125000 per second (125 kHz frequency) // T0 = timer/carrier = 1500kHz/125kHz = 1500000/125000 = 6 -#define T0 3 +//#define HITAG_T0 3 ////////////////////////////////////////////////////////////////////////////// // Global variables @@ -52,16 +52,28 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { volatile uint8_t adc_val; //uint8_t avg_peak = 140, avg_through = 96; uint8_t avg_peak = 130, avg_through = 106; + int16_t checked = 0; + + while (true) { + + // only every 1000th times, in order to save time when collecting samples. + if (checked == 1000) { + if (BUTTON_PRESS() || data_available()) { + checked = -1; + break; + } else { + checked = 0; + } + } + ++checked; - while (!BUTTON_PRESS()) { - // Watchdog hit WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { adc_val = AT91C_BASE_SSC->SSC_RHR; periods++; - if (logging) logSample(adc_val, 1, 8, 0); + if (logging) logSampleSimple(adc_val); // Only test field changes if state of adc values matter if (!wait) { @@ -91,7 +103,7 @@ size_t lf_count_edge_periods_ex(size_t max, bool wait, bool detect_gap) { if (periods == max) return 0; } } - if (logging) logSample(255, 1, 8, 0); + if (logging) logSampleSimple(0xFF); return 0; } @@ -143,7 +155,11 @@ void lf_init(bool reader) { FpgaSetupSsc(); // When in reader mode, give the field a bit of time to settle. - if (reader) SpinDelay(50); + // 313T0 = 313 * 8us = 2504us = 2.5ms Hitag2 tags needs to be fully powered. + if (reader) { + // 50 ms + SpinDelay(50); + } // Steal this pin from the SSP (SPI communication channel with fpga) and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; @@ -168,7 +184,9 @@ void lf_init(bool reader) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Prepare data trace - if (logging) initSampleBuffer(NULL); + uint32_t bufsize = 20000; + + if (logging) initSampleBuffer(&bufsize); } @@ -204,14 +222,13 @@ size_t lf_detect_field_drop(size_t max) { } ++checked; - // Watchdog hit WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { periods++; adc_val = AT91C_BASE_SSC->SSC_RHR; - if (logging) logSample(adc_val, 1, 8, 0); + if (logging) logSampleSimple(adc_val); if (adc_val == 0) { rising_edge = false; diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 5808fff07..2d92cd692 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -93,6 +93,7 @@ sample_config *getSamplingConfig() { void pushBit(BitstreamOut *stream, uint8_t bit) { int bytepos = stream->position >> 3; // divide by 8 int bitpos = stream->position & 7; + *(stream->buffer + bytepos) &= ~(1 << (7 - bitpos)); *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos); stream->position++; stream->numbits++; @@ -106,17 +107,25 @@ sampling_t samples = {0, 0, 0, 0}; void initSampleBuffer(uint32_t *sample_size) { + BigBuf_free(); +// We can't erase the buffer now, it would drastically delay the acquisition +// BigBuf_Clear_ext(false); + if (sample_size == NULL || *sample_size == 0) { *sample_size = BigBuf_max_traceLen(); - } else { - *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); - } - // use a bitstream to handle the output - data.buffer = BigBuf_get_addr(); + data.buffer = BigBuf_get_addr(); // We can't erase the buffer now, it would drastically delay the acquisition -// memset(data.buffer, 0, *sample_size); +// memset(data.buffer, 0, *sample_size); + } else { + *sample_size = MIN(*sample_size, BigBuf_max_traceLen()); + + data.buffer = BigBuf_malloc(*sample_size); + +// We can't erase the buffer now, it would drastically delay the acquisition +// memset(data.buffer, 0, *sample_size); + } // samples.dec_counter = 0; @@ -129,6 +138,10 @@ uint32_t getSampleCounter() { return samples.total_saved; } +void logSampleSimple(uint8_t sample) { + logSample(sample, config.decimation, config.bits_per_sample, config.averaging); +} + void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg) { if (!data.buffer) return; diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index e97a3ac1a..cd3a8993e 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -70,6 +70,7 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size); * Refactoring of lf sampling buffer */ void initSampleBuffer(uint32_t *sample_size); +void logSampleSimple(uint8_t sample); void logSample(uint8_t sample, uint8_t decimation, uint8_t bits_per_sample, bool avg); uint32_t getSampleCounter(); diff --git a/client/cmdflashmemspiffs.c b/client/cmdflashmemspiffs.c index 492fc0bcc..5d003bd2c 100644 --- a/client/cmdflashmemspiffs.c +++ b/client/cmdflashmemspiffs.c @@ -314,11 +314,69 @@ static int CmdFlashMemSpiFFSDump(const char *Cmd) { return PM3_SUCCESS; } +int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen) { + + int ret_val = PM3_SUCCESS; + + // We want to mount before multiple operation so the lazy writes/append will not + // trigger a mount + umount each loop iteration (lazy ops device side) + SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); + + // Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = datalen; + uint32_t append = 0; + + // fast push mode + conn.block_after_ACK = true; + + while (bytes_remaining > 0) { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + clearCommandBuffer(); + + char fdata[32 + bytes_in_packet]; + memset(fdata, 0, sizeof(fdata)); + memcpy(fdata, destfn, 32); + memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); + + if (bytes_sent > 0) + append = 1; + + SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + + PacketResponseNG resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + ret_val = PM3_ETIMEOUT; + break; + } + + uint8_t isok = resp.oldarg[0] & 0xFF; + if (!isok) { + PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + ret_val = PM3_EFLASH; + break; + } + } + + // turn off fast push mode + conn.block_after_ACK = false; + + // We want to unmount after these to set things back to normal but more than this + // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory + SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); + + return ret_val; +} + static int CmdFlashMemSpiFFSLoad(const char *Cmd) { - uint32_t append = 0; char filename[FILE_PATH_SIZE] = {0}; - char destfilename[32] = {0}; + uint8_t destfilename[32] = {0}; bool errors = false; uint8_t cmdp = 0; @@ -334,8 +392,8 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { cmdp += 2; break; case 'o': - param_getstr(Cmd, cmdp + 1, destfilename, 32); - if (strlen(destfilename) == 0) { + param_getstr(Cmd, cmdp + 1, (char*)destfilename, 32); + if (strlen((char*)destfilename) == 0) { PrintAndLogEx(FAILED, "Destination Filename missing or invalid"); errors = true; } @@ -362,63 +420,14 @@ static int CmdFlashMemSpiFFSLoad(const char *Cmd) { return PM3_EFILE; } - // We want to mount before multiple operation so the lazy writes/append will not - // trigger a mount + umount each loop iteration (lazy ops device side) - SendCommandNG(CMD_SPIFFS_MOUNT, NULL, 0); - - // Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = datalen; - - // fast push mode - conn.block_after_ACK = true; - - // SendCommandMIX(CMD_SPIFFS_COPY, 0, 0, 0, (uint8_t *)data, 65); - - while (bytes_remaining > 0) { - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - - clearCommandBuffer(); - - char fdata[32 + bytes_in_packet]; - memset(fdata, 0, sizeof(fdata)); - memcpy(fdata, destfilename, 32); - memcpy(fdata + 32, data + bytes_sent, bytes_in_packet); - // sprintf(fdata, "%s%s", destfilename, data + bytes_sent); - - if (bytes_sent > 0) - append = 1; - - SendCommandOLD(CMD_SPIFFS_WRITE, append, bytes_in_packet, 0, fdata, 32 + bytes_in_packet); - - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; - - PacketResponseNG resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - conn.block_after_ACK = false; - free(data); - return PM3_ETIMEOUT; - } - - uint8_t isok = resp.oldarg[0] & 0xFF; - if (!isok) { - conn.block_after_ACK = false; - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - free(data); - return PM3_EFLASH; - } - } - - conn.block_after_ACK = false; + res = flashmem_spiffs_load(destfilename, data, datalen); + free(data); - PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); - - // We want to unmount after these to set things back to normal but more than this - // unmouting ensure that SPIFFS CACHES are all flushed so our file is actually written on memory - SendCommandNG(CMD_SPIFFS_UNMOUNT, NULL, 0); - return PM3_SUCCESS; + + if ( res == PM3_SUCCESS ) + PrintAndLogEx(SUCCESS, "Wrote "_GREEN_("%zu") "bytes to file "_GREEN_("%s"), datalen, destfilename); + + return res; } static command_t CommandTable[] = { diff --git a/client/cmdflashmemspiffs.h b/client/cmdflashmemspiffs.h index d2dee17ab..9324a541b 100644 --- a/client/cmdflashmemspiffs.h +++ b/client/cmdflashmemspiffs.h @@ -14,5 +14,6 @@ #include "common.h" int CmdFlashMemSpiFFS(const char *Cmd); +int flashmem_spiffs_load(uint8_t *destfn, uint8_t *data, size_t datalen); #endif diff --git a/client/cmdhf.c b/client/cmdhf.c index 52ad853fa..e90f2ea28 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -85,8 +85,6 @@ int CmdHFSearch(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_search(); - PrintAndLogEx(INFO, "Checking for known tags..."); - PROMPT_CLEARLINE; PrintAndLogEx(INPLACE, "Searching for ThinFilm tag..."); if (IfPm3NfcBarcode()) { @@ -170,9 +168,8 @@ int CmdHFSearch(const char *Cmd) { } PROMPT_CLEARLINE; - PrintAndLogEx(INPLACE, "done"); + PrintAndLogEx(INPLACE, _RED_("No known/supported 13.56 MHz tags found")); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(FAILED, _RED_("No known/supported 13.56 MHz tags found")); return PM3_ESOFT; } @@ -272,15 +269,16 @@ static command_t CommandTable[] = { {"15", CmdHF15, AlwaysAvailable, "{ ISO15693 RFIDs... }"}, {"epa", CmdHFEPA, AlwaysAvailable, "{ German Identification Card... }"}, {"felica", CmdHFFelica, AlwaysAvailable, "{ ISO18092 / Felica RFIDs... }"}, - {"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"}, + {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, {"iclass", CmdHFiClass, AlwaysAvailable, "{ ICLASS RFIDs... }"}, + {"legic", CmdHFLegic, AlwaysAvailable, "{ LEGIC RFIDs... }"}, + {"lto", CmdHFLTO, AlwaysAvailable, "{ LTO Cartridge Memory RFIDs... }"}, {"mf", CmdHFMF, AlwaysAvailable, "{ MIFARE RFIDs... }"}, {"mfp", CmdHFMFP, AlwaysAvailable, "{ MIFARE Plus RFIDs... }"}, {"mfu", CmdHFMFUltra, AlwaysAvailable, "{ MIFARE Ultralight RFIDs... }"}, {"mfdes", CmdHFMFDes, AlwaysAvailable, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, - {"fido", CmdHFFido, AlwaysAvailable, "{ FIDO and FIDO2 authenticators... }"}, {"thinfilm", CmdHFThinfilm, AlwaysAvailable, "{ Thinfilm RFIDs... }"}, + {"topaz", CmdHFTopaz, AlwaysAvailable, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"list", CmdTraceList, AlwaysAvailable, "List protocol data in trace buffer"}, {"plot", CmdHFPlot, IfPm3Hfplot, "Plot signal"}, {"tune", CmdHFTune, IfPm3Present, "Continuously measure HF antenna tuning"}, diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index ae1109717..616f5e2e2 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2805,6 +2805,7 @@ int readIclass(bool loop, bool verbose) { FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; + uint32_t res = PM3_ETIMEOUT; // loop in client not device - else on windows have a communication error while (!kbd_enter_pressed()) { @@ -2876,6 +2877,6 @@ int readIclass(bool loop, bool verbose) { if (!loop) break; } DropField(); - return PM3_SUCCESS; + return res; } diff --git a/client/cmdhflist.c b/client/cmdhflist.c index c9d0f2bb7..2fde8492c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -1101,10 +1101,10 @@ void annotateLTO(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { snprintf(exp, size, "REQ Standard"); break; case LTO_SELECT: - snprintf(exp, size, "SELECT"); - break; - case LTO_SELECT_1: - snprintf(exp, size, "SELECT_1"); + if (cmd[1] == 0x70) + snprintf(exp, size, "SELECT_UID-2"); + else if (cmd[1] == 0x20) + snprintf(exp, size, "SELECT"); break; case LTO_REQ_ALL: snprintf(exp, size, "REQ All"); diff --git a/client/cmdhflto.c b/client/cmdhflto.c index 8a1e914aa..39e9cf30b 100644 --- a/client/cmdhflto.c +++ b/client/cmdhflto.c @@ -42,9 +42,17 @@ static void lto_switch_on_field(void) { } // send a raw LTO-CM command, returns the length of the response (0 in case of error) -static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool verbose) { +static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16_t *response_len, bool addcrc, bool verbose) { - SendCommandOLD(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, len, 0, cmd, len); + uint64_t arg0 = ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS; + uint32_t arg1 = (len == 1) ? (7 << 16) : 0; + arg1 |= len; + + if (addcrc) { + arg0 |= ISO14A_APPEND_CRC; + } + + SendCommandOLD(CMD_HF_ISO14443A_READER, arg0, arg1, 0, cmd, len); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { @@ -55,7 +63,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 if (resp.oldarg[0] == *response_len) { *response_len = resp.oldarg[0]; - PrintAndLogEx(INFO, "%s", sprint_hex(resp.data.asBytes, *response_len)); if (*response_len > 0) { memcpy(response, resp.data.asBytes, *response_len); } @@ -66,7 +73,6 @@ static int lto_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response, uint16 return PM3_SUCCESS; } - // select a LTO-CM tag. Send WUPA and RID. static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { // Todo: implement anticollision @@ -75,26 +81,27 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { uint16_t resp_len; uint8_t wupa_cmd[] = {LTO_REQ_STANDARD}; uint8_t select_cmd[] = {LTO_SELECT, 0x20}; - uint8_t select_1_cmd[] = {LTO_SELECT_1, 0x70, 0, 0, 0, 0, 0}; + uint8_t select_1_cmd[] = {LTO_SELECT, 0x70, 0, 0, 0, 0, 0}; lto_switch_on_field(); resp_len = 2; - int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, verbose); + int status = lto_send_cmd_raw(wupa_cmd, sizeof(wupa_cmd), resp, &resp_len, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { lto_switch_off_field(); return PM3_ESOFT; // WUPA failed } resp_len = id_len; - status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, verbose); + status = lto_send_cmd_raw(select_cmd, sizeof(select_cmd), id_response, &resp_len, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { lto_switch_off_field(); return PM3_EWRONGANSVER; // SELECT failed } + memcpy(select_1_cmd + 2, id_response, sizeof(select_1_cmd) - 2); resp_len = 1; - status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, verbose); + status = lto_send_cmd_raw(select_1_cmd, sizeof(select_1_cmd), resp, &resp_len, true, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT || resp[0] != 0x0A) { lto_switch_off_field(); return PM3_EWRONGANSVER; // SELECT failed @@ -104,7 +111,6 @@ static int lto_select(uint8_t *id_response, uint8_t id_len, bool verbose) { return PM3_SUCCESS; } - static int CmdHfLTOInfo(const char *Cmd) { uint8_t cmdp = 0; @@ -126,7 +132,7 @@ static int CmdHfLTOInfo(const char *Cmd) { return PM3_EINVARG; } - return infoLTO(true); + return infoLTO(false); } int infoLTO(bool verbose) { @@ -134,18 +140,20 @@ int infoLTO(bool verbose) { clearCommandBuffer(); uint8_t serial_number[5]; - uint8_t serial_len = 0; - + uint8_t serial_len = sizeof(serial_number); int ret_val = lto_select(serial_number, serial_len, verbose); - lto_switch_off_field(); - /* - -- "hf 14a raw -a -p -b 7 45" - -- "hf 14a raw -c -p 9320" - -- "hf 14a raw -c -p 9370%s", serial_number - -- "disconnect" + if (ret_val == PM3_SUCCESS) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, " UID : " _YELLOW_("%s"), sprint_hex_inrow(serial_number, sizeof(serial_number))); + PrintAndLogEx(SUCCESS, "TYPE : "); + // todo: add printing of all configuration + } else { + if (verbose) PrintAndLogEx(WARNING, "LTO-CM card select failed"); + } + /* read block: SendCommandNG(CMD_HF_THINFILM_READ, NULL, 0); PacketResponseNG resp; diff --git a/client/cmdlf.c b/client/cmdlf.c index 48f1cd235..617d87c0e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -339,7 +339,7 @@ int CmdLFCommandRead(const char *Cmd) { // bitbang mode if (payload.delay == 0) { if (payload.zeros < 7 || payload.ones < 7) { - PrintAndLogEx(WARNING, "Warning periods cannot be less than 7us in bit bang mode"); + PrintAndLogEx(WARNING, "warning periods cannot be less than 7us in bit bang mode"); return PM3_EINVARG; } } @@ -347,15 +347,14 @@ int CmdLFCommandRead(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_lf_cmdread(); - PrintAndLogEx(SUCCESS, "Sending"); + PrintAndLogEx(SUCCESS, "sending"); clearCommandBuffer(); SendCommandNG(CMD_LF_MOD_THEN_ACQ_RAW_ADC, (uint8_t *)&payload, 8 + datalen); - printf("\n"); - PacketResponseNG resp; uint8_t i = 10; + // 20sec wait loop while (!WaitForResponseTimeout(CMD_LF_MOD_THEN_ACQ_RAW_ADC, &resp, 2000) && i != 0) { printf("."); fflush(stdout); @@ -365,15 +364,15 @@ int CmdLFCommandRead(const char *Cmd) { if (resp.status == PM3_SUCCESS) { if (i) { - PrintAndLogEx(SUCCESS, "Downloading response signal data"); - getSamples(0, false); + PrintAndLogEx(SUCCESS, "downloading response signal data"); + getSamples(0, true); return PM3_SUCCESS; } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return PM3_ETIMEOUT; } } - PrintAndLogEx(WARNING, "Command failed."); + PrintAndLogEx(WARNING, "command failed."); return PM3_ESOFT; } @@ -1214,17 +1213,18 @@ int CmdLFfind(const char *Cmd) { // only run these tests if device is online if (isOnline) { + + if (IfPm3Hitag()) { + if (readHitagUid()) { + PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!"); + return PM3_SUCCESS; + } + } + // only run if graphbuffer is just noise as it should be for hitag // The improved noise detection will find Cotag. if (getSignalProperties()->isnoise) { - if (IfPm3Hitag()) { - if (readHitagUid()) { - PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Hitag") "found!"); - return PM3_SUCCESS; - } - } - if (readMotorolaUid()) { PrintAndLogEx(SUCCESS, "\nValid " _GREEN_("Motorola FlexPass ID") "found!"); return PM3_SUCCESS; diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 40e909024..f0a8037dc 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -18,6 +18,7 @@ #include "commonutil.h" #include "hitag.h" #include "fileutils.h" // savefile +#include "protocols.h" // defines static int CmdHelp(const char *Cmd); @@ -35,7 +36,7 @@ static int usage_hitag_sniff(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag sniff"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_sim(void) { PrintAndLogEx(NORMAL, "Simulate " _YELLOW_("Hitag2 / HitagS")" transponder"); @@ -49,7 +50,7 @@ static int usage_hitag_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag sim 2 b lf-hitag-dump"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_info(void) { PrintAndLogEx(NORMAL, "Usage: lf hitag info [h] p "); @@ -58,7 +59,7 @@ static int usage_hitag_info(void) { PrintAndLogEx(NORMAL, " p password"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag info"); - return 0; + return PM3_SUCCESS; } /* static int usage_hitag_dump(void) { @@ -71,7 +72,7 @@ static int usage_hitag_dump(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag dump f mydump"); PrintAndLogEx(NORMAL, " lf hitag dump p 4D494B52 f mydump"); - return 0; + return PM3_SUCCESS; } */ static int usage_hitag_reader(void) { @@ -85,12 +86,12 @@ static int usage_hitag_reader(void) { PrintAndLogEx(NORMAL, " Hitag1 (1*)"); PrintAndLogEx(NORMAL, " Not implemented"); PrintAndLogEx(NORMAL, " Hitag2 (2*)"); - PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: 4D494B52 (\"MIKR\")"); + PrintAndLogEx(NORMAL, " 21 Read all pages, password mode. Default: " _YELLOW_("4D494B52") "(\"MIKR\")"); PrintAndLogEx(NORMAL, " 22 Read all pages, challenge mode"); - PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: 4F4E4D494B52 (\"ONMIKR\")"); + PrintAndLogEx(NORMAL, " 23 Read all pages, crypto mode. Key format: ISK high + ISK low. Default: " _YELLOW_("4F4E4D494B52") "(\"ONMIKR\")"); PrintAndLogEx(NORMAL, " 25 Test recorded authentications"); PrintAndLogEx(NORMAL, " 26 Just read UID"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, "Hitag writer functions"); @@ -106,7 +107,7 @@ static int usage_hitag_writer(void) { PrintAndLogEx(NORMAL, " 24 Write page, crypto mode. Key format: ISK high + ISK low."); PrintAndLogEx(NORMAL, " Default: 4F4E4D494B52 (\"ONMIKR\"). Set key=0 for no auth"); PrintAndLogEx(NORMAL, " 27 Write page, password mode. Default: 4D494B52 (\"MIKR\")"); - return 0; + return PM3_SUCCESS; } static int usage_hitag_checkchallenges(void) { PrintAndLogEx(NORMAL, "Check challenges, load a file with save hitag crypto challenges and test them all."); @@ -119,19 +120,19 @@ static int usage_hitag_checkchallenges(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hitag cc f lf-hitag-challenges"); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagList(const char *Cmd) { (void)Cmd; // Cmd is not used so far - CmdTraceList("hitag"); - return 0; + CmdTraceList("hitag2"); + return PM3_SUCCESS; /* uint8_t *got = calloc(PM3_CMD_DATA_SIZE, sizeof(uint8_t)); if (!got) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); - return 2; + return PM3_EMALLOC; } // Query for the actual size of the trace @@ -139,7 +140,7 @@ static int CmdLFHitagList(const char *Cmd) { if (!GetFromDevice(BIG_BUF, got, PM3_CMD_DATA_SIZE, 0, NULL, 0, &response, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); - return 2; + return PM3_ETIMEOUT; } uint16_t traceLen = response.arg[2]; @@ -148,13 +149,13 @@ static int CmdLFHitagList(const char *Cmd) { if (p == NULL) { PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); free(got); - return 2; + return PM3_EMALLOC; } got = p; if (!GetFromDevice(BIG_BUF, got, traceLen, 0, NULL, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "command execution time out"); free(got); - return 2; + return PM3_ETIMEOUT; } } @@ -251,7 +252,7 @@ static int CmdLFHitagList(const char *Cmd) { } free(got); - return 0; + return PM3_SUCCES; */ } @@ -262,7 +263,7 @@ static int CmdLFHitagSniff(const char *Cmd) { clearCommandBuffer(); SendCommandNG(CMD_LF_HITAG_SNIFF, NULL, 0); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagSim(const char *Cmd) { @@ -343,7 +344,7 @@ static int CmdLFHitagSim(const char *Cmd) { } free(data); - return 0; + return PM3_SUCCESS; } static void printHitagConfiguration(uint8_t config) { @@ -483,21 +484,20 @@ static int CmdLFHitagInfo(const char *Cmd) { // read UID uint32_t uid = 0; if (getHitagUid(&uid) == false) - return 1; + return PM3_ESOFT; - PrintAndLogEx(SUCCESS, "UID: %08X", uid); + PrintAndLogEx(SUCCESS, "UID: " _YELLOW_("%08X"), uid); // how to detemine Hitag types? // read block3, get configuration byte. - PrintAndLogEx(FAILED, _RED_("TODO: This is a hardcoded example!")); // common configurations. - printHitagConfiguration(0x06); + // printHitagConfiguration(0x06); //printHitagConfiguration( 0x0E ); //printHitagConfiguration( 0x02 ); //printHitagConfiguration( 0x00 ); //printHitagConfiguration( 0x04 ); - return 0; + return PM3_SUCCESS; } // TODO: iceman @@ -550,21 +550,22 @@ static int CmdLFHitagReader(const char *Cmd) { } clearCommandBuffer(); - SendCommandOLD(cmd, htf, 0, 0, &htd, sizeof(htd)); + SendCommandMIX(cmd, htf, 0, 0, &htd, sizeof(htd)); PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return PM3_ETIMEOUT; } if (resp.oldarg[0] == false) { PrintAndLogEx(DEBUG, "DEBUG: Error - hitag failed"); - return 1; + return PM3_ESOFT; } uint32_t id = bytes_to_num(resp.data.asBytes, 4); - PrintAndLogEx(SUCCESS, "Valid Hitag2 tag found - UID: %08x", id); + PrintAndLogEx(SUCCESS, " UID: " _YELLOW_("%08x"), id); + if (htf != RHT2F_UID_ONLY) { PrintAndLogEx(SUCCESS, "Dumping tag memory..."); @@ -575,6 +576,8 @@ static int CmdLFHitagReader(const char *Cmd) { fnameptr += sprintf(fnameptr, "lf-hitag-"); FillFileNameByUID(fnameptr, data, "-dump", 4); + + saveFile(filename, ".bin", data, 48); saveFileEML(filename, data, 48, 4); saveFileJSON(filename, jsfHitag, data, 48); @@ -582,7 +585,7 @@ static int CmdLFHitagReader(const char *Cmd) { // block3, 1 byte printHitagConfiguration(data[4 * 3]); } - return 0; + return PM3_SUCCESS; } static int CmdLFHitagCheckChallenges(const char *Cmd) { @@ -631,7 +634,7 @@ static int CmdLFHitagCheckChallenges(const char *Cmd) { SendCommandMIX(CMD_LF_HITAGS_TEST_TRACES, 0, 0, 0, NULL, 0); free(data); - return 0; + return PM3_SUCCESS; } static int CmdLFHitagWriter(const char *Cmd) { @@ -675,14 +678,14 @@ static int CmdLFHitagWriter(const char *Cmd) { PacketResponseNG resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return PM3_ETIMEOUT; } if (resp.oldarg[0] == false) { PrintAndLogEx(DEBUG, "DEBUG: Error - hitag write failed"); - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } /* @@ -692,10 +695,50 @@ static int CmdLFHitagDump(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_hitag_dump(); - return 0; + return PM3_SUCCESS; } */ +// Annotate HITAG protocol +void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { +} + +void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { + + uint8_t cmdbits = (cmd[0] & 0xC0) >> 6; + + if (cmdsize == 1) { + if (cmdbits == HITAG2_START_AUTH) { + snprintf(exp, size, "START AUTH"); + return; + } + if (cmdbits == HITAG2_HALT) { + snprintf(exp, size, "HALT"); + return; + } + } + + if (cmdsize == 2) { + if (cmdbits == HITAG2_START_AUTH) { + // C 1 C 0 + // 1100 0 00 1 1100 000 + uint8_t page = (cmd[0] & 0x38) >> 3; + uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6); + snprintf(exp, size, "READ page(%x) %x", page, inv_page); + return; + } + if (cmdbits == HITAG2_WRITE_PAGE) { + uint8_t page = (cmd[0] & 0x38) >> 3; + uint8_t inv_page = ((cmd[0] & 0x1) << 2) | ((cmd[1] & 0xC0) >> 6); + snprintf(exp, size, "WRITE page(%x) %x", page, inv_page); + return; + } + } +} + +void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize) { +} + static command_t CommandTable[] = { {"help", CmdHelp, AlwaysAvailable, "This help" }, {"list", CmdLFHitagList, IfPm3Hitag, "List Hitag trace history" }, @@ -711,7 +754,7 @@ static command_t CommandTable[] = { static int CmdHelp(const char *Cmd) { (void)Cmd; // Cmd is not used so far CmdsHelp(CommandTable); - return 0; + return PM3_SUCCESS; } int CmdLFHitag(const char *Cmd) { @@ -720,5 +763,5 @@ int CmdLFHitag(const char *Cmd) { } int readHitagUid(void) { - return CmdLFHitagReader("26") == 0; + return (CmdLFHitagReader("26") == PM3_SUCCESS); } diff --git a/client/cmdlfhitag.h b/client/cmdlfhitag.h index c95c0e334..98b9968e0 100644 --- a/client/cmdlfhitag.h +++ b/client/cmdlfhitag.h @@ -16,5 +16,7 @@ int CmdLFHitag(const char *Cmd); int readHitagUid(void); - +void annotateHitag1(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateHitag2(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); +void annotateHitagS(char *exp, size_t size, uint8_t *cmd, uint8_t cmdsize); #endif diff --git a/client/cmdtrace.c b/client/cmdtrace.c index a13a82809..88f55ed3f 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -17,6 +17,7 @@ #include "cmdhflist.h" // annotations #include "comms.h" // for sending cmds to device. GetFromBigBuf #include "fileutils.h" // for saveFile +#include "cmdlfhitag.h" // annotate hitag static int CmdHelp(const char *Cmd); @@ -45,7 +46,9 @@ static int usage_trace_list() { PrintAndLogEx(NORMAL, " iclass - interpret data as iclass 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, " hitag1 - interpret data as Hitag1 communications"); + PrintAndLogEx(NORMAL, " hitag2 - interpret data as Hitag2 communications"); + PrintAndLogEx(NORMAL, " hitags - interpret data as HitagS communications"); PrintAndLogEx(NORMAL, " lto - interpret data as LTO-CM communications"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -281,7 +284,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr crcStatus = iso15693_CRC_check(frame, data_len); break; case ISO_7816_4: - case PROTO_HITAG: + case PROTO_HITAG1: + case PROTO_HITAG2: + case PROTO_HITAGS: default: break; } @@ -301,7 +306,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr && protocol != ISO_15693 && protocol != ICLASS && protocol != ISO_7816_4 - && protocol != PROTO_HITAG + && protocol != PROTO_HITAG1 + && protocol != PROTO_HITAG2 + && protocol != PROTO_HITAGS && protocol != THINFILM && protocol != FELICA && protocol != LTO @@ -385,6 +392,15 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr case LTO: annotateLTO(explanation, sizeof(explanation), frame, data_len); break; + case PROTO_HITAG1: + annotateHitag1(explanation, sizeof(explanation), frame, data_len); + break; + case PROTO_HITAG2: + annotateHitag2(explanation, sizeof(explanation), frame, data_len); + break; + case PROTO_HITAGS: + annotateHitagS(explanation, sizeof(explanation), frame, data_len); + break; default: break; } @@ -593,7 +609,9 @@ int CmdTraceList(const char *Cmd) { 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, "hitag1") == 0) protocol = PROTO_HITAG1; + else if (strcmp(type, "hitag2") == 0) protocol = PROTO_HITAG2; + else if (strcmp(type, "hitags") == 0) protocol = PROTO_HITAGS; else if (strcmp(type, "thinfilm") == 0) protocol = THINFILM; else if (strcmp(type, "lto") == 0) protocol = LTO; else if (strcmp(type, "raw") == 0) protocol = -1; //No crc, no annotations @@ -644,8 +662,7 @@ int CmdTraceList(const char *Cmd) { } } - PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %lu bytes)", traceLen); - PrintAndLogEx(INFO, ""); + PrintAndLogEx(SUCCESS, "Recorded activity (trace len = " _YELLOW_("%lu") "bytes)", traceLen); /* if (protocol == FELICA) { @@ -657,27 +674,27 @@ int CmdTraceList(const char *Cmd) { tracepos = printHexLine(tracepos, traceLen, trace, protocol); } } else { - PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); + PrintAndLogEx(INFO, _YELLOW_("Start") "= Start of Start Bit, " _YELLOW_("End") "= End of last modulation. " _YELLOW_("Src") "= Source of Transfer"); if (protocol == ISO_14443A || protocol == PROTO_MIFARE || protocol == MFDES || protocol == TOPAZ || protocol == LTO) - PrintAndLogEx(NORMAL, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); + PrintAndLogEx(INFO, "ISO14443A - All times are in carrier periods (1/13.56MHz)"); if (protocol == THINFILM) - PrintAndLogEx(NORMAL, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); + PrintAndLogEx(INFO, "Thinfilm - All times are in carrier periods (1/13.56MHz)"); if (protocol == ICLASS) - PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate"); + PrintAndLogEx(INFO, "iClass - Timings are not as accurate"); if (protocol == LEGIC) - PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" + PrintAndLogEx(INFO, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); if (protocol == ISO_14443B) - PrintAndLogEx(NORMAL, "ISO14443B"); // Timings ? + PrintAndLogEx(INFO, "ISO14443B"); // Timings ? if (protocol == ISO_15693) - PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); + PrintAndLogEx(INFO, "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(INFO, "ISO7816-4 / Smartcard - Timings N/A yet"); + if (protocol == PROTO_HITAG1 || protocol == PROTO_HITAG2 || protocol == PROTO_HITAGS) + PrintAndLogEx(INFO, "Hitag1 / Hitag2 / HitagS - Timings in ETU (8us)"); if (protocol == FELICA) - PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); - + PrintAndLogEx(INFO, "ISO18092 / FeliCa - Timings are not as accurate"); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); PrintAndLogEx(NORMAL, "------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------"); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index 5ba245070..e3021c8f6 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -125,15 +125,16 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } } - PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); + PrintAndLogEx(SUCCESS, "found " _YELLOW_("%u") "candidate key%s", keycount, (keycount > 1) ? "s." : "."); *key = UINT64_C(-1); uint8_t keyBlock[PM3_CMD_DATA_SIZE]; uint32_t max_keys = KEYS_IN_BLOCK; for (uint32_t i = 0; i < keycount; i += max_keys) { - uint32_t size = keycount - i > max_keys ? max_keys : keycount - i; - for (uint32_t j = 0; j < size; j++) { + uint8_t size = keycount - i > max_keys ? max_keys : keycount - i; + register uint8_t j; + for (j = 0; j < size; j++) { if (par_list == 0) { num_to_bytes(last_keylist[i * max_keys + j], 6, keyBlock + (j * 6)); } else { @@ -159,6 +160,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { free(keylist); return PM3_SUCCESS; } + int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t *keyBlock, uint64_t *key) { *key = -1; clearCommandBuffer(); @@ -308,7 +310,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk } // Compare 16 Bits out of cryptostate -static int Compare16Bits(const void *a, const void *b) { +inline static int Compare16Bits(const void *a, const void *b) { if ((*(uint64_t *)b & 0x00ff000000ff0000) == (*(uint64_t *)a & 0x00ff000000ff0000)) return 0; if ((*(uint64_t *)b & 0x00ff000000ff0000) > (*(uint64_t *)a & 0x00ff000000ff0000)) return 1; return -1; @@ -330,13 +332,14 @@ __attribute__((force_align_arg_pointer)) statelist->len = p1 - statelist->head.slhead; statelist->tail.sltail = --p1; + qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); return statelist->head.slhead; } int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey, bool calibrate) { - uint16_t i; + uint32_t uid; StateList_t statelists[2]; struct Crypto1State *p1, *p2, *p3, *p4; @@ -385,7 +388,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, memcpy(&uid, package->cuid, sizeof(package->cuid)); - for (i = 0; i < 2; i++) { + for (uint8_t i = 0; i < 2; i++) { statelists[i].blockNo = package->block; statelists[i].keyType = package->keytype; statelists[i].uid = uid; @@ -402,11 +405,11 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, pthread_t thread_id[2]; // create and run worker threads - for (i = 0; i < 2; i++) + for (uint8_t i = 0; i < 2; i++) pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); // wait for threads to terminate: - for (i = 0; i < 2; i++) + for (uint8_t i = 0; i < 2; i++) pthread_join(thread_id[i], (void *)&statelists[i].head.slhead); // the first 16 Bits of the cryptostate already contain part of our key. @@ -457,6 +460,8 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t keycnt = statelists[0].len; if (keycnt == 0) goto out; + PrintAndLogEx(SUCCESS, "Found " _YELLOW_("%u") "candidate keys", keycnt); + memset(resultKey, 0, 6); uint64_t key64 = -1; @@ -464,11 +469,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint32_t max_keys = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - for (i = 0; i < keycnt; i += max_keys) { + uint64_t start_time = msclock(); - int size = keycnt - i > max_keys ? max_keys : keycnt - i; + for (uint32_t i = 0; i < keycnt; i += max_keys) { - for (int j = 0; j < size; j++) { + uint8_t size = keycnt - i > max_keys ? max_keys : keycnt - i; + + register uint8_t j; + for (j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock + j * 6); } @@ -485,6 +493,13 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, ); return -5; } + + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + start_time = msclock(); + + if ( i + 1 % 10 == 0) + PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + } out: @@ -499,7 +514,7 @@ out: } int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *resultKey) { - uint16_t i; + uint32_t uid; StateList_t statelists[1]; struct Crypto1State *p1, *p3; @@ -589,16 +604,18 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl uint32_t max_keys_slice = keycnt > KEYS_IN_BLOCK ? KEYS_IN_BLOCK : keycnt; uint8_t keyBlock[PM3_CMD_DATA_SIZE] = {0x00}; - for (i = 0; i < keycnt; i += max_keys_slice) { + uint64_t start_time = msclock(); + for (uint32_t i = 0; i < keycnt; i += max_keys_slice) { - PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); +// PrintAndLogEx(INFO, "Testing %u / %u ", i, keycnt); key64 = 0; - int size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; + uint8_t size = keycnt - i > max_keys_slice ? max_keys_slice : keycnt - i; // copy x keys to device. - for (int j = 0; j < size; j++) { + register uint8_t j; + for (j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i + j, &key64); num_to_bytes(key64, 6, keyBlock + j * 6); } @@ -617,6 +634,12 @@ int mfStaticNested(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBl ); return PM3_SUCCESS; } + float bruteforce_per_second = (float)KEYS_IN_BLOCK / (float)(msclock() - start_time) * 1000.0; + start_time = msclock(); + + if ( i+1 % 10 == 0) + PrintAndLogEx(INFO, " %8d keys left | %5.1f keys/sec | worst case %6.1f seconds remaining", keycnt - i, bruteforce_per_second, (keycnt-i) / bruteforce_per_second); + } out: diff --git a/include/hitag.h b/include/hitag.h index 9df93fcf7..af90c9f88 100644 --- a/include/hitag.h +++ b/include/hitag.h @@ -21,6 +21,8 @@ typedef enum { RHTSF_KEY = 02, WHTSF_CHALLENGE = 03, WHTSF_KEY = 04, + RHT1F_PLAIN = 11, + RHT1F_AUTHENTICATE = 12, RHT2F_PASSWORD = 21, RHT2F_AUTHENTICATE = 22, RHT2F_CRYPTO = 23, @@ -44,8 +46,17 @@ typedef struct { uint8_t data[4]; } PACKED rht2d_crypto; +typedef struct { + bool key_no; + uint8_t logdata_0[4]; + uint8_t logdata_1[4]; + uint8_t nonce[4]; + uint8_t key[4]; +} PACKED rht1d_authenticate; + typedef union { rht2d_password pwd; + rht1d_authenticate ht1auth; rht2d_authenticate auth; rht2d_crypto crypto; } hitag_data; diff --git a/include/protocols.h b/include/protocols.h index 857cb2a4a..e1d898d53 100644 --- a/include/protocols.h +++ b/include/protocols.h @@ -305,9 +305,11 @@ 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 +#define PROTO_HITAG1 10 #define THINFILM 11 #define LTO 12 +#define PROTO_HITAG2 13 +#define PROTO_HITAGS 14 //-- Picopass fuses #define FUSE_FPERS 0x80 @@ -588,12 +590,18 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define HITAG1_HALT 0x70 // left 4 bits only, followed by 8 bits (dummy) page and 8 bits CRC // HITAG2 commands -#define HITAG2_START_AUTH 0xC0 // left 5 bits only -#define HITAG2_READ_PAGE 0xC0 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_READ_PAGE_INVERTED 0x44 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_WRITE_PAGE 0x82 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits -#define HITAG2_HALT 0x00 // left 5 bits only +#define HITAG2_START_AUTH 0x3 // left 5 bits only +#define HITAG2_HALT 0x0 // left 5 bits only +#define HITAG2_READ_PAGE 0x3 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits +#define HITAG2_READ_PAGE_INVERTED 0x1 // page number in bits 5 to 3, page number inverted in bit 0 and following 2 bits +#define HITAG2_WRITE_PAGE 0x2 // page number in bits 5 to 3, page number + + +// HITAG S commands +#define HITAGS_QUIET 0x70 +//inverted in bit 0 and following 2 bits +#define HITAGS_WRITE_BLOCK 0x90 // LTO-CM commands #define LTO_REQ_STANDARD 0x45 @@ -602,7 +610,6 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define LTO_READBLOCK 0x30 #define LTO_READBLOCK_CONT 0x80 #define LTO_SELECT 0x93 -#define LTO_SELECT_1 0x97 #define LTO_WRITEWORD 0xB0 // write 2 bytes (word) #define LTO_WRITEBLOCK 0xA0 #define LTO_HALT 0x50 diff --git a/tools/hitag2crack/.gitignore b/tools/hitag2crack/.gitignore new file mode 100644 index 000000000..e69de29bb diff --git a/tools/hitag2crack/crack2/.gitignore b/tools/hitag2crack/crack2/.gitignore new file mode 100644 index 000000000..71494d126 --- /dev/null +++ b/tools/hitag2crack/crack2/.gitignore @@ -0,0 +1,7 @@ +ht2crack2buildtable +ht2crack2search +ht2crack2gentest + +ht2crack2buildtable.exe +ht2crack2search.exe +ht2crack2gentest.exe diff --git a/tools/hitag2crack/crack2/HardwareProfile.h b/tools/hitag2crack/crack2/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack2/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// spi for SD card +#define SD_CARD_DET LATFbits.LATF0 +#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it + // (held LOW by default - cut solder bridge to GND to free pin if required) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack2/Makefile b/tools/hitag2crack/crack2/Makefile new file mode 100644 index 000000000..3ec604530 --- /dev/null +++ b/tools/hitag2crack/crack2/Makefile @@ -0,0 +1,26 @@ +WARN=-Wall +INCLUDE=-I../include +CFLAGS=-c $(WARN) $(INCLUDE) +# Linux libs +LIBS=-pthread -D_GNU_SOURCE +# Mac libs +# LIBS= + +all: ht2crack2buildtable.c ht2crack2search.c ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o + cc $(WARN) -o ht2crack2buildtable ht2crack2buildtable.c hitagcrypto.o ht2crack2utils.o $(LIBS) + cc $(WARN) -o ht2crack2search ht2crack2search.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS) + cc $(WARN) -o ht2crack2gentest ht2crack2gentest.c hitagcrypto.o utilpart.o ht2crack2utils.o $(LIBS) + +ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h + cc $(CFLAGS) ht2crack2utils.c + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +clean: + rm -rf *.o ht2crack2buildtable ht2crack2search ht2crack2gentest + +fresh: clean all diff --git a/tools/hitag2crack/crack2/hitagcrypto.c b/tools/hitag2crack/crack2/hitagcrypto.c new file mode 100644 index 000000000..2334f8288 --- /dev/null +++ b/tools/hitag2crack/crack2/hitagcrypto.c @@ -0,0 +1,487 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +//#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + + +static uint32_t hitag2_crypt(uint64_t s) +{ + const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 + const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 + const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + uint32_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * uint32_t serialnum - 32 bit tag serial number + * uint32_t initvector - 32 bit random IV from reader, part of tag authentication + */ +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) +{ + // init state, from serial number and lowest 16 bits of shared key + uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; + + // mix the initialisation vector and highest 32 bits of the shared key + initvector ^= (uint32_t) (sharedkey >> 16); + + // move 16 bits from (IV xor Shared Key) to top of uint64_t state + // these will be XORed in turn with output of the crypto function + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // optimise with one 64-bit intermediate + uint64_t temp = state ^ (state >> 1); + pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * Hitag_State* pstate - in/out, internal cipher state after initialisation + * uint32_t steps - number of bits requested, (capped at 32) + */ +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// commented out the restriction on number of steps so we can step further in one go. +// this still only returns 32 bits obviously +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +//#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "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. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack2/hitagcrypto.h b/tools/hitag2crack/crack2/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack2/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + uint64_t lfsr; // fast lfsr, used to make software faster +} Hitag_State; + +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack2/ht2crack2buildtable.c b/tools/hitag2crack/crack2/ht2crack2buildtable.c new file mode 100644 index 000000000..402c5b245 --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2buildtable.c @@ -0,0 +1,561 @@ +/* + * ht2crack2buildtable.c + * This builds the 1.2TB table and sorts it. + */ + +#include "ht2crack2utils.h" + + +// DATAMAX is the size of each bucket (bytes). There are 65536 buckets so choose a value such that +// DATAMAX * 65536 < RAM available. For ex, if you want to use 12GB of RAM (for a 16GB machine +// leaving some RAM free for OS and other stuff), DATAMAX = 12GB / 65536 = 196608. Round this down +// to a power of 10; DATAMAX = 196600. +#define DATAMAX 196600 // around 192K rounded down to a power of 10 + +// NUM_BUILD_THREADS and NUM_SORT_THREADS are the number of threads to run concurrently. These should +// ideally be equal to the number of virtual cores you have available. A quad-core machine will +// likely have 8 virtual cores, so set them to 8. +// +// If sorting fails with a 'bus error' then that is likely because your disk I/O can't keep up with +// the read/write demands of the multi-threaded sorting. In this case, reduce the number of sorting +// threads. This will most likely only be a problem with network disks; SATA should be okay; +// USB2/3 should keep up. +// +// These MUST be a power of 2 for the maths to work - you have been warned! +// Also, sort threads MUST be <= build threads or a horrible buffer overflow will happen! +#define NUM_BUILD_THREADS 8 +#define NUM_SORT_THREADS 8 + +// DATASIZE is the number of bytes in an entry. This is 10; 4 bytes of keystream (2 are in the filepath) + +// 6 bytes of PRNG state. +#define DATASIZE 10 + +int debug = 0; + +// table entry for a bucket +struct table { + char path[32]; + pthread_mutex_t mutex; + unsigned char *data; + unsigned char *ptr; +}; + + +// actual table +struct table *t; + +// jump table 1 +uint64_t d[48]; +int nsteps; + +// jump table 2 +uint64_t d2[48]; +int nsteps2; + +// create table entry +void create_table(struct table *t, int d1, int d2) +{ + if (!t) { + printf("create_table: t is NULL\n"); + exit(1); + } + + // create some space + t->data = (unsigned char *)malloc(DATAMAX); + if (!(t->data)) { + printf("create_table: cannot malloc data\n"); + exit(1); + } + + // set data ptr to start of data table + t->ptr = t->data; + + // init the mutex + if (pthread_mutex_init(&(t->mutex), NULL)) { + printf("create_table: cannot init mutex\n"); + exit(1); + } + + // create the path +// sprintf(t->path, "/Volumes/2tb/%02X/%02X.bin", d1 & 0xff, d2 & 0xff); + sprintf(t->path, "table/%02x/%02x.bin", d1 & 0xff, d2 & 0xff); +} + + +// create all table entries +void create_tables(struct table *t) +{ + int i, j; + + if (!t) { + printf("create_tables: t is NULL\n"); + exit(1); + } + + for (i=0; i<0x100; i++) { + for (j=0; j<0x100; j++) { + create_table(t + ((i * 0x100) + j), i, j); + } + } +} + + +// free the table memory +void free_tables(struct table *t) +{ + int i; + struct table *ttmp; + + if (!t) { + printf("free_tables: t is NULL\n"); + exit(1); + } + + for (i=0; i<0x10000; i++) { + ttmp = t + i; + free(ttmp->data); + } +} + + + +// write (partial) table to file +void writetable(struct table *t1) +{ + int fd; + + if (debug) printf("writetable %s\n", t1->path); + + fd = open(t1->path, O_WRONLY | O_CREAT | O_APPEND, 0644); + if (fd <= 0) { + printf("writetable cannot open file %s for appending\n", t1->path); + exit(1); + } + + if (debug) printf("writetable %s opened\n", t1->path); + + if (write(fd, t1->data, t1->ptr - t1->data) < (t1->ptr - t1->data)) { + printf("writetable cannot write all of the data\n"); + exit(1); + } + + if (debug) printf("writetable %s written\n", t1->path); + + close(fd); +} + + +// store value in table +void store(unsigned char *data) +{ + unsigned char d1, d2; + int offset; + struct table *t1; + + // use the first two bytes as an index + d1 = data[0]; + d2 = data[1]; + offset = (d1 * 0x100) + d2; + + if (debug) printf("store, d1=%02X, d2=%02X, offset = %d\n", d1, d2, offset); + + // get pointer to table entry + t1 = t + offset; + + // wait for a lock on this entry + if (pthread_mutex_lock(&(t1->mutex))) { + printf("store: cannot lock mutex at offset %d\n", offset); + exit(1); + } + + if (debug) printf("store, offset = %d, got lock\n", offset); + + // store the entry + memcpy(t1->ptr, data+2, 10); + + if (debug) printf("store, offset = %d, copied data\n", offset); + + // update the ptr + t1->ptr += 10; + + // check if table is full + if ((t1->ptr - t1->data) >= DATAMAX) { + // write the table to disk + writetable(t1); + // reset ptr + t1->ptr = t1->data; + } + + if (debug) printf("store, offset = %d, after possible write\n", offset); + + // release the lock + if (pthread_mutex_unlock(&(t1->mutex))) { + printf("store: cannot unlock mutex at offset %d\n", offset); + exit(1); + } + + if (debug) printf("store, offset = %d, unlocked\n", offset); + +} + +// writes the ks (keystream) and s (state) +void write_ks_s(uint32_t ks1, uint32_t ks2, uint64_t shiftreg) +{ + unsigned char buf[16]; + + // create buffer + writebuf(buf, ks1, 3); + writebuf(buf+3, ks2, 3); + writebuf(buf+6, shiftreg, 6); + + // store buffer + store(buf); + +} + + +// builds the di table for jumping +void builddi(int steps, int table) +{ + uint64_t statemask; + int i; + Hitag_State mystate; + uint64_t *thisd = NULL; + + statemask = 1; + + // select jump table + if (table == 1) { + nsteps = steps; + thisd = d; + } else if (table == 2) { + nsteps2 = steps; + thisd = d2; + } else { + printf("builddi: invalid table num\n"); + exit(1); + } + + // build di states + for (i=0; i<48; i++) { + mystate.shiftreg = statemask; + buildlfsr(&mystate); + hitag2_nstep(&mystate, steps); + thisd[i] = mystate.shiftreg; + + statemask = statemask << 1; + } +} + +// jump function - quickly jumps a load of steps +void jumpnsteps(Hitag_State *hstate, int table) +{ + uint64_t output = 0; + uint64_t bitmask; + int i; + uint64_t *thisd = NULL; + + + // select jump table + if (table == 1) { + thisd = d; + } else if (table == 2) { + thisd = d2; + } else { + printf("jumpnsteps: invalid table num\n"); + exit(1); + } + + // xor all di.si where di is a d state and si is a bit + // we do this by multiplying di by si: + // if si is 1, di.si = di; if si is 0, di.si = 0 + + bitmask = 1; + for (i=0; i<48; i++) { + if (hstate->shiftreg & bitmask) { + output = output ^ thisd[i]; + } + + bitmask = bitmask << 1; + } + + hstate->shiftreg = output; + buildlfsr(hstate); +} + + +// thread to build a part of the table +void *buildtable(void *d) +{ + Hitag_State hstate; + Hitag_State hstate2; + unsigned long i; + unsigned long maxentries = 1; + uint32_t ks1; + uint32_t ks2; + int index = (int)(long)d; + int tnum = NUM_BUILD_THREADS; + + /* set random state */ + hstate.shiftreg = 0x123456789abc; + buildlfsr(&hstate); + + /* jump to offset using jump table 2 (2048) */ + for (i=0; i> 1; + tnum = tnum >> 1; + } + + /* make the entries */ + for (i=0; iptr > t1->data) { + writetable(t1); + } + } + + // dump the memory + free_tables(t); + free(t); + + + + // now for the sorting + + + // start the threads + for (i=0; i 32)) { + printf("makerandom: len must be between 1 and 32 inclusive\n"); + exit(1); + } + + if (read(fd, raw, len) != len) { + printf("makerandom: cannot read random bytes\n"); + exit(1); + } + + for (i=0; ilen = filestat.st_size / 2; +// printf("r->len = %d\n", r->len); + + r->data = (unsigned char *)malloc(r->len); + if (!(r->data)) { + printf("cannot malloc\n"); + exit(1); + } + + j = 0; + nibble = 0; + for (i=0; (ilen); i++) { + if ((data[i] != 0x0a) && (data[i] != 0x0d) && (data[i] != 0x20)) { + if (!nibble) { + r->data[j] = hex2bin(data[i]) << 4; + nibble = 1; + } else { + r->data[j] |= hex2bin(data[i]); + nibble = 0; + j++; + } + } + } + + r->len = j; + + munmap(data, filestat.st_size); + close(fd); + + return 1; +} + +int makecand(unsigned char *c, struct rngdata *r, int bitoffset) +{ + int bytenum; + int bitnum; + int i; + + if (!c || !r || (bitoffset > ((r->len * 8) - 48))) { + printf("makecand: invalid params\n"); + return 0; + } + + bytenum = bitoffset / 8; + bitnum = bitoffset % 8; + + for (i=0; i<6; i++) { + if (!bitnum) { + c[i] = r->data[bytenum + i]; + } else { + c[i] = (r->data[bytenum + i] << bitnum) | (r->data[bytenum + i + 1] >> (8 - bitnum)); + } + } + + return 1; +} + + +// test the candidate against the next or previous rng data +int testcand(unsigned char *f, unsigned char *rt, int fwd) +{ + Hitag_State hstate; + int i; + uint32_t ks1; + uint32_t ks2; + unsigned char buf[6]; + + // build the prng state at the candidate + hstate.shiftreg = 0; + for (i=0; i<6; i++) { + hstate.shiftreg = (hstate.shiftreg << 8) | f[i+4]; + } + buildlfsr(&hstate); + + if (fwd) { + // roll forwards 48 bits + hitag2_nstep(&hstate, 48); + } else { + // roll backwards 48 bits + rollback(&hstate, 48); + buildlfsr(&hstate); + } + + // get 48 bits of RNG from the rolled to state + ks1 = hitag2_nstep(&hstate, 24); + ks2 = hitag2_nstep(&hstate, 24); + + writebuf(buf, ks1, 3); + writebuf(buf+3, ks2, 3); + + // compare them + if (!memcmp(buf, rt, 6)) { + return 1; + } else { + return 0; + } +} + +int searchcand(unsigned char *c, unsigned char *rt, int fwd, unsigned char *m, unsigned char *s) +{ + int fd; + struct stat filestat; + char file[64]; + unsigned char *data; + unsigned char item[10]; + unsigned char *found = NULL; + + + if (!c || !rt || !m || !s) { + printf("searchcand: invalid params\n"); + return 0; + } + + sprintf(file, INPUTFILE, c[0], c[1]); + + fd = open(file, O_RDONLY); + if (fd <= 0) { + printf("cannot open table file %s\n", file); + exit(1); + } + + if (fstat(fd, &filestat)) { + printf("cannot stat file %s\n", file); + exit(1); + } + + data = mmap((caddr_t)0, filestat.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (data == MAP_FAILED) { + printf("cannot mmap file %s\n", file); + exit(1); + } + + memcpy(item, c+2, 4); + + found = (unsigned char *)bsearch(item, data, filestat.st_size / DATASIZE, DATASIZE, datacmp); + + if (found) { + + // our candidate is in the table + // go backwards and see if there are other matches + while (((found - data) >= DATASIZE) && (!memcmp(found - DATASIZE, item, 4))) { + found = found - DATASIZE; + } + + // now test all matches + while (((found - data) <= (filestat.st_size - DATASIZE)) && (!memcmp(found, item, 4))) { + if (testcand(found, rt, fwd)) { + memcpy(m, c, 2); + memcpy(m+2, found, 4); + memcpy(s, found+4, 6); + + munmap(data, filestat.st_size); + close(fd); + return 1; + } + + found = found + DATASIZE; + } + } + + munmap(data, filestat.st_size); + close(fd); + + return 0; + +} + +int findmatch(struct rngdata *r, unsigned char *outmatch, unsigned char *outstate, int *bitoffset) +{ + int i; + int bitlen; + unsigned char cand[6]; + unsigned char rngtest[6]; + int fwd; + + if (!r || !outmatch || !outstate || !bitoffset) { + printf("findmatch: invalid params\n"); + return 0; + } + + bitlen = r->len * 8; + + for (i=0; i<=bitlen - 48; i++) { + // print progress + if ((i % 100) == 0) { + printf("searching on bit %d\n", i); + } + + if (!makecand(cand, r, i)) { + printf("cannot makecand, %d\n", i); + return 0; + } +// printf("cand: %02x %02x %02x %02x %02x %02x : ", cand[0], cand[1], cand[2], cand[3], cand[4], cand[5]); +// printbin(cand); + + /* make following or preceding RNG test data to confirm match */ + if (i < (bitlen - 96)) { + if (!makecand(rngtest, r, i + 48)) { + printf("cannot makecand rngtest %d + 48\n", i); + return 0; + } + fwd = 1; + } else { + if (!makecand(rngtest, r, i - 48)) { + printf("cannot makecand rngtest %d - 48\n", i); + return 0; + } + fwd = 0; + } + + if (searchcand(cand, rngtest, fwd, outmatch, outstate)) { + *bitoffset = i; + return 1; + } + } + + return 0; +} + + + + +void rollbackrng(Hitag_State *hstate, unsigned char *s, int offset) +{ + int i; + + if (!s) { + printf("rollbackrng: invalid params\n"); + return; + } + + // build prng at recovered offset + hstate->shiftreg = 0; + for (i=0; i<6; i++) { + hstate->shiftreg = (hstate->shiftreg << 8) | s[i]; + } + + printf("recovered prng state at offset %d:\n", offset); + printstate(hstate); + + // rollback to state after auth + rollback(hstate, offset); + + // rollback through auth (aR, p3) + rollback(hstate, 64); + + printf("prng state after initialisation:\n"); + printstate(hstate); + + +} + +uint64_t recoverkey(Hitag_State *hstate, char *uidstr, char *nRstr) +{ + uint64_t key; + uint64_t keyupper; + uint32_t uid; + uint32_t uidtmp; + uint32_t nRenc; + uint32_t nR; + uint32_t nRxork; + uint32_t b = 0; + int i; + + // key lower 16 bits are lower 16 bits of prng state + key = hstate->shiftreg & 0xffff; + nRxork = (hstate->shiftreg >> 16) & 0xffffffff; + uid = rev32(hexreversetoulong(uidstr)); + nRenc = rev32(hexreversetoulong(nRstr)); + + uidtmp = uid; + // rollback and extract bits b + for (i=0; i<32; i++) { + hstate->shiftreg = ((hstate->shiftreg) << 1) | ((uidtmp >> 31) & 0x1); + uidtmp = uidtmp << 1; + b = (b << 1) | fnf(hstate->shiftreg); + } + + printf("end state:\n"); + printstate(hstate); + printf("b:\t\t"); + printbin2(b, 32); + printf("\n"); + printf("nRenc:\t\t"); + printbin2(nRenc, 32); + printf("\n"); + + nR = nRenc ^ b; + + printf("nR:\t\t"); + printbin2(nR, 32); + printf("\n"); + + keyupper = nRxork ^ nR; + key = key | (keyupper << 16); + printf("key:\t\t"); + printbin2(key, 48); + printf("\n"); + + return key; +} + + +int main(int argc, char *argv[]) +{ + Hitag_State hstate; + struct rngdata rng; + int bitoffset = 0; + unsigned char rngmatch[6]; + unsigned char rngstate[6]; + char *uidstr; + char *nRstr; + uint64_t keyrev; + uint64_t key; + int i; + + if (argc < 4) { + printf("ht2crack2search rngdatafile UID nR\n"); + exit(1); + } + + if (!loadrngdata(&rng, argv[1])) { + printf("loadrngdata failed\n"); + exit(1); + } + + if (!strncmp(argv[2], "0x", 2)) { + uidstr = argv[2] + 2; + } else { + uidstr = argv[2]; + } + + if (!strncmp(argv[3], "0x", 2)) { + nRstr = argv[3] + 2; + } else { + nRstr = argv[3]; + } + + + if (!findmatch(&rng, rngmatch, rngstate, &bitoffset)) { + printf("couldn't find a match\n"); + exit(1); + } + + printf("found match:\n"); + printf("rngmatch = %02x %02x %02x %02x %02x %02x\n", rngmatch[0], rngmatch[1], rngmatch[2], rngmatch[3], rngmatch[4], rngmatch[5]); + printf("rngstate = %02x %02x %02x %02x %02x %02x\n", rngstate[0], rngstate[1], rngstate[2], rngstate[3], rngstate[4], rngstate[5]); + printf("bitoffset = %d\n", bitoffset); + + rollbackrng(&hstate, rngstate, bitoffset); + + keyrev = recoverkey(&hstate, uidstr, nRstr); + key = rev64(keyrev); + + printf("keyrev:\t\t"); + printbin2(key, 48); + printf("\n"); + + printf("KEY:\t\t"); + for (i=0; i<6; i++) { + printf("%02X", (int)(key & 0xff)); + key = key >> 8; + } + printf("\n"); + + return 0; + +} + + diff --git a/tools/hitag2crack/crack2/ht2crack2utils.c b/tools/hitag2crack/crack2/ht2crack2utils.c new file mode 100644 index 000000000..2152f8ef3 --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2utils.c @@ -0,0 +1,187 @@ +#include "ht2crack2utils.h" + +// writes a value into a buffer as a series of bytes +void writebuf(unsigned char *buf, uint64_t val, unsigned int len) +{ + int i; + char c; + + for (i=len-1; i>=0; i--) + { + c = val & 0xff; + buf[i] = c; + val = val >> 8; + } + +} + + +/* simple hexdump for testing purposes */ +void shexdump(unsigned char *data, int data_len) +{ + int i; + + if (!data || (data_len <= 0)) { + printf("shexdump: invalid parameters\n"); + return; + } + + printf("Hexdump from %p:\n", data); + + for (i=0; i> 7); + x = x << 1; + } + } + printf("\n"); +} + + +void printbin2(uint64_t val, unsigned int size) +{ + int i; + uint64_t mask = 1; + + mask = mask << (size - 1); + + for (i=0; ishiftreg, 48); + printf("\n"); +} + + + + +// convert hex char to binary +unsigned char hex2bin(unsigned char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } else if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } else if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } else { + return 0; + } +} + +// return a single bit from a value +int bitn(uint64_t x, int bit) +{ + uint64_t bitmask = 1; + + bitmask = bitmask << bit; + + if (x & bitmask) { + return 1; + } else { + return 0; + } +} + + +// the sub-function R that rollback depends upon +int fnR(uint64_t x) +{ + // renumbered bits because my state is 0-47, not 1-48 + return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^ + bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ + bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); +} + +// the rollback function that lets us go backwards in time +void rollback(Hitag_State *hstate, unsigned int steps) +{ + int i; + + for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); + } + +} + + +// the three filter sub-functions that feed fnf +int fa(unsigned int i) +{ + return bitn(0x2C79, i); +} + +int fb(unsigned int i) +{ + return bitn(0x6671, i); +} + +int fc(unsigned int i) +{ + return bitn(0x7907287B, i); +} + +// the filter function that generates a bit of output from the prng state +int fnf(uint64_t s) +{ + unsigned int x1, x2, x3, x4, x5, x6; + + x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3); + x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3); + x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3); + x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3); + x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3); + + x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4); + + return fc(x6); +} + +// builds the lfsr for the prng (quick calcs for hitag2_nstep()) +void buildlfsr(Hitag_State *hstate) +{ + uint64_t state = hstate->shiftreg; + uint64_t temp; + + temp = state ^ (state >> 1); + hstate->lfsr = state ^ (state >> 6) ^ (state >> 16) + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); +} + + + diff --git a/tools/hitag2crack/crack2/ht2crack2utils.h b/tools/hitag2crack/crack2/ht2crack2utils.h new file mode 100644 index 000000000..14eea840c --- /dev/null +++ b/tools/hitag2crack/crack2/ht2crack2utils.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "util.h" + +#include "hitagcrypto.h" + +#define HEX_PER_ROW 16 + + + +void writebuf(unsigned char *buf, uint64_t val, unsigned int len); +void shexdump(unsigned char *data, int data_len); +void printbin(unsigned char *c); +void printbin2(uint64_t val, unsigned int size); +void printstate(Hitag_State *hstate); +unsigned char hex2bin(unsigned char c); +int bitn(uint64_t x, int bit); +int fnR(uint64_t x); +void rollback(Hitag_State *hstate, unsigned int steps); +int fa(unsigned int i); +int fb(unsigned int i); +int fc(unsigned int i); +int fnf(uint64_t s); +void buildlfsr(Hitag_State *hstate); diff --git a/tools/hitag2crack/crack2/readme.md b/tools/hitag2crack/crack2/readme.md new file mode 100644 index 000000000..dd0872260 --- /dev/null +++ b/tools/hitag2crack/crack2/readme.md @@ -0,0 +1,68 @@ +ht2crack2 suite + + + +Build +----- + +Edit ht2crack2buildtable.c and set the DATAMAX, NUM_BUILD_THREADS and NUM_SORT_THREADS values. +These are important if you want it to run quickly. Ideally set DATAMAX to the largest value +that you can get away with and set NUM_BUILD_THREADS and NUM_SORT_THREADS to the number of +virtual cores you have available, which MUST be a power of 2. NUM_BUILD_THREADS MUST be >= +NUM_SORT_THREADS. + +Calculate DATAMAX = free RAM available / 65536, and then round down to a power of 10. + +The Makefile is configured for linux. To compile on Mac, edit it and swap the LIBS= lines. + +make clean +make + + +Run ht2crack2buildtable +----------------------- + +Make sure you are in a directory on a disk with at least 1.5TB of space. +./ht2crack2buildtable + +Wait a very long time. Maybe a few days. + +This will create a directory tree called table/ while it is working that will contain +files that will slowly build up in size to approx 20MB each. Once it has finished making +these unsorted files, it will sort them into the directory tree sorted/ and remove the +original files. It will then exit and you'll have your shiny table. + + +Test with ht2crack2gentests +--------------------------- + +./ht2crack2gentests NUMBER_OF_TESTS + +to generate NUMBER_OF_TESTS test files. These will all be named +keystream.key-KEYVALUE.uid-UIDVALUE.nR-NRVALUE + +Test a single test with +./runtest.sh KEYSTREAMFILE + +or manually with +./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE + +or run all tests with +./runalltests.sh + +Feel free to edit the shell scripts to find your tools. You might want to create a +symbolic link to your sorted/ directory called 'sorted' to help ht2crack2seach find the +table. + +If the tests work, then the table is sound. + + +Search for key in real keystream +-------------------------------- + +Recover 2048 bits of keystream from the target RFID tag with the RFIDler. You will have had +to supply an NR value and you should know the tag's UID (you can get this using the RFIDler). + +./ht2crack2search KEYSTREAMFILE UIDVALUE NRVALUE + + diff --git a/tools/hitag2crack/crack2/rfidler.h b/tools/hitag2crack/crack2/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack2/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#define TAG_TYPE_AWID_26 17 +#define TAG_TYPE_EM4X05 18 +#define TAG_TYPE_TAMAGOTCHI 19 +#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack2/runalltests.sh b/tools/hitag2crack/crack2/runalltests.sh new file mode 100755 index 000000000..945873cfb --- /dev/null +++ b/tools/hitag2crack/crack2/runalltests.sh @@ -0,0 +1,3 @@ +for i in keystream*; do +./runtest.sh $i +done diff --git a/tools/hitag2crack/crack2/runtest.sh b/tools/hitag2crack/crack2/runtest.sh new file mode 100755 index 000000000..bcc08727c --- /dev/null +++ b/tools/hitag2crack/crack2/runtest.sh @@ -0,0 +1,25 @@ +#!/bin/bash + +if [ "$1" == "" ]; then +echo "runtest.sh testfile" +echo "testfile name should be of the form:" +echo "keystream.key-KEY.uid-UID.nR-NR" +exit 1 +fi + +filename=$1 + +UIDV=`echo $1 | cut -d'-' -f3 | cut -d'.' -f1` +NR=`echo $1 | cut -d'-' -f4` +KEYV=`echo $1 | cut -d'-' -f2 | cut -d'.' -f1` + +echo "********************" +echo "FILENAME = $filename" +echo "UID = $UIDV" +echo "NR = $NR" +echo "Expected KEY = $KEYV" + +./ht2crack2search $filename $UIDV $NR +echo "Expected KEY = $KEYV" +echo "********************" +echo "" diff --git a/tools/hitag2crack/crack2/util.h b/tools/hitag2crack/crack2/util.h new file mode 100644 index 000000000..c0d4c156a --- /dev/null +++ b/tools/hitag2crack/crack2/util.h @@ -0,0 +1,206 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#define CRC16_MASK_CCITT 0x1021 // CRC-CCITT mask (ISO 3309, used in X25, HDLC) +#define CRC16_MASK_ISO_11785 0x8408 // ISO 11785 animal tags +#define CRC16_MASK_CRC16 0xA001 // standard CRC16 mask (used in ARC files) + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#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)) + + +BYTE approx(unsigned long number, unsigned long target, unsigned char percentage); +unsigned int bcdtouint(BYTE *bcd, BYTE length); +unsigned long long bcdtoulonglong(BYTE *bcd, BYTE length); +void inttobinarray(BYTE *target, unsigned int source, unsigned int bits); +void ulongtobinarray(BYTE *target, unsigned long source, unsigned int bits); +void ulonglongtobinarray(BYTE *target, unsigned long long source, unsigned int bits); +void inttobinstring(BYTE *target, unsigned int source, unsigned int bits); +void ulongtobinstring(BYTE *target, unsigned long source, unsigned int bits); +BOOL ulongtohex(BYTE *target, unsigned long source); +unsigned int binarraytoint(BYTE *bin, BYTE length); +unsigned long long binarraytolonglong(BYTE *bin, BYTE length); +unsigned long binarraytoulong(BYTE *bin, BYTE length); +BYTE hextobyte(BYTE *hex); +void printhexreadable(BYTE *hex, BYTE maxlength); +unsigned long hextoulong(BYTE *hex); +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hextoulonglong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); +char hextolonglong(unsigned long long *out, unsigned char *hex); +unsigned int hextobinarray(unsigned char *target, unsigned char *source); +unsigned int hextobinstring(unsigned char *target, unsigned char *source); +unsigned int binarraytohex(unsigned char *target, unsigned char *source, unsigned int length); +void hexprintbinarray(BYTE *bin, unsigned int length); +unsigned int binstringtohex(unsigned char *target, unsigned char *source); +unsigned int binstringtobinarray(BYTE *target, BYTE *source); +void binstringtobyte(BYTE *target, unsigned char *source, BYTE length); +void binarraytobinstring(BYTE *target, BYTE *source, unsigned int length); +void printhexasbin(unsigned char *hex); +void printbinashex(unsigned char *bin); +void invertbinarray(BYTE *target, BYTE *source, unsigned int length); +void invertbinstring(BYTE *target, BYTE *source); +void printbinarray(unsigned char *bin, unsigned int length); +unsigned char getbit(unsigned char byte, unsigned char bit); +void bytestohex(unsigned char *target, unsigned char *source, unsigned int length); +unsigned int manchester_encode(unsigned char *target, unsigned char *source, unsigned int length); +unsigned int manchester_decode(unsigned char *target, unsigned char *source, unsigned int length); +char * strip_newline(char *buff); +BOOL command_ack(BOOL data); +BOOL command_nack(BYTE *reason); +BOOL command_unknown(void); +void ToUpper(char *string); +void string_reverse(unsigned char *string, unsigned int length); +BOOL string_byteswap(unsigned char *string, unsigned int length); +BYTE parity(unsigned char *string, BYTE type, unsigned int length); +unsigned long get_reader_pulse(unsigned int timeout_us); +unsigned long get_reader_gap(unsigned int timeout_us); +unsigned int crc_ccitt(BYTE *data, unsigned int length); +unsigned int crc16(unsigned int crc, BYTE *data, unsigned int length, unsigned int mask); +void space_indent(BYTE count); +void xml_version(void); +void xml_header(BYTE *item, BYTE *indent); +void xml_footer(BYTE *item, BYTE *indent, BOOL newline); +void xml_indented_text(BYTE *data, BYTE indent); +void xml_item_text(BYTE *item, BYTE *data, BYTE *indent); +void xml_item_decimal(BYTE *item, BYTE num, BYTE *indent); +void xml_indented_array(BYTE *data, BYTE mask, unsigned int length, BYTE indent); +void xml_item_array(BYTE *item, BYTE *data, BYTE mask, unsigned int length, BYTE *indent); + diff --git a/tools/hitag2crack/crack2/utilpart.c b/tools/hitag2crack/crack2/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack2/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +rtccTime RTC_time; // time structure +rtccDate RTC_date; // date structure + +// convert byte-reversed 8 digit hex to unsigned long +unsigned long hexreversetoulong(BYTE *hex) +{ + unsigned long ret= 0L; + unsigned int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +unsigned long long hexreversetoulonglong(BYTE *hex) +{ + unsigned long long ret= 0LL; + BYTE tmp[9]; + + // this may seem an odd way to do it, but weird compiler issues were + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/crack3/.gitignore b/tools/hitag2crack/crack3/.gitignore new file mode 100644 index 000000000..c993f2fe3 --- /dev/null +++ b/tools/hitag2crack/crack3/.gitignore @@ -0,0 +1,6 @@ +ht2crack3 +ht2test + +ht2crack3.exe +ht2test.exe + diff --git a/tools/hitag2crack/crack3/HardwareProfile.h b/tools/hitag2crack/crack3/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack3/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// spi for SD card +#define SD_CARD_DET LATFbits.LATF0 +#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it + // (held LOW by default - cut solder bridge to GND to free pin if required) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack3/Makefile b/tools/hitag2crack/crack3/Makefile new file mode 100644 index 000000000..6f6b7b57c --- /dev/null +++ b/tools/hitag2crack/crack3/Makefile @@ -0,0 +1,19 @@ +WARN=-Wall +INCLUDE=-I../include +CFLAGS=-c $(WARN) $(INCLUDE) +LIBS= + +all: ht2crack3.c ht2test.c hitagcrypto.o utilpart.o + cc $(WARN) -o ht2crack3 ht2crack3.c hitagcrypto.o utilpart.o -lpthread $(LIBS) + cc $(WARN) -o ht2test ht2test.c hitagcrypto.o utilpart.o $(LIBS) + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +clean: + rm -rf *.o ht2crack3 ht2test + +fresh: clean all diff --git a/tools/hitag2crack/crack3/hitagcrypto.c b/tools/hitag2crack/crack3/hitagcrypto.c new file mode 100644 index 000000000..422efbe92 --- /dev/null +++ b/tools/hitag2crack/crack3/hitagcrypto.c @@ -0,0 +1,485 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + + +static uint32_t hitag2_crypt(uint64_t s) +{ + const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 + const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 + const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + uint32_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * uint32_t serialnum - 32 bit tag serial number + * uint32_t initvector - 32 bit random IV from reader, part of tag authentication + */ +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) +{ + // init state, from serial number and lowest 16 bits of shared key + uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; + + // mix the initialisation vector and highest 32 bits of the shared key + initvector ^= (uint32_t) (sharedkey >> 16); + + // move 16 bits from (IV xor Shared Key) to top of uint64_t state + // these will be XORed in turn with output of the crypto function + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // optimise with one 64-bit intermediate + uint64_t temp = state ^ (state >> 1); + pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * Hitag_State* pstate - in/out, internal cipher state after initialisation + * uint32_t steps - number of bits requested, (capped at 32) + */ +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "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. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack3/hitagcrypto.h b/tools/hitag2crack/crack3/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack3/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + uint64_t lfsr; // fast lfsr, used to make software faster +} Hitag_State; + +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack3/ht2crack3.c b/tools/hitag2crack/crack3/ht2crack3.c new file mode 100644 index 000000000..190f8197d --- /dev/null +++ b/tools/hitag2crack/crack3/ht2crack3.c @@ -0,0 +1,466 @@ +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +// max number of NrAr pairs to load - you only need 136 good pairs, but this +// is the max +#define NUM_NRAR 1024 +#define NUM_THREADS 8 + +// table entry for Tkleft +struct Tklower { + uint64_t yxorb; + char notb32; + uint64_t klowery; +}; + +// table entry for nR aR pair +struct nRaR { + uint64_t nR; + uint64_t aR; +}; + +// struct to hold data for thread +struct threaddata { + uint64_t uid; + struct nRaR *TnRaR; + unsigned int numnrar; + uint64_t klowerstart; + uint64_t klowerrange; +}; + +void printbin(uint64_t val) +{ + int i; + + for (i=0; i<64; i++) { + if (val & 0x8000000000000000) { + printf("1"); + } else { + printf("0"); + } + val = val << 1; + } +} + +void printstate(Hitag_State *hstate) +{ + printf("shiftreg =\t"); + printbin(hstate->shiftreg); + printf("\n"); +} + + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +// these and the following hitag2_crypt function taken from Rfidler +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + + +static uint32_t hitag2_crypt(uint64_t s) +{ + const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 + const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 + const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + uint32_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + + +// this function is a modification of the filter function f, based heavily +// on the hitag2_crypt function in Rfidler +int fnP(uint64_t klowery) +{ + const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 + const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 + const uint32_t ht2_function4p = 0xAE83; // 1010 1110 1000 0011 + uint32_t i; + + i = (ht2_function4a >> pickbits2_2 (klowery, 2, 5)) & 1; + i |= ((ht2_function4b << 1) >> pickbits1_1_2 (klowery, 8, 12, 14)) & 0x02; + i |= ((ht2_function4b << 2) >> pickbits1x4 (klowery, 17, 21, 23, 26)) & 0x04; + i |= ((ht2_function4b << 3) >> pickbits2_1_1 (klowery, 28, 31, 33)) & 0x08; + + // modified to use reference implementation approach + // orig fc table is 0x7907287B = 0111 1001 0000 0111 0010 1000 0111 1011 + // we ignore the top bit (bit 4) of the parameter, so therefore create a new + // table that indicates which bit positions are the same if the top bit is 1 or 0 + return (ht2_function4p >> i) & 1; +} + +// comparison function for sorting/searching Tklower entries +int Tk_cmp(const void *v1, const void *v2) +{ + const struct Tklower *Tk1 = (struct Tklower *)v1; + const struct Tklower *Tk2 = (struct Tklower *)v2; + + if (Tk1->yxorb < Tk2->yxorb) { + return -1; + } else if (Tk1->yxorb > Tk2->yxorb) { + return 1; + } + + return 0; +} + +// test for bad guesses of kmiddle +int is_kmiddle_badguess(uint64_t z, struct Tklower *Tk, int max, int aR0) { + + struct Tklower *result, target; + + // "If there is an entry in Tklower for which y ^ b = z but !b32 != aR[0] + // then the attacker learns that kmiddle is a bad guess... otherwise, if + // !b32 == aR[0] then kmiddle is still a viable guess." + + target.yxorb = z; + target.notb32 = 0; + result = (struct Tklower *)bsearch(&target, Tk, max, sizeof(struct Tklower), Tk_cmp); + + if (result) { + if (result->notb32 != aR0) { + return 1; + } + } else { + return 2; + } + + return 0; +} + +// function to test if a partial key is valid +int testkey(uint64_t *out, uint64_t uid, uint64_t pkey, uint64_t nR, uint64_t aR) +{ + uint64_t kupper; + uint64_t key; + Hitag_State hstate; + uint64_t b; + uint32_t revaR; + uint32_t normaR; + + // normalise aR + revaR = rev32(aR); + normaR = ((revaR >> 24) | ((revaR >> 8) & 0xff00) | ((revaR << 8) & 0xff0000) | (revaR << 24)); + + // search for remaining 14 bits + for (kupper=0; kupper < 0x3fff; kupper++) { + key = (kupper << 34) | pkey; + hitag2_init(&hstate, key, uid, nR); + b = hitag2_nstep(&hstate, 32); + if ((normaR ^ b) == 0xffffffff) { + *out = key; + return 1; + } + } + return 0; +} + + + + + + + +// some notes on how I think this attack should work. +// due to the way fc works, in a number of cases, it doesn't matter what +// the most significant bits are doing for it to produce the same result. +// These are the most sig 14 bits to be clear. Looking at fc it is poss +// to see cases where the most sig bit of the input to fc (which is made +// from fa on 4 of the most sig bits from bit 34 onwards) does not affect +// whether it gives a 0 or 1 as the input 0b0ABCD gives the same bit value +// as input 0b1ABCD. +// The PRNG is initialised by setting the lower 32 bits to the UID, with +// the upper 16 bits set to the lower 16 bits of the key. Next the 32 +// upper bits of the key are XORed with the private nonce and these are +// shifted in, with the PRNG outputting bits b0 to b31. These bits are +// used to encrypt (XOR with) the nonce to produce nR, which is sent to +// the card. +// (The card should init the PRNG with the same UID and lower 16 bits of +// the key, receive the nR, then shift it in bit by bit while xoring each +// bit with its output, and the key - this essentially decrypts the nR to +// the nonce XOR the upper 32 bits of the key, while shifting it in. +// The card's PRNG will then be in the same state as the RWD.) +// By knowing the UID and guessing the lower 16 bits of the key, and +// focusing on nR values that don't affect the upper bits of fc, we can +// limit our guesses to a smaller set than a full brute force and +// effectively work out candidates for the lower 34 bits of the key. + + +void *crack(void *d) +{ + struct threaddata *data = (struct threaddata *)d; + uint64_t uid; + struct nRaR *TnRaR; + unsigned int numnrar; + + Hitag_State hstate; + int i, j; + + uint64_t klower; + uint64_t kmiddle; + uint64_t y; + uint64_t ytmp; + uint64_t klowery; + unsigned int count = 0; + uint64_t bit; + uint64_t b; + uint64_t z; + uint64_t foundkey; + uint64_t revkey; + int ret; + unsigned int found = 0; + unsigned int badguess = 0; + + struct Tklower *Tk = NULL; + + if (!data) { + printf("Thread data is NULL\n"); + exit(1); + } + + uid = data->uid; + TnRaR = data->TnRaR; + numnrar = data->numnrar; + + // create space for tables + Tk = (struct Tklower *)malloc(sizeof(struct Tklower) * 0x40000); + if (!Tk) { + printf("cannot malloc Tk\n"); + exit(1); + } + + // find keys + for (klower=data->klowerstart; klower < (data->klowerstart + data->klowerrange); klower++) { + printf("trying klower = 0x%05lx\n", klower); + // build table + count = 0; + for (y=0; y<0x40000; y++) { + // create klowery + klowery = (y << 16) | klower; + // check for cases where right most bit of fc doesn't matter + + if (fnP(klowery)) { + // store klowery + Tk[count].klowery = klowery; + // build the initial prng state + hstate.shiftreg = (klower << 32) | uid; + // zero the lfsr so only 0s are inserted + hstate.lfsr = 0; + // insert y into shiftreg and extract keystream, reversed order + b = 0; + ytmp = y; + for (j=0; j<2; j++) { + hstate.shiftreg = hstate.shiftreg | ((ytmp & 0xffff) << 48); + for (i=0; i<16; i++) { + hstate.shiftreg = hstate.shiftreg >> 1; + bit = hitag2_crypt(hstate.shiftreg); + b = (b >> 1) | (bit << 31); + } + ytmp = ytmp >> 16; + } + + // store the xor of y and b0-17 + Tk[count].yxorb = y ^ (b & 0x3ffff); + + // get and store inverse of next bit from prng + // don't need to worry about shifting in the new bit because + // it doesn't affect the filter function anyway + hstate.shiftreg = hstate.shiftreg >> 1; + Tk[count].notb32 = hitag2_crypt(hstate.shiftreg) ^ 0x1; + + // increase count + count++; + } + } + + qsort(Tk, count, sizeof(struct Tklower), Tk_cmp); + + // look for matches + for (kmiddle=0; kmiddle<0x40000; kmiddle++) { + // loop over nRaR pairs + badguess = 0; + found = 0; + for (i=0; (i> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); + printf("\n\nSuccess - key = %012lX\n", foundkey); + exit(0); + + return (void *)foundkey; + } + + } + + } + } + + return NULL; +} +int main(int argc, char *argv[]) +{ + FILE *fp; + int i; + pthread_t threads[NUM_THREADS]; + void *status; + + uint64_t uid; + uint64_t klowerstart; + unsigned int numnrar = 0; + char *buf = NULL; + char *buft1 = NULL; + char *buft2 = NULL; + size_t lenbuf = 64; + + struct nRaR *TnRaR = NULL; + struct threaddata *tdata = NULL; + + if (argc < 3) { + printf("ht2crack3 uid nRaRfile\n"); + exit(1); + } + + // read the UID into internal format + if (!strncmp(argv[1], "0x", 2)) { + uid = rev32(hexreversetoulong(argv[1] + 2)); + } else { + uid = rev32(hexreversetoulong(argv[1])); + } + + // create table of nR aR pairs + TnRaR = (struct nRaR *)malloc(sizeof(struct nRaR) * NUM_NRAR); + + // open file + fp = fopen(argv[2], "r"); + if (!fp) { + printf("cannot open nRaRfile\n"); + exit(1); + } + + // set klowerstart (for debugging) + if (argc > 3) { + klowerstart = strtol(argv[3], NULL, 0); + } else { + klowerstart = 0; + } + + // read in nR aR pairs + numnrar = 0; + buf = (char *)malloc(lenbuf); + if (!buf) { + printf("cannot malloc buf\n"); + exit(1); + } + + while (getline(&buf, &lenbuf, fp) > 0) { + buft1 = strchr(buf, ' '); + if (!buft1) { + printf("invalid file input on line %d\n", numnrar + 1); + exit(1); + } + *buft1 = 0x00; + buft1++; + buft2 = strchr(buft1, '\n'); + if (!buft2) { + printf("no CR on line %d\n", numnrar + 1); + exit(1); + } + *buft2 = 0x00; + if (!strncmp(buf, "0x", 2)) { + TnRaR[numnrar].nR = rev32(hexreversetoulong(buf+2)); + TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1+2)); + } else { + TnRaR[numnrar].nR = rev32(hexreversetoulong(buf)); + TnRaR[numnrar].aR = rev32(hexreversetoulong(buft1)); + } + numnrar++; + } + + // close file + fclose(fp); + fp = NULL; + + printf("Loaded %d NrAr pairs\n", numnrar); + + // create table of thread data + tdata = (struct threaddata *)malloc(sizeof(struct threaddata) * NUM_THREADS); + if (!tdata) { + printf("cannot malloc threaddata\n"); + exit(1); + } + + for (i=0; i +#include + + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + + + +int main(int argc, char *argv[]) +{ + Hitag_State hstate; + FILE *fp; + char *line = NULL; + size_t linelen = 0; + long len = 0; + char *nr = NULL; + char *ar = NULL; + uint32_t arval; + uint32_t ks; + char *key; + char *uid; + + if (argc < 4) { + printf("ht2test nRaRfile KEY UID\n"); + exit(1); + } + + fp = fopen(argv[1], "r"); + if (!fp) { + printf("cannot open file\n"); + exit(1); + } + + if (!strncmp(argv[2], "0x", 2)) { + key = argv[2] + 2; + } else { + key = argv[2]; + } + + if (!strncmp(argv[3], "0x", 2)) { + uid = argv[3] + 2; + } else { + uid = argv[3]; + } + + while ((len = getline(&line, &linelen, fp)) > 0) { + if (len > 16) { + ar = strchr(line, ' '); + *ar = 0x00; + ar++; + ar[strlen(ar)-1] = 0x00; + if (!strncmp(line, "0x", 2)) { + nr = line + 2; + } else { + nr = line; + } + hitag2_init(&hstate, rev64(hexreversetoulonglong(key)), rev32(hexreversetoulong(uid)), rev32(hexreversetoulong(nr))); + + arval = strtol(ar, NULL, 16); + ks = hitag2_nstep(&hstate, 32); + + + if ((arval ^ ks) != 0xffffffff) { + printf("FAIL! nR = %s, aR = %s\n", line, ar); + } else { + printf("SUCCESS! nR = %s, aR = %s\n", line, ar); + } + } + } + + fclose(fp); + + return 0; +} + diff --git a/tools/hitag2crack/crack3/readme.md b/tools/hitag2crack/crack3/readme.md new file mode 100644 index 000000000..4d35ad7e0 --- /dev/null +++ b/tools/hitag2crack/crack3/readme.md @@ -0,0 +1,35 @@ +ht2crack3 + + + +Build +----- + +make clean +make + + +Run +--- + +You'll need a file consisting of 136 (or more) nR aR pairs. These are the +encrypted nonces and challenge response values. They should be in hex with +one pair per line, e.g.: +0x12345678 0x9abcdef0 + +./ht2crack3 UID NRARFILE + +UID is the UID of the tag that you used to gather the nR aR values. +NRARFILE is the file containing the nR aR values. + + +Tests +----- + +If you happen to know the key and want to check that all your nR aR values +are valid (for high-powered demonstrations only, really) then you can use +the ht2test program to check them. It's otherwise massively pointless and a +complete waste of space. + +./ht2test NRARFILE KEY UID + diff --git a/tools/hitag2crack/crack3/rfidler.h b/tools/hitag2crack/crack3/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack3/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#define TAG_TYPE_AWID_26 17 +#define TAG_TYPE_EM4X05 18 +#define TAG_TYPE_TAMAGOTCHI 19 +#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack3/util.h b/tools/hitag2crack/crack3/util.h new file mode 100644 index 000000000..c2399c37c --- /dev/null +++ b/tools/hitag2crack/crack3/util.h @@ -0,0 +1,147 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#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)) + + +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); + diff --git a/tools/hitag2crack/crack3/utilpart.c b/tools/hitag2crack/crack3/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack3/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +rtccTime RTC_time; // time structure +rtccDate RTC_date; // date structure + +// convert byte-reversed 8 digit hex to unsigned long +unsigned long hexreversetoulong(BYTE *hex) +{ + unsigned long ret= 0L; + unsigned int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +unsigned long long hexreversetoulonglong(BYTE *hex) +{ + unsigned long long ret= 0LL; + BYTE tmp[9]; + + // this may seem an odd way to do it, but weird compiler issues were + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/crack4/.gitignore b/tools/hitag2crack/crack4/.gitignore new file mode 100644 index 000000000..f7ca5917b --- /dev/null +++ b/tools/hitag2crack/crack4/.gitignore @@ -0,0 +1,3 @@ +ht2crack4 + +ht2crack4.exe diff --git a/tools/hitag2crack/crack4/HardwareProfile.h b/tools/hitag2crack/crack4/HardwareProfile.h new file mode 100644 index 000000000..a2f804be6 --- /dev/null +++ b/tools/hitag2crack/crack4/HardwareProfile.h @@ -0,0 +1,524 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + + +#ifndef HARDWARE_PROFILE_UBW32_H +#define HARDWARE_PROFILE_UBW32_H + +//#include "plib.h" +typedef char BOOL; +typedef char BYTE; +typedef int rtccTime; +typedef int rtccDate; + + +#ifndef __PIC32MX__ + #define __PIC32MX__ +#endif + +#define GetSystemClock() (80000000ul) +#define GetPeripheralClock() (GetSystemClock()) +#define GetInstructionClock() (GetSystemClock()) + +//#define USE_SELF_POWER_SENSE_IO +#define tris_self_power TRISAbits.TRISA2 // Input +#define self_power 1 + +//#define USE_USB_BUS_SENSE_IO +#define tris_usb_bus_sense TRISBbits.TRISB5 // Input +#define USB_BUS_SENSE 1 + +// LEDs +#define mLED_1 LATEbits.LATE3 + +#define mLED_2 LATEbits.LATE2 +#define mLED_Comms mLED_2 + +#define mLED_3 LATEbits.LATE1 +#define mLED_Clock mLED_3 + +#define mLED_4 LATEbits.LATE0 +#define mLED_Emulate mLED_4 + +#define mLED_5 LATGbits.LATG6 +#define mLED_Read mLED_5 + +#define mLED_6 LATAbits.LATA15 +#define mLED_User mLED_6 + +#define mLED_7 LATDbits.LATD11 +#define mLED_Error mLED_7 + +// active low +#define mLED_ON 0 +#define mLED_OFF 1 + +#define mGetLED_1() mLED_1 +#define mGetLED_USB() mLED_1 +#define mGetLED_2() mLED_2 +#define mGetLED_Comms() mLED_2 +#define mGetLED_3() mLED_3 +#define mGetLED_Clock() mLED_3 +#define mGetLED_4() mLED_4 +#define mGetLED_Emulate() mLED_4 +#define mGetLED_5() mLED_5 +#define mGetLED_Read() mLED_5 +#define mGetLED_6() mLED_6 +#define mGetLED_User() mLED_6 +#define mGetLED_7() mLED_7 +#define mGetLED_Error() mLED_7 + +#define mLED_1_On() mLED_1 = mLED_ON +#define mLED_USB_On() mLED_1_On() +#define mLED_2_On() mLED_2 = mLED_ON +#define mLED_Comms_On() mLED_2_On() +#define mLED_3_On() mLED_3 = mLED_ON +#define mLED_Clock_On() mLED_3_On() +#define mLED_4_On() mLED_4 = mLED_ON +#define mLED_Emulate_On() mLED_4_On() +#define mLED_5_On() mLED_5 = mLED_ON +#define mLED_Read_On() mLED_5_On() +#define mLED_6_On() mLED_6 = mLED_ON +#define mLED_User_On() mLED_6_On() +#define mLED_7_On() mLED_7 = mLED_ON +#define mLED_Error_On() mLED_7_On() + +#define mLED_1_Off() mLED_1 = mLED_OFF +#define mLED_USB_Off() mLED_1_Off() +#define mLED_2_Off() mLED_2 = mLED_OFF +#define mLED_Comms_Off() mLED_2_Off() +#define mLED_3_Off() mLED_3 = mLED_OFF +#define mLED_Clock_Off() mLED_3_Off() +#define mLED_4_Off() mLED_4 = mLED_OFF +#define mLED_Emulate_Off() mLED_4_Off() +#define mLED_5_Off() mLED_5 = mLED_OFF +#define mLED_Read_Off() mLED_5_Off() +#define mLED_6_Off() mLED_6 = mLED_OFF +#define mLED_User_Off() mLED_6_Off() +#define mLED_7_Off() mLED_7 = mLED_OFF +#define mLED_Error_Off() mLED_7_Off() + +#define mLED_1_Toggle() mLED_1 = !mLED_1 +#define mLED_USB_Toggle() mLED_1_Toggle() +#define mLED_2_Toggle() mLED_2 = !mLED_2 +#define mLED_Comms_Toggle() mLED_2_Toggle() +#define mLED_3_Toggle() mLED_3 = !mLED_3 +#define mLED_Clock_Toggle() mLED_3_Toggle() +#define mLED_4_Toggle() mLED_4 = !mLED_4 +#define mLED_Emulate_Toggle() mLED_4_Toggle() +#define mLED_5_Toggle() mLED_5 = !mLED_5 +#define mLED_Read_Toggle( ) mLED_5_Toggle() +#define mLED_6_Toggle() mLED_6 = !mLED_6 +#define mLED_User_Toggle() mLED_6_Toggle() +#define mLED_7_Toggle() mLED_7 = !mLED_7 +#define mLED_Error_Toggle() mLED_7_Toggle() + +#define mLED_All_On() { mLED_1_On(); mLED_2_On(); mLED_3_On(); mLED_4_On(); mLED_5_On(); mLED_6_On(); mLED_7_On(); } +#define mLED_All_Off() { mLED_1_Off(); mLED_2_Off(); mLED_3_Off(); mLED_4_Off(); mLED_5_Off(); mLED_6_Off(); mLED_7_Off(); } + +// usb status lights +#define mLED_Both_Off() {mLED_USB_Off();mLED_Comms_Off();} +#define mLED_Both_On() {mLED_USB_On();mLED_Comms_On();} +#define mLED_Only_USB_On() {mLED_USB_On();mLED_Comms_Off();} +#define mLED_Only_Comms_On() {mLED_USB_Off();mLED_Comms_On();} + +/** SWITCH *********************************************************/ +#define swBootloader PORTEbits.RE7 +#define swUser PORTEbits.RE6 + +/** I/O pin definitions ********************************************/ +#define INPUT_PIN 1 +#define OUTPUT_PIN 0 + +#define TRUE 1 +#define FALSE 0 + +#define ENABLE 1 +#define DISABE 0 + +#define EVEN 0 +#define ODD 1 + +#define LOW FALSE +#define HIGH TRUE + +#define CLOCK_ON LOW +#define CLOCK_OFF HIGH + +// output coil control - select between reader/emulator circuits +#define COIL_MODE LATBbits.LATB4 +#define COIL_MODE_READER() COIL_MODE= LOW +#define COIL_MODE_EMULATOR() COIL_MODE= HIGH + +// coil for emulation +#define COIL_OUT LATGbits.LATG9 +#define COIL_OUT_HIGH() COIL_OUT=HIGH +#define COIL_OUT_LOW() COIL_OUT=LOW + +// door relay (active low) +#define DOOR_RELAY LATAbits.LATA14 +#define DOOR_RELAY_OPEN() DOOR_RELAY= HIGH +#define DOOR_RELAY_CLOSE() DOOR_RELAY= LOW + +// inductance/capacitance freq +#define IC_FREQUENCY PORTAbits.RA2 + +#define SNIFFER_COIL PORTDbits.RD12 // external reader clock detect +#define READER_ANALOGUE PORTBbits.RB11 // reader coil analogue +#define DIV_LOW_ANALOGUE PORTBbits.RB12 // voltage divider LOW analogue +#define DIV_HIGH_ANALOGUE PORTBbits.RB13 // voltage divider HIGH analogue + +// clock coil (normally controlled by OC Module, but defined here so we can force it high or low) +#define CLOCK_COIL PORTDbits.RD4 +#define CLOCK_COIL_MOVED PORTDbits.RD0 // temporary for greenwire + +// digital output after analogue reader circuit +#define READER_DATA PORTDbits.RD8 + +// trace / debug +#define DEBUG_PIN_1 LATCbits.LATC1 +#define DEBUG_PIN_1_TOGGLE() DEBUG_PIN_1= !DEBUG_PIN_1 +#define DEBUG_PIN_2 LATCbits.LATC2 +#define DEBUG_PIN_2_TOGGLE() DEBUG_PIN_2= !DEBUG_PIN_2 +#define DEBUG_PIN_3 LATCbits.LATC3 +#define DEBUG_PIN_3_TOGGLE() DEBUG_PIN_3= !DEBUG_PIN_3 +#define DEBUG_PIN_4 LATEbits.LATE5 +#define DEBUG_PIN_4_TOGGLE() DEBUG_PIN_4= !DEBUG_PIN_4 + +// spi (sdi1) for sd card (not directly referenced) +//#define SD_CARD_RX LATCbits.LATC4 +//#define SD_CARD_TX LATDbits.LATD0 +//#define SD_CARD_CLK LATDbits.LATD10 +//#define SD_CARD_SS LATDbits.LATD9 +// spi for SD card +#define SD_CARD_DET LATFbits.LATF0 +#define SD_CARD_WE LATFbits.LATF1 // write enable - unused for microsd but allocated anyway as library checks it + // (held LOW by default - cut solder bridge to GND to free pin if required) +#define SPI_SD SPI_CHANNEL1 +#define SPI_SD_BUFF SPI1BUF +#define SPI_SD_STAT SPI1STATbits +// see section below for more defines! + +// iso 7816 smartcard +// microchip SC module defines pins so we don't need to, but +// they are listed here to help avoid conflicts +#define ISO_7816_RX LATBbits.LATF2 // RX +#define ISO_7816_TX LATBbits.LATF8 // TX +#define ISO_7816_VCC LATBbits.LATB9 // Power +#define ISO_7816_CLK LATCbits.LATD1 // Clock +#define ISO_7816_RST LATEbits.LATE8 // Reset + +// user LED +#define USER_LED LATDbits.LATD7 +#define USER_LED_ON() LATDbits.LATD7=1 +#define USER_LED_OFF() LATDbits.LATD7=0 + +// LCR +#define LCR_CALIBRATE LATBbits.LATB5 + +// wiegand / clock & data +#define WIEGAND_IN_0 PORTDbits.RD5 +#define WIEGAND_IN_0_PULLUP CNPUEbits.CNPUE14 +#define WIEGAND_IN_0_PULLDOWN CNPDbits.CNPD14 +#define WIEGAND_IN_1 PORTDbits.RD6 +#define WIEGAND_IN_1_PULLUP CNPUEbits.CNPUE15 +#define WIEGAND_IN_1_PULLDOWN CNPDbits.CNPD15 +#define CAND_IN_DATA WIEGAND_IN_0 +#define CAND_IN_CLOCK WIEGAND_IN_1 + +#define WIEGAND_OUT_0 LATDbits.LATD3 +#define WIEGAND_OUT_1 LATDbits.LATD2 +#define WIEGAND_OUT_0_TRIS TRISDbits.TRISD3 +#define WIEGAND_OUT_1_TRIS TRISDbits.TRISD2 +#define CAND_OUT_DATA WIEGAND_OUT_0 +#define CAND_OUT_CLOCK WIEGAND_OUT_1 + +// connect/disconnect reader clock from coil - used to send RWD signals by creating gaps in carrier +#define READER_CLOCK_ENABLE LATEbits.LATE9 +#define READER_CLOCK_ENABLE_ON() READER_CLOCK_ENABLE=CLOCK_ON +#define READER_CLOCK_ENABLE_OFF(x) {READER_CLOCK_ENABLE=CLOCK_OFF; COIL_OUT=x;} + +// these input pins must NEVER bet set to output or they will cause short circuits! +// they can be used to see data from reader before it goes into or gate +#define OR_IN_A PORTAbits.RA4 +#define OR_IN_B PORTAbits.RA5 + + +// CNCON and CNEN are set to allow wiegand input pin weak pullups to be switched on +#define Init_GPIO() { \ + CNCONbits.ON= TRUE; \ + CNENbits.CNEN14= TRUE; \ + CNENbits.CNEN15= TRUE; \ + TRISAbits.TRISA2= INPUT_PIN; \ + TRISAbits.TRISA4= INPUT_PIN; \ + TRISAbits.TRISA5= INPUT_PIN; \ + TRISAbits.TRISA14= OUTPUT_PIN; \ + TRISAbits.TRISA15= OUTPUT_PIN; \ + TRISBbits.TRISB4= OUTPUT_PIN; \ + TRISBbits.TRISB5= OUTPUT_PIN; \ + TRISBbits.TRISB9= OUTPUT_PIN; \ + TRISBbits.TRISB11= INPUT_PIN; \ + TRISBbits.TRISB12= INPUT_PIN; \ + TRISBbits.TRISB13= INPUT_PIN; \ + TRISCbits.TRISC1= OUTPUT_PIN; \ + TRISCbits.TRISC2= OUTPUT_PIN; \ + TRISCbits.TRISC3= OUTPUT_PIN; \ + TRISCbits.TRISC4= INPUT_PIN; \ + TRISDbits.TRISD0= INPUT_PIN; \ + TRISDbits.TRISD1= OUTPUT_PIN; \ + TRISDbits.TRISD2= OUTPUT_PIN; \ + TRISDbits.TRISD3= OUTPUT_PIN; \ + TRISDbits.TRISD4= OUTPUT_PIN; \ + TRISDbits.TRISD5= INPUT_PIN; \ + TRISDbits.TRISD6= INPUT_PIN; \ + TRISDbits.TRISD7= OUTPUT_PIN; \ + TRISDbits.TRISD8= INPUT_PIN; \ + TRISDbits.TRISD11= OUTPUT_PIN; \ + TRISDbits.TRISD12= INPUT_PIN; \ + TRISEbits.TRISE0= OUTPUT_PIN; \ + TRISEbits.TRISE1= OUTPUT_PIN; \ + TRISEbits.TRISE2= OUTPUT_PIN; \ + TRISEbits.TRISE3= OUTPUT_PIN; \ + TRISEbits.TRISE5= OUTPUT_PIN; \ + TRISEbits.TRISE6= INPUT_PIN; \ + TRISEbits.TRISE7= INPUT_PIN; \ + TRISEbits.TRISE8= OUTPUT_PIN; \ + TRISEbits.TRISE9= OUTPUT_PIN; \ + TRISFbits.TRISF0= INPUT_PIN; \ + TRISFbits.TRISF1= INPUT_PIN; \ + TRISFbits.TRISF2= INPUT_PIN; \ + TRISFbits.TRISF8= OUTPUT_PIN; \ + TRISGbits.TRISG6= OUTPUT_PIN; \ + TRISGbits.TRISG12= INPUT_PIN; \ + TRISGbits.TRISG13= INPUT_PIN; \ + TRISGbits.TRISG9= OUTPUT_PIN; \ + LATBbits.LATB9= LOW; \ + LATCbits.LATC1= LOW; \ + LATCbits.LATC2= LOW; \ + LATCbits.LATC3= LOW; \ + LATDbits.LATD2= WIEGAND_IN_1; \ + LATDbits.LATD3= WIEGAND_IN_0; \ + LATEbits.LATE5= LOW; \ + LATEbits.LATE9= HIGH; \ + } + +// uart3 (CLI/API) speed +#define BAUDRATE3 115200UL +#define BRG_DIV3 4 +#define BRGH3 1 + +// spi for potentiometer +#define SPI_POT SPI_CHANNEL4 +#define SPI_POT_BUFF SPI4BUF +#define SPI_POT_STAT SPI4STATbits + +// spi for sd card - defines required for Microchip SD-SPI libs +// define interface type +#define USE_SD_INTERFACE_WITH_SPI + +#define MDD_USE_SPI_1 +#define SPI_START_CFG_1 (PRI_PRESCAL_64_1 | SEC_PRESCAL_8_1 | MASTER_ENABLE_ON | SPI_CKE_ON | SPI_SMP_ON) +#define SPI_START_CFG_2 (SPI_ENABLE) +// Define the SPI frequency +#define SPI_FREQUENCY (20000000) +// Description: SD-SPI Card Detect Input bit +#define SD_CD PORTFbits.RF0 +// Description: SD-SPI Card Detect TRIS bit +#define SD_CD_TRIS TRISFbits.TRISF0 +// Description: SD-SPI Write Protect Check Input bit +#define SD_WE PORTFbits.RF1 +// Description: SD-SPI Write Protect Check TRIS bit +#define SD_WE_TRIS TRISFbits.TRISF1 +// Description: The main SPI control register +#define SPICON1 SPI1CON +// Description: The SPI status register +#define SPISTAT SPI1STAT +// Description: The SPI Buffer +#define SPIBUF SPI1BUF +// Description: The receive buffer full bit in the SPI status register +#define SPISTAT_RBF SPI1STATbits.SPIRBF +// Description: The bitwise define for the SPI control register (i.e. _____bits) +#define SPICON1bits SPI1CONbits +// Description: The bitwise define for the SPI status register (i.e. _____bits) +#define SPISTATbits SPI1STATbits +// Description: The enable bit for the SPI module +#define SPIENABLE SPICON1bits.ON +// Description: The definition for the SPI baud rate generator register (PIC32) +#define SPIBRG SPI1BRG +// Description: The TRIS bit for the SCK pin +#define SPICLOCK TRISDbits.TRISD10 +// Description: The TRIS bit for the SDI pin +#define SPIIN TRISCbits.TRISC4 +// Description: The TRIS bit for the SDO pin +#define SPIOUT TRISDbits.TRISD0 +#define SD_CS LATDbits.LATD9 +// Description: SD-SPI Chip Select TRIS bit +#define SD_CS_TRIS TRISDbits.TRISD9 +//SPI library functions +#define putcSPI putcSPI1 +#define getcSPI getcSPI1 +#define OpenSPI(config1, config2) OpenSPI1(config1, config2) + +// Define setup parameters for OpenADC10 function +// Turn module on | Ouput in integer format | Trigger mode auto | Enable autosample +#define ADC_CONFIG1 (ADC_FORMAT_INTG | ADC_CLK_AUTO | ADC_AUTO_SAMPLING_ON) +// ADC ref external | Disable offset test | Disable scan mode | Perform 2 samples | Use dual buffers | Use alternate mode +#define ADC_CONFIG2 (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_1 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) + +// Use ADC internal clock | Set sample time +#define ADC_CONFIG3 (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_0) + +// slow sample rate for tuning coils +#define ADC_CONFIG2_SLOW (ADC_VREF_AVDD_AVSS | ADC_OFFSET_CAL_DISABLE | ADC_SCAN_OFF | ADC_SAMPLES_PER_INT_16 | ADC_ALT_BUF_ON | ADC_ALT_INPUT_ON) +#define ADC_CONFIG3_SLOW (ADC_CONV_CLK_INTERNAL_RC | ADC_SAMPLE_TIME_31) + +// use AN11 +#define ADC_CONFIGPORT ENABLE_AN11_ANA +// Do not assign channels to scan +#define ADC_CONFIGSCAN SKIP_SCAN_ALL + +#define ADC_TO_VOLTS 0.003208F + + +// flash memory - int myvar = *(int*)(myflashmemoryaddress); + +// memory is 0x9D005000 to 0x9D07FFFF + +#define NVM_MEMORY_END 0x9D07FFFF +#define NVM_PAGE_SIZE 4096 +#define NVM_PAGES 2 // config & VTAG +#define RFIDLER_NVM_ADDRESS (NVM_MEMORY_END - (NVM_PAGE_SIZE * NVM_PAGES)) + +// UART timeout in us +#define SERIAL_TIMEOUT 100 + +#endif diff --git a/tools/hitag2crack/crack4/Makefile b/tools/hitag2crack/crack4/Makefile new file mode 100644 index 000000000..82e7f2560 --- /dev/null +++ b/tools/hitag2crack/crack4/Makefile @@ -0,0 +1,20 @@ +WARN=-Wall +CFLAGS=-c $(WARN) $(INCLUDE) +LIBS=-lpthread + +all: ht2crack4.c HardwareProfile.h rfidler.h util.h utilpart.o hitagcrypto.o ht2crack2utils.o + cc $(WARN) -o ht2crack4 ht2crack4.c utilpart.o hitagcrypto.o ht2crack2utils.o $(LIBS) + +utilpart.o: utilpart.c util.h + cc $(CFLAGS) utilpart.c + +hitagcrypto.o: hitagcrypto.c hitagcrypto.h + cc $(CFLAGS) hitagcrypto.c + +ht2crack2utils.o: ht2crack2utils.c ht2crack2utils.h + cc $(CFLAGS) ht2crack2utils.c + +clean: + rm -rf *.o ht2crack4 + +fresh: clean all diff --git a/tools/hitag2crack/crack4/hitagcrypto.c b/tools/hitag2crack/crack4/hitagcrypto.c new file mode 100644 index 000000000..422efbe92 --- /dev/null +++ b/tools/hitag2crack/crack4/hitagcrypto.c @@ -0,0 +1,485 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + +// uncomment this to build file as a standalone crypto test program +// #define UNIT_TEST +// also uncomment to include verbose debug prints +// #define TEST_DEBUG + +//#include +#include "HardwareProfile.h" +#include "rfidler.h" +#include "hitagcrypto.h" +#include "util.h" + +#ifdef UNIT_TEST +#include +#endif + +#if defined(UNIT_TEST) && defined(TEST_DEBUG) +// Note that printf format %I64x prints 64 bit ints in MS Visual C/C++. +// This may need changing for other compilers/platforms. +#define DEBUG_PRINTF(...) printf(__VA_ARGS__) +#else +#define DEBUG_PRINTF(...) +#endif + + +/* Brief info about NXP Hitag 1, Hitag 2, Hitag S and Hitag u (mu) + + Hitag 125kHz RFID was created by a company called Mikron (Mikron Gesellschaft + fur Integrierte Mikroelektronik Mbh), of Austria, for micropayment applications. + At about the same time, late 1980s to early 1990s, Mikron developed the + similarly featured Mifare micropayment card for 13.56MHz RFID. + (Mikron's European Patent EP 0473569 A2 was filed 23 August 1991, with a + priority date of 23 Aug 1990.) + Mikron was subsequently acquired by Philips Semiconductors in 1995. + Philips Semiconductors divsion subsequently became NXP. + + + Modulation read/write device -> transponder: 100 % ASK and binary pulse + length coding + + Modulation transponder -> read/write device: Strong ASK modulation, + selectable Manchester or Biphase coding + + Hitag S, Hitag u; anti-collision procedure + + Fast anti-collision protocol + + Hitag u; optional Cyclic Redundancy Check (CRC) + + Reader Talks First mode + + Hitag 2 & later; Transponder Talks First (TTF) mode + + Temporary switch from Transponder Talks First into Reader Talks First + (RTF) Mode + + Data rate read/write device to transponder: 5.2 kbit/s + + Data rates transponder to read/write device: 2 kbit/s, 4 kbit/s, 8 kbit/s + + 32-bit password feature + + Hitag 2, S = 32-bit Unique Identifier + + Hitag u = 48-bit Unique Identifier + + Selectable password modes for reader / tag mutual authentication + (Hitag 1 has 2 pairs of keys, later versions have 1 pair) + + Hitag 2 & Hitag S; Selectable encrypted mode, 48 bit key + + Known tag types: + + HITAG 1 2048 bits total memory + + HITAG 2 256 Bit total memory Read/Write + 8 pages of 32 bits, inc UID (32), + secret key (64), password (24), config (8) + + HITAG S 32 32 bits Unique Identifier Read Only + HITAG S 256 256 bits total memory Read/Write + HITAG S 2048 2048 bits total memory Read/Write + + HITAG u RO64 64 bits total memory Read Only + HITAG u 128 bits total memory Read/Write + HITAG u Advanced 512 bits total memory Read/Write + HITAG u Advanced+ 1760 bits total memory Read/Write + + Default 48-bit key for Hitag 2, S encryption: + "MIKRON" = O N M I K R + Key = 4F 4E 4D 49 4B 52 + +*/ + + +// We want the crypto functions to be as fast as possible, so optimize! +// The best compiler optimization in Microchip's free XC32 edition is -O1 +#pragma GCC optimize("O1") + +// private, nonlinear function to generate 1 crypto bit +static uint32_t hitag2_crypt(uint64_t x); + + +// macros to pick out 4 bits in various patterns of 1s & 2s & make a new number +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + + +static uint32_t hitag2_crypt(uint64_t s) +{ + const uint32_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 + const uint32_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 + const uint32_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + uint32_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + + DEBUG_PRINTF("hitag2_crypt bitindex = %02x\n", bitindex); + return (ht2_function5c >> bitindex) & 1; +} + +/* + * Parameters: + * Hitag_State* pstate - output, internal state after initialisation + * uint64_t sharedkey - 48 bit key shared between reader & tag + * uint32_t serialnum - 32 bit tag serial number + * uint32_t initvector - 32 bit random IV from reader, part of tag authentication + */ +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector) +{ + // init state, from serial number and lowest 16 bits of shared key + uint64_t state = ((sharedkey & 0xFFFF) << 32) | serialnum; + + // mix the initialisation vector and highest 32 bits of the shared key + initvector ^= (uint32_t) (sharedkey >> 16); + + // move 16 bits from (IV xor Shared Key) to top of uint64_t state + // these will be XORed in turn with output of the crypto function + state |= (uint64_t) initvector << 48; + initvector >>= 16; + + // unrolled loop is faster on PIC32 (MIPS), do 32 times + // shift register, then calc new bit + state >>= 1; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + // highest 16 bits of IV XOR Shared Key + state |= (uint64_t) initvector << 47; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state = (state >> 1) ^ (uint64_t) hitag2_crypt(state) << 46; + state ^= (uint64_t) hitag2_crypt(state) << 47; + + DEBUG_PRINTF("hitag2_init result = %012I64x\n", state); + pstate->shiftreg = state; + /* naive version for reference, LFSR has 16 taps + pstate->lfsr = state ^ (state >> 2) ^ (state >> 3) ^ (state >> 6) + ^ (state >> 7) ^ (state >> 8) ^ (state >> 16) ^ (state >> 22) + ^ (state >> 23) ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (state >> 42) ^ (state >> 43) ^ (state >> 46) ^ (state >> 47); + */ + { + // optimise with one 64-bit intermediate + uint64_t temp = state ^ (state >> 1); + pstate->lfsr = state ^ (state >> 6) ^ (state >> 16) + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); + } +} + + +/* + * Return up to 32 crypto bits. + * Last bit is in least significant bit, earlier bits are shifted left. + * Note that the Hitag transmission protocol is least significant bit, + * so we may want to change this, or add a function, that returns the + * crypto output bits in the other order. + * + * Parameters: + * Hitag_State* pstate - in/out, internal cipher state after initialisation + * uint32_t steps - number of bits requested, (capped at 32) + */ +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps) +{ + uint64_t state = pstate->shiftreg; + uint32_t result = 0; + uint64_t lfsr = pstate->lfsr; + + if (steps == 0) + return 0; + +// if (steps > 32) +// steps = 32; + + do { + // update shift registers + if (lfsr & 1) { + state = (state >> 1) | 0x800000000000; + lfsr = (lfsr >> 1) ^ 0xB38083220073; + + // accumulate next bit of crypto + result = (result << 1) | hitag2_crypt(state); + } else { + state >>= 1; + lfsr >>= 1; + + result = (result << 1) | hitag2_crypt(state); + } + } while (--steps); + + DEBUG_PRINTF("hitag2_nstep state = %012I64x, result %02x\n", state, result); + pstate->shiftreg = state; + pstate->lfsr = lfsr; + return result; +} + +// end of crypto core, revert to default optimization level +#pragma GCC reset_options + + +/* Test code + + Test data and below information about it comes from + http://www.mikrocontroller.net/attachment/102194/hitag2.c + Written by "I.C. Wiener 2006-2007" + + "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. + +*/ + + +/* +unsigned int hitag2_benchtest_gen32() +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + + // init crypto + hitag2_init(&state, key, serial, initvec); + + // benchmark: generation of 32 bit stream (excludes initialisation) + GetTimer_us(RESET); + + (void) hitag2_nstep(&state, 32); + + return GetTimer_us(NO_RESET); +} + + +unsigned int hitag2_benchtest(uint32_t count) +{ + const uint64_t key = 0x4ad292b272f2; + const uint32_t serial = 0x96eac292; + const uint32_t initvec = 0x4ea276a6; + Hitag_State state; + uint32_t i; + + // start timer + GetTimer_us(RESET); + + // benchmark: initialise crypto & generate 32 bit authentication + // adding i stops gcc optimizer moving init function call out of loop + for (i = 0; i < count; i++) { + hitag2_init(&state, key, serial, initvec + i); + (void) hitag2_nstep(&state, 32); + } + + return GetTimer_us(NO_RESET); +} + + +unsigned hitag2_verifytest() +{ + uint8_t expected[16] = { 0xD7, 0x23, 0x7F, 0xCE, 0x8C, 0xD0, 0x37, 0xA9, 0x57, 0x49, 0xC1, 0xE6, 0x48, 0x00, 0x8A, 0xB6 }; + // key = 0x4ad292b272f2 after each byte has its bit order reversed + // serial = 0x96eac292 ditto + // initvec = 0x4ea276a6 ditto + const uint64_t key = rev64 (0x524B494D4E4FUL); + const uint32_t serial = rev32 (0x69574349); + const uint32_t initvec = rev32 (0x72456E65); + + uint32_t i; + Hitag_State state; + + // initialise + hitag2_init(&state, key, serial, initvec); + + for (i = 0; i < 16; i++) { + // get 8 bits of keystream + uint8_t x = (uint8_t) hitag2_nstep(&state, 8); + uint8_t y = expected[i]; + + DEBUG_PRINTF ("%02X (%02X) \n", x, y); + if (x != y) + return 0; + } + + return 1; +} +*/ + +#ifdef UNIT_TEST + +int main(int argc, char* argv[]) +{ + unsigned pass = hitag2_verifytest(); + + printf ("Crypto Verify test = %s\n\n", pass ? "PASS" : "FAIL"); + + if (pass) { + hitag2_benchtest(10000); + } + + return 0; +} + +#endif // UNIT_TEST diff --git a/tools/hitag2crack/crack4/hitagcrypto.h b/tools/hitag2crack/crack4/hitagcrypto.h new file mode 100644 index 000000000..d5aa9104c --- /dev/null +++ b/tools/hitag2crack/crack4/hitagcrypto.h @@ -0,0 +1,171 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: unknown. +// Modifications for RFIDler: Tony Naggs , Adam Laurie + + +#ifndef HITAGCRYPTO_H +#define HITAGCRYPTO_H + +#include + +/* + Our model of Hitag 2 crypto uses 2 parallel shift registers: + a. 48 bit Feedback Shift Register, required for inputs to the nonlinear function. + b. 48 bit Linear Feedback Shift Register (LFSR). + A transform of initial register (a) value, which is then run in parallel. + Enables much faster calculation of the feedback values. + + API: + void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, + uint32_t initvector); + Initialise state from 48 bit shared (secret) reader/tag key, + 32 bit tag serial number and 32 bit initialisation vector from reader. + + uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + update shift register state and generate N cipher bits (N should be <= 32) + */ + + +typedef struct { + uint64_t shiftreg; // naive shift register, required for nonlinear fn input + uint64_t lfsr; // fast lfsr, used to make software faster +} Hitag_State; + +void hitag2_init(Hitag_State* pstate, uint64_t sharedkey, uint32_t serialnum, uint32_t initvector); + +uint32_t hitag2_nstep(Hitag_State* pstate, uint32_t steps); + +unsigned int hitag2_benchtest_gen32(); +unsigned int hitag2_benchtest(uint32_t count); +unsigned hitag2_verifytest(); + +#endif /* HITAGCRYPTO_H */ + diff --git a/tools/hitag2crack/crack4/ht2crack2utils.c b/tools/hitag2crack/crack4/ht2crack2utils.c new file mode 100644 index 000000000..2152f8ef3 --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack2utils.c @@ -0,0 +1,187 @@ +#include "ht2crack2utils.h" + +// writes a value into a buffer as a series of bytes +void writebuf(unsigned char *buf, uint64_t val, unsigned int len) +{ + int i; + char c; + + for (i=len-1; i>=0; i--) + { + c = val & 0xff; + buf[i] = c; + val = val >> 8; + } + +} + + +/* simple hexdump for testing purposes */ +void shexdump(unsigned char *data, int data_len) +{ + int i; + + if (!data || (data_len <= 0)) { + printf("shexdump: invalid parameters\n"); + return; + } + + printf("Hexdump from %p:\n", data); + + for (i=0; i> 7); + x = x << 1; + } + } + printf("\n"); +} + + +void printbin2(uint64_t val, unsigned int size) +{ + int i; + uint64_t mask = 1; + + mask = mask << (size - 1); + + for (i=0; ishiftreg, 48); + printf("\n"); +} + + + + +// convert hex char to binary +unsigned char hex2bin(unsigned char c) +{ + if ((c >= '0') && (c <= '9')) { + return (c - '0'); + } else if ((c >= 'a') && (c <= 'f')) { + return (c - 'a' + 10); + } else if ((c >= 'A') && (c <= 'F')) { + return (c - 'A' + 10); + } else { + return 0; + } +} + +// return a single bit from a value +int bitn(uint64_t x, int bit) +{ + uint64_t bitmask = 1; + + bitmask = bitmask << bit; + + if (x & bitmask) { + return 1; + } else { + return 0; + } +} + + +// the sub-function R that rollback depends upon +int fnR(uint64_t x) +{ + // renumbered bits because my state is 0-47, not 1-48 + return (bitn(x, 1) ^ bitn(x, 2) ^ bitn(x, 5) ^ bitn(x, 6) ^ bitn(x, 7) ^ + bitn(x, 15) ^ bitn(x, 21) ^ bitn(x, 22) ^ bitn(x, 25) ^ bitn(x, 29) ^ bitn(x, 40) ^ + bitn(x, 41) ^ bitn(x, 42) ^ bitn(x, 45) ^ bitn(x, 46) ^ bitn(x, 47)); +} + +// the rollback function that lets us go backwards in time +void rollback(Hitag_State *hstate, unsigned int steps) +{ + int i; + + for (i=0; ishiftreg = ((hstate->shiftreg << 1) & 0xffffffffffff) | fnR(hstate->shiftreg); + } + +} + + +// the three filter sub-functions that feed fnf +int fa(unsigned int i) +{ + return bitn(0x2C79, i); +} + +int fb(unsigned int i) +{ + return bitn(0x6671, i); +} + +int fc(unsigned int i) +{ + return bitn(0x7907287B, i); +} + +// the filter function that generates a bit of output from the prng state +int fnf(uint64_t s) +{ + unsigned int x1, x2, x3, x4, x5, x6; + + x1 = (bitn(s, 2) << 0) | (bitn(s, 3) << 1) | (bitn(s, 5) << 2) | (bitn(s, 6) << 3); + x2 = (bitn(s, 8) << 0) | (bitn(s, 12) << 1) | (bitn(s, 14) << 2) | (bitn(s, 15) << 3); + x3 = (bitn(s, 17) << 0) | (bitn(s, 21) << 1) | (bitn(s, 23) << 2) | (bitn(s, 26) << 3); + x4 = (bitn(s, 28) << 0) | (bitn(s, 29) << 1) | (bitn(s, 31) << 2) | (bitn(s, 33) << 3); + x5 = (bitn(s, 34) << 0) | (bitn(s, 43) << 1) | (bitn(s, 44) << 2) | (bitn(s, 46) << 3); + + x6 = (fa(x1) << 0) | (fb(x2) << 1) | (fb(x3) << 2) | (fb(x4) << 3) | (fa(x5) << 4); + + return fc(x6); +} + +// builds the lfsr for the prng (quick calcs for hitag2_nstep()) +void buildlfsr(Hitag_State *hstate) +{ + uint64_t state = hstate->shiftreg; + uint64_t temp; + + temp = state ^ (state >> 1); + hstate->lfsr = state ^ (state >> 6) ^ (state >> 16) + ^ (state >> 26) ^ (state >> 30) ^ (state >> 41) + ^ (temp >> 2) ^ (temp >> 7) ^ (temp >> 22) + ^ (temp >> 42) ^ (temp >> 46); +} + + + diff --git a/tools/hitag2crack/crack4/ht2crack2utils.h b/tools/hitag2crack/crack4/ht2crack2utils.h new file mode 100644 index 000000000..14eea840c --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack2utils.h @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "HardwareProfile.h" +#include "rfidler.h" +#include "util.h" + +#include "hitagcrypto.h" + +#define HEX_PER_ROW 16 + + + +void writebuf(unsigned char *buf, uint64_t val, unsigned int len); +void shexdump(unsigned char *data, int data_len); +void printbin(unsigned char *c); +void printbin2(uint64_t val, unsigned int size); +void printstate(Hitag_State *hstate); +unsigned char hex2bin(unsigned char c); +int bitn(uint64_t x, int bit); +int fnR(uint64_t x); +void rollback(Hitag_State *hstate, unsigned int steps); +int fa(unsigned int i); +int fb(unsigned int i); +int fc(unsigned int i); +int fnf(uint64_t s); +void buildlfsr(Hitag_State *hstate); diff --git a/tools/hitag2crack/crack4/ht2crack4.c b/tools/hitag2crack/crack4/ht2crack4.c new file mode 100644 index 000000000..da439692f --- /dev/null +++ b/tools/hitag2crack/crack4/ht2crack4.c @@ -0,0 +1,868 @@ +/* ht2crack4.c + * + * This is an implementation of the fast correlation attack in Section 4.4 of the + * paper, Lock It and Still Lose It - On the (In)Security of Automotive Remote + * Keyless Entry Systems by Garcia, Oswald, Kasper and Pavlides. + * It is essentially an attack on the HiTag2 cryptosystem; it uses a small number + * (between 4 and 32) of encrypted nonce and challenge response pairs for the same + * UID to recover the key. + * + * Key recovery is performed by enumerating all 65536 of the first 16 bits of the + * key and then, using the encrypted nonces and challenge response pairs, scoring + * all of the guesses for how likely they are to be the first 16 bits of the actual + * key. The best of these guesses are then expanded by 1 bit and the process + * iterates until all bits have been guessed. The resulting guesses are then searched + * for the one that is actually correct, testing against two pairs. + * + * The program reads in up to 32 encrypted nonce and challenge response pairs from + * the supplied file; the number actually used is specified on the command line + * (defaults to all those read in). The default size of the table is 800000 but this + * can be changed via the command line options. + * + * Using more encrypted nonce and challenge response pairs improves the chances of + * recovering the key and doesn't significantly add to the time it takes. + * + * Using a larger table also improves the chances of recovering the key but + * *significantly* increases the time it takes to run. + * + * Best recommendation is to use as many encrypted nonce and challenge response + * pairs as you can, and start with a table size of about 500000, as this will take + * around 45s to run. If it fails, run it again with a table size of 1000000, + * continuing to double the table size until it succeeds. Alternatively, start with + * a table size of about 3000000 and expect it to take around 4 mins to run, but + * with a high likelihood of success. + * + * Setting table size to a large number (~32000000) will likely blow up the stack + * during the recursive qsort(). This could be fixed by making the stack space + * larger but really, you need a smaller table and more encrypted nonces. + * + * The scoring of the guesses is controversial, having been tweaked over and again + * to find a measure that provides the best results. Feel free to tweak it yourself + * if you don't like it or want to try alternative metrics. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "ht2crack2utils.h" + +/* you could have more than 32 traces, but you shouldn't really need + * more than 16. You can still win with 8 if you're lucky. */ +#define MAX_NONCES 32 + +/* set this to the number of virtual cores you have */ +#define NUM_THREADS 8 + +/* encrypted nonce and keystream storage + * ks is ~enc_aR */ +struct nonce { + uint64_t enc_nR; + uint64_t ks; +}; + +/* guess table entry - we store key guesses and do the maths to convert + * to states in the code + * score is used for sorting purposes + * b0to31 is an array of the keystream generated from the init state + * that is later XORed with the encrypted nonce and key guess + */ +struct guess { + uint64_t key; + double score; + uint64_t b0to31[MAX_NONCES]; +}; + +/* thread_data is the data sent to the scoring threads */ +struct thread_data { + unsigned int start; + unsigned int end; + unsigned int size; +}; + +/* guess table and encrypted nonce/keystream table */ +struct guess *guesses = NULL; +unsigned int num_guesses; +struct nonce nonces[MAX_NONCES]; +unsigned int num_nRaR; +uint64_t uid; +int maxtablesize = 800000; +uint64_t supplied_testkey = 0; + +void usage() +{ + printf("ht2crack4 - K Sheldrake, based on the work of Garcia et al\n\n"); + printf("Cracks a HiTag2 key using a small number (4 to 16) of encrypted\n"); + printf("nonce and challenge response pairs, using a fast correlation\n"); + printf("approach.\n\n"); + printf(" -u UID (required)\n"); + printf(" -n NONCEFILE (required)\n"); + printf(" -N number of nRaR pairs to use (defaults to 32)\n"); + printf(" -t TABLESIZE (defaults to 800000\n"); + printf("Increasing the table size will slow it down but will be more\n"); + printf("successful.\n"); + + exit(1); +} + + +/* macros to select bits from lfsr states - from RFIDler code */ +#define pickbits2_2(S, A, B) ( ((S >> A) & 3) | ((S >> (B - 2)) & 0xC) ) +#define pickbits1x4(S, A, B, C, D) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 4) | ((S >> (D - 3)) & 8) ) +#define pickbits1_1_2(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 2) | \ + ((S >> (C - 2)) & 0xC) ) +#define pickbits2_1_1(S, A, B, C) ( ((S >> A) & 3) | ((S >> (B - 2)) & 4) | \ + ((S >> (C - 3)) & 8) ) +#define pickbits1_2_1(S, A, B, C) ( ((S >> A) & 1) | ((S >> (B - 1)) & 6) | \ + ((S >> (C - 3)) & 8) ) + +/* boolean tables for fns a, b and c - from RFIDler code */ +const uint64_t ht2_function4a = 0x2C79; // 0010 1100 0111 1001 +const uint64_t ht2_function4b = 0x6671; // 0110 0110 0111 0001 +const uint64_t ht2_function5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 + +/* following arrays are the probabilities of getting a 1 from each function, given + * a known least-sig pattern. first index is num bits in known part, second is the + * bit pattern of the known part. */ +double pfna[][8] = { +{0.50000, 0.50000, }, +{0.50000, 0.50000, 0.50000, 0.50000, }, +{0.50000, 0.00000, 0.50000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, +}; +double pfnb[][8] = { +{0.62500, 0.37500, }, +{0.50000, 0.75000, 0.75000, 0.00000, }, +{0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 1.00000, 1.00000, 0.00000, }, +}; +double pfnc[][16] = { +{0.50000, 0.50000, }, +{0.62500, 0.62500, 0.37500, 0.37500, }, +{0.75000, 0.50000, 0.25000, 0.75000, 0.50000, 0.75000, 0.50000, 0.00000, }, +{1.00000, 1.00000, 0.50000, 0.50000, 0.50000, 0.50000, 0.50000, 0.00000, 0.50000, 0.00000, 0.00000, 1.00000, 0.50000, 1.00000, 0.50000, 0.00000, }, +}; + + +/* hitag2_crypt works on the post-shifted form of the lfsr; this is the ref in rfidler code */ +static uint32_t hitag2_crypt(uint64_t s) +{ + uint32_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 1, 4)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 7, 11, 13)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 16, 20, 22, 25)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 27, 30, 32)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 33, 42, 45)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + +/* ht2crypt works on the pre-shifted form of the lfsr; this is the ref in the paper */ +uint64_t ht2crypt(uint64_t s) +{ + uint64_t bitindex; + + bitindex = (ht2_function4a >> pickbits2_2 (s, 2, 5)) & 1; + bitindex |= ((ht2_function4b << 1) >> pickbits1_1_2 (s, 8, 12, 14)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> pickbits1x4 (s, 17, 21, 23, 26)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> pickbits2_1_1 (s, 28, 31, 33)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> pickbits1_2_1(s, 34, 43, 46)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + + +/* fnL is the feedback function for the reference code */ +uint64_t fnL(uint64_t x) +{ + return (bitn(x, 0) ^ bitn(x, 2) ^ bitn(x, 3) ^ bitn(x, 6) ^ bitn(x, 7) ^ bitn(x, 8) ^ + bitn(x, 16) ^ bitn(x, 22) ^ bitn(x, 23) ^ bitn(x, 26) ^ bitn(x, 30) ^ bitn(x, 41) ^ + bitn(x, 42) ^ bitn(x, 43) ^ bitn(x, 46) ^ bitn(x, 47)); +} + + +/* packed_size is an array that maps the number of confirmed bits in a state to + * the number of relevant bits. + * e.g. if there are 16 confirmed bits in a state, then packed_size[16] = 8 relevant bits. + * this is for pre-shifted lfsr */ +unsigned int packed_size[] = { 0, 0, 0, 1, 2, 2, 3, 4, 4, 5, 5, 5, 5, 6, 6, 7, 8, + 8, 9, 9, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 14, 14, 15, + 15, 16, 17, 17, 17, 17, 17, 17, 17, 17, 17, 18, 19, 19, 20, 20 }; + + +/* f20 is the same as hitag2_crypt except it works on the packed version + * of the state where all 20 relevant bits are squashed together */ +uint64_t f20(uint64_t y) +{ + uint64_t bitindex; + + bitindex = (ht2_function4a >> (y & 0xf)) & 1; + bitindex |= ((ht2_function4b << 1) >> ((y >> 4) & 0xf)) & 0x02; + bitindex |= ((ht2_function4b << 2) >> ((y >> 8) & 0xf)) & 0x04; + bitindex |= ((ht2_function4b << 3) >> ((y >> 12) & 0xf)) & 0x08; + bitindex |= ((ht2_function4a << 4) >> ((y >> 16) & 0xf)) & 0x10; + + return (ht2_function5c >> bitindex) & 1; +} + + +/* packstate packs the relevant bits from LFSR state into 20 bits for pre-shifted lfsr */ +uint64_t packstate(uint64_t s) +{ + uint64_t packed; + + packed = pickbits2_2 (s, 2, 5); + packed |= (pickbits1_1_2 (s, 8, 12, 14) << 4); + packed |= (pickbits1x4 (s, 17, 21, 23, 26) << 8); + packed |= (pickbits2_1_1 (s, 28, 31, 33) << 12); + packed |= (pickbits1_2_1(s, 34, 43, 46) << 16); + + return packed; +} + + +/* create_guess_table mallocs the tables */ +void create_guess_table() +{ + guesses = (struct guess *)malloc(sizeof(struct guess) * maxtablesize); + if (!guesses) { + printf("cannot malloc guess table\n"); + exit(1); + } +} + + +/* init the guess table by reading in the encrypted nR,aR values and + * setting the first 2^16 key guesses */ +void init_guess_table(char *filename, char *uidstr) +{ + unsigned int i, j; + FILE *fp; + char *buf = NULL; + char *buft1 = NULL; + char *buft2 = NULL; + size_t lenbuf = 64; + + if (!guesses) { + printf("guesses is NULL\n"); + exit(1); + } + + // read uid + if (!strncmp(uidstr, "0x", 2)) { + uid = rev32(hexreversetoulong(uidstr + 2)); + } else { + uid = rev32(hexreversetoulong(uidstr)); + } + + + // read encrypted nonces and challenge response values + fp = fopen(filename, "r"); + if (!fp) { + printf("cannot open nRaR file\n"); + exit(1); + } + + num_nRaR = 0; + buf = (char *)malloc(lenbuf); + if (!buf) { + printf("cannot malloc buf\n"); + exit(1); + } + + while ((getline(&buf, &lenbuf, fp) > 0) && (num_nRaR < MAX_NONCES)) { + buft1 = strchr(buf, ' '); + if (!buft1) { + printf("invalid file input on line %d\n", num_nRaR + 1); + exit(1); + } + *buft1 = 0x00; + buft1++; + buft2 = strchr(buft1, '\n'); + if (!buft2) { + printf("no CR on line %d\n", num_nRaR + 1); + exit(1); + } + *buft2 = 0x00; + if (!strncmp(buf, "0x", 2)) { + nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf+2)); + nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1+2)) ^ 0xffffffff; + } else { + nonces[num_nRaR].enc_nR = rev32(hexreversetoulong(buf)); + nonces[num_nRaR].ks = rev32(hexreversetoulong(buft1)) ^ 0xffffffff; + } + num_nRaR++; + } + + fclose(fp); + fp = NULL; + + fprintf(stderr, "Loaded %d nRaR pairs\n", num_nRaR); + + // set key and copy in enc_nR and ks values + // set score to -1.0 to distinguish them from 0 scores + for (i=0; i<65536; i++) { + guesses[i].key = i; + guesses[i].score = -1.0; + for (j=0; j> (packed & 0xf)) & 1; + fncinput |= ((ht2_function4b << 1) >> ((packed >> 4) & 0xf)) & 0x02; + fncinput |= ((ht2_function4b << 2) >> ((packed >> 8) & 0xf)) & 0x04; + fncinput |= ((ht2_function4b << 3) >> ((packed >> 12) & 0xf)) & 0x08; + fncinput |= ((ht2_function4a << 4) >> ((packed >> 16) & 0xf)) & 0x10; + + // mask to keep the full nibble bits + fncinput = fncinput & ((1l << (n / 4)) - 1); + + if ((n % 4) == 0) { + // only complete nibbles + prob = pfnc[(n / 4) - 1][fncinput]; + } else { + // one nibble is incomplete + if (n <= 16) { + // it's in the fnb area + nibprob1 = pfnb[(n % 4) - 1][packed >> ((n / 4) * 4)]; + nibprob0 = 1.0 - nibprob1; + prob = (nibprob0 * pfnc[n / 4][fncinput]) + (nibprob1 * pfnc[n / 4][fncinput | (1l << (n / 4))]); + } else { + // it's in the final fna + nibprob1 = pfna[(n % 4) - 1][packed >> 16]; + nibprob0 = 1.0 - nibprob1; + prob = (nibprob0 * ((ht2_function5c >> fncinput) & 0x1)) + (nibprob1 * ((ht2_function5c >> (fncinput | 0x10)) & 0x1)); + } + } + } else { + // n==20 + prob = f20(packed); + } + + if (b1) { + return prob; + } else { + return (1.0 - prob); + } +} + + +/* score is like bit_score but does multiple bit correlation. + * bit_score and then shift and then repeat, adding all + * bit_scores together until no bits remain. bit_scores are + * multiplied by the number of relevant bits in the scored state + * to give weight to more complete states. */ +double score(uint64_t s, unsigned int size, uint64_t ks, unsigned int kssize) +{ + double sc, sc2; + + if ((size == 1) || (kssize == 1)) { + sc = bit_score(s, size, ks & 0x1); + return (sc * (packed_size[size] + 1)); + } else { + // I've introduced a weighting for each score to + // give more significance to bigger windows. + + sc = bit_score(s, size, ks & 0x1); + + // if a bit_score returns a probability of 0 then this can't be a winner + if (sc == 0.0) { + return 0.0; + } else { + + sc2 = score(s >> 1, size - 1, ks >> 1, kssize - 1); + + // if score returns a probability of 0 then this can't be a winner + if (sc2 == 0.0) { + return 0.0; + } else { + return (sc * (packed_size[size] + 1)) + sc2; + } + } + } +} + + +/* score_traces runs score for each encrypted nonce */ +void score_traces(struct guess *g, unsigned int size) +{ + uint64_t lfsr; + unsigned int i; + double sc; + double total_score = 0.0; + + // don't bother scoring traces that are already losers + if (g->score == 0.0) { + return; + } + + for (i=0; i> (size - 16)) | ((g->key << (48 - size)) ^ + ((nonces[i].enc_nR ^ g->b0to31[i]) << (64 - size))); + g->b0to31[i] = g->b0to31[i] | (ht2crypt(lfsr) << (size - 16)); + + // create lfsr - lower 16 bits are lower 16 bits of key + // bits 16-47 are upper bits of key XOR enc_nonce XOR bitstream + lfsr = g->key ^ ((nonces[i].enc_nR ^ g->b0to31[i]) << 16); + + sc = score(lfsr, size, nonces[i].ks, 32); + + // look out for losers + if (sc == 0.0) { + g->score = 0.0; + return; + } + total_score = total_score + sc; + } + + // save average score + g->score = total_score / num_nRaR; + +} + + +/* score_all_traces runs score_traces for every key guess in the table */ +/* this was used in the non-threaded version */ +/* +void score_all_traces(unsigned int size) +{ + unsigned int i; + + for (i=0; istart; iend; i++) { + score_traces(&(guesses[i]), tdata->size); + } + + return NULL; +} + + +/* score_all_traces runs score_traces for every key guess in the table */ +void score_all_traces(unsigned int size) +{ + pthread_t threads[NUM_THREADS]; + void *status; + struct thread_data tdata[NUM_THREADS]; + unsigned int i; + unsigned int chunk_size; + + chunk_size = num_guesses / NUM_THREADS; + + // create thread data + for (i=0; iscore < b1->score) { + return 1; + } else if (a1->score > b1->score) { + return -1; + } else { + return 0; + } +} + + +/* expand all guesses in first half of (sorted) table by + * copying them into the second half and extending the copied + * ones with an extra 1, leaving the first half with an extra 0 */ +void expand_guesses(unsigned int halfsize, unsigned int size) +{ + unsigned int i, j; + + for (i=0; i> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); + fprintf(stderr, " guess=%012" PRIx64 ", num_guesses = %d, top score=%1.10f, min score=%1.10f\n", foundkey, num_guesses, guesses[0].score, guesses[num_guesses - 1].score); + } +} + + +/* test function to make sure I know how the LFSR works */ +void testkey(uint64_t key) +{ + uint64_t i; + uint64_t b0to31 = 0; + uint64_t ks = 0; + uint64_t lfsr; + uint64_t nRxorkey; + Hitag_State hstate; + + printf("ORIG REFERENCE\n"); + hitag2_init(&hstate, key, uid, nonces[0].enc_nR); + printf("after init with key, uid, nR:\n"); + printstate(&hstate); + b0to31 = 0; + for (i=0; i<32; i++) { + b0to31 = (b0to31 >> 1) | (hitag2_nstep(&hstate, 1) << 31); + } + printf("ks = 0x%08" PRIx64 ", enc_aR = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 "\n", b0to31, nonces[0].ks ^ 0xffffffff, nonces[0].ks ^ 0xffffffff ^ b0to31); + printstate(&hstate); + + printf("\n"); + + + printf("MY REFERENCE\n"); + // build initial lfsr + lfsr = uid | ((key & 0xffff) << 32); + b0to31 = 0; + // xor upper part of key with encrypted nonce + nRxorkey = nonces[0].enc_nR ^ (key >> 16); + // insert keyupper xor encrypted nonce xor ks + for (i=0; i<32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + b0to31 = (b0to31 >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((b0to31 >> 31) & 0x1)) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } + printf("after init with key, uid, nR:\n"); + printf("lfsr =\t\t"); + printbin2(lfsr, 48); + printf("\n"); + + // iterate lfsr with fnL, extracting ks + for (i=0; i<32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + ks = (ks >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | (fnL(lfsr) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } + + printf("ks = 0x%08" PRIx64 ", aR = 0x%08" PRIx64 ", ks(orig) = 0x%08" PRIx64 ", aR(orig) = %08" PRIx64 "\n", ks, ks ^ 0xffffffff, nonces[0].ks, nonces[0].ks ^ 0xffffffff); + printf("lfsr = \t\t"); + printbin2(lfsr, 48); + printf("\n\n"); +} + + +/* test function to generate test data */ +void gen_bitstreams_testks(struct guess *g, uint64_t key) +{ + unsigned int i, j; + uint64_t nRxorkey, lfsr, ks; + + for (j=0; jb0to31[j] = 0; + // xor upper part of key with encrypted nonce + nRxorkey = nonces[j].enc_nR ^ (key >> 16); + // insert keyupper xor encrypted nonce xor ks + for (i=0; i<32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + g->b0to31[j] = (g->b0to31[j] >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | ((((nRxorkey >> i) & 0x1) ^ ((g->b0to31[j] >> 31) & 0x1)) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } + + ks = 0; + // iterate lfsr with fnL, extracting ks + for (i=0; i<32; i++) { + // store ks - when done, the first ks bit will be bit 0 and the last will be bit 31 + ks = (ks >> 1) | (ht2crypt(lfsr) << 31); + // insert new bit + lfsr = lfsr | (fnL(lfsr) << 48); + // shift lfsr + lfsr = lfsr >> 1; + } + + printf("orig ks = 0x%08" PRIx64 ", gen ks = 0x%08" PRIx64 ", b0to31 = 0x%08" PRIx64 "\n", nonces[j].ks, ks, g->b0to31[j]); + if (nonces[j].ks != ks) { + printf(" FAIL!\n"); + } + } +} + + +/* test function */ +void test() +{ + uint64_t lfsr; + uint64_t packed; + + uint64_t i; + + + for (i=0; i<1000; i++) { + lfsr = ((uint64_t)rand() << 32) | rand(); + packed = packstate(lfsr); + + if (hitag2_crypt(lfsr) != f20(packed)) { + printf(" * * * FAIL: %3" PRIu64 ": 0x%012" PRIx64 " = %d, 0x%012" PRIx64 " = 0x%05" PRIx64 "\n", i, lfsr, hitag2_crypt(lfsr), packed, f20(packed)); + } + } + + printf("test done\n"); +} + + +/* check_key tests the potential key against an encrypted nonce, ks pair */ +int check_key(uint64_t key, uint64_t enc_nR, uint64_t ks) +{ + Hitag_State hstate; + uint64_t bits; + int i; + + hitag2_init(&hstate, key, uid, enc_nR); + bits = 0; + for (i=0; i<32; i++) { + bits = (bits >> 1) | (hitag2_nstep(&hstate, 1) << 31); + } + if (ks == bits) { + return 1; + } else { + return 0; + } +} + + +/* start up */ +int main(int argc, char *argv[]) +{ + unsigned int i; + uint64_t revkey; + uint64_t foundkey; + int tot_nRaR = 0; + char c; + char *uidstr = NULL; + char *noncefilestr = NULL; + +// test(); +// exit(0); + + while ((c = getopt(argc, argv, "u:n:N:t:T:h")) != -1) { + switch(c) { + case 'u': + uidstr = optarg; + break; + case 'n': + noncefilestr = optarg; + break; + case 'N': + tot_nRaR = atoi(optarg); + break; + case 't': + maxtablesize = atoi(optarg); + break; + case 'T': + supplied_testkey = rev64(hexreversetoulonglong(optarg)); + break; + case 'h': + usage(); + break; + default: + usage(); + } + } + + if (!uidstr || !noncefilestr || (maxtablesize <= 0)) { + usage(); + } + + create_guess_table(); + + init_guess_table(noncefilestr, uidstr); + + if ((tot_nRaR > 0) && (tot_nRaR <= num_nRaR)) { + num_nRaR = tot_nRaR; + } + fprintf(stderr, "Using %d nRaR pairs\n", num_nRaR); + + crack(); + + // test all key guesses and stop if one works + for (i=0; i> 40) & 0xff) | ((revkey >> 24) & 0xff00) | ((revkey >> 8) & 0xff0000) | ((revkey << 8) & 0xff000000) | ((revkey << 24) & 0xff00000000) | ((revkey << 40) & 0xff0000000000); + printf("key = %012" PRIX64 "\n", foundkey); + exit(0); + } + } + + printf("FAIL :( - none of the potential keys in the table are correct.\n"); + exit(1); + return 0; +} + + + diff --git a/tools/hitag2crack/crack4/readme.md b/tools/hitag2crack/crack4/readme.md new file mode 100644 index 000000000..a906700b1 --- /dev/null +++ b/tools/hitag2crack/crack4/readme.md @@ -0,0 +1,29 @@ +ht2crack4 + + + +Build +----- + +make clean +make + + +Run +--- + +You'll need a file consisting of 16 (or more) nR aR pairs. These are the +encrypted nonces and challenge response values. They should be in hex with +one pair per line, e.g.: +0x12345678 0x9abcdef0 + +./ht2crack4 -u UID -n NRARFILE [-N nonces to use] [-t table size] + +UID is the UID of the tag that you used to gather the nR aR values. +NRARFILE is the file containing the nR aR values. +The number of nonces to use allows you to use less than 32 nonces to increase +speed. +The table size can be tweaked for speed. Start with 500000 and double it each +time it fails to find the key. + + diff --git a/tools/hitag2crack/crack4/rfidler.h b/tools/hitag2crack/crack4/rfidler.h new file mode 100644 index 000000000..c8ce90396 --- /dev/null +++ b/tools/hitag2crack/crack4/rfidler.h @@ -0,0 +1,412 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +#include +#include + +// BCD hardware revision for usb descriptor (usb_descriptors.c) +#define RFIDLER_HW_VERSION 0x020 + +// max sizes in BITS +#define MAXBLOCKSIZE 512 +#define MAXTAGSIZE 4096 +#define MAXUID 512 + +#define TMP_LARGE_BUFF_LEN 2048 +#define TMP_SMALL_BUFF_LEN 256 +#define ANALOGUE_BUFF_LEN 8192 + +#define COMMS_BUFFER_SIZE 128 + +#define DETECT_BUFFER_SIZE 512 + +#define SAMPLEMASK ~(BIT_1 | BIT_0) // mask to remove two bottom bits from analogue sample - we will then use those for reader & bit period + +// globals + +extern BOOL WiegandOutput; // Output wiegand data whenenver UID is read +extern BYTE *EMU_Reset_Data; // Pointer to full array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *EMU_Data; // Pointer to current location in EMU_Reset_Data +extern BYTE EMU_ThisBit; // The next data bit to transmit +extern BYTE EMU_SubCarrier_T0; // Number of Frame Clocks for sub-carrier '0' +extern BYTE EMU_SubCarrier_T1; // Number of Frame Clocks for sub-carrier '1' +extern unsigned int EMU_Repeat; // Number of times to transmit full data set +extern BOOL EMU_Background; // Emulate in the background until told to stop +extern unsigned int EMU_DataBitRate; // Number of Frame Clocks per bit +extern BYTE TmpBits[TMP_LARGE_BUFF_LEN]; // Shared scratchpad +extern BYTE ReaderPeriod; // Flag for sample display +extern unsigned char Comms_In_Buffer[COMMS_BUFFER_SIZE]; // USB/Serial buffer +extern BYTE Interface; // user interface - CLI or API +extern BYTE CommsChannel; // user comms channel - USB or UART +extern BOOL FakeRead; // flag for analogue sampler to signal it wants access to buffers during read +extern BOOL PWD_Mode; // is this tag password protected? +extern BYTE Password[9]; // 32 bits as HEX string set with LOGIN +extern unsigned int Led_Count; // LED status counter, also used for entropy +extern unsigned long Reader_Bit_Count; // Reader ISR bit counter +extern char Previous; // Reader ISR previous bit type + +// RWD (read/write device) coil state +extern BYTE RWD_State; // current state of RWD coil +extern unsigned int RWD_Fc; // field clock in uS +extern unsigned int RWD_Gap_Period; // length of command gaps in OC5 ticks +extern unsigned int RWD_Zero_Period; // length of '0' in OC5 ticks +extern unsigned int RWD_One_Period; // length of '1' in OC5 ticks +extern unsigned int RWD_Sleep_Period; // length of initial sleep to reset tag in OC5 ticks +extern unsigned int RWD_Wake_Period; // length required for tag to restart in OC5 ticks +extern unsigned int RWD_Wait_Switch_TX_RX; // length to wait when switching from TX to RX in OC5 ticks +extern unsigned int RWD_Wait_Switch_RX_TX; // length to wait when switching from RX to TX in OC5 ticks +extern unsigned int RWD_Post_Wait; // low level ISR wait period in OC5 ticks +extern unsigned int RWD_OC5_config; // Output Compare Module settings +extern unsigned int RWD_OC5_r; // Output Compare Module primary compare value +extern unsigned int RWD_OC5_rs; // Output Compare Module secondary compare value +extern BYTE RWD_Command_Buff[TMP_SMALL_BUFF_LEN]; // Command buffer, array of bits as bytes, stored as 0x00/0x01, '*' terminated +extern BYTE *RWD_Command_ThisBit; // Current command bit +extern BOOL Reader_ISR_State; // current state of reader ISR + +// NVM variables +// timings etc. that want to survive a reboot should go here +typedef struct { + BYTE Name[7]; // will be set to "RFIDler" so we can test for new device + BYTE AutoRun[128]; // optional command to run at startup + unsigned char TagType; + unsigned int PSK_Quality; + unsigned int Timeout; + unsigned int Wiegand_Pulse; + unsigned int Wiegand_Gap; + BOOL Wiegand_IdleState; + unsigned int FrameClock; + unsigned char Modulation; + unsigned int DataRate; + unsigned int DataRateSub0; + unsigned int DataRateSub1; + unsigned int DataBits; + unsigned int DataBlocks; + unsigned int BlockSize; + unsigned char SyncBits; + BYTE Sync[4]; + BOOL BiPhase; + BOOL Invert; + BOOL Manchester; + BOOL HalfDuplex; + unsigned int Repeat; + unsigned int PotLow; + unsigned int PotHigh; + unsigned int RWD_Gap_Period; + unsigned int RWD_Zero_Period; + unsigned int RWD_One_Period; + unsigned int RWD_Sleep_Period; + unsigned int RWD_Wake_Period; + unsigned int RWD_Wait_Switch_TX_RX; + unsigned int RWD_Wait_Switch_RX_TX; +} StoredConfig; + +// somewhere to store TAG data. this will be interpreted according to the TAG +// type. +typedef struct { + BYTE TagType; // raw tag type + BYTE EmulatedTagType; // tag type this tag is configured to emulate + BYTE UID[MAXUID + 1]; // Null-terminated HEX string + BYTE Data[MAXTAGSIZE]; // raw data + unsigned char DataBlocks; // number of blocks in Data field + unsigned int BlockSize; // blocksize in bits +} VirtualTag; + +extern StoredConfig RFIDlerConfig; +extern VirtualTag RFIDlerVTag; +extern BYTE TmpBuff[NVM_PAGE_SIZE]; +extern BYTE DataBuff[ANALOGUE_BUFF_LEN]; +extern unsigned int DataBuffCount; +extern const BYTE *ModulationSchemes[]; +extern const BYTE *OnOff[]; +extern const BYTE *HighLow[]; +extern const BYTE *TagTypes[]; + +// globals for ISRs +extern BYTE EmulationMode; +extern unsigned long HW_Bits; +extern BYTE HW_Skip_Bits; +extern unsigned int PSK_Min_Pulse; +extern BOOL PSK_Read_Error; +extern BOOL Manchester_Error; +extern BOOL SnifferMode; +extern unsigned int Clock_Tick_Counter; +extern BOOL Clock_Tick_Counter_Reset; + +// smart card lib +#define MAX_ATR_LEN (BYTE)33 +extern BYTE scCardATR[MAX_ATR_LEN]; +extern BYTE scATRLength; + +// RTC +extern rtccTime RTC_time; // time structure +extern rtccDate RTC_date; // date structure + +// digital pots +#define POTLOW_DEFAULT 100 +#define POTHIGH_DEFAULT 150 +#define DC_OFFSET 60 // analogue circuit DC offset (as close as we can get without using 2 LSB) +#define VOLTS_TO_POT 0.019607843F + +// RWD/clock states +#define RWD_STATE_INACTIVE 0 // RWD not in use +#define RWD_STATE_GO_TO_SLEEP 1 // RWD coil shutdown request +#define RWD_STATE_SLEEPING 2 // RWD coil shutdown for sleep period +#define RWD_STATE_WAKING 3 // RWD active for pre-determined period after reset +#define RWD_STATE_START_SEND 4 // RWD starting send of data +#define RWD_STATE_SENDING_GAP 5 // RWD sending a gap +#define RWD_STATE_SENDING_BIT 6 // RWD sending a data bit +#define RWD_STATE_POST_WAIT 7 // RWD finished sending data, now in forced wait period +#define RWD_STATE_ACTIVE 8 // RWD finished, now just clocking a carrier + +// reader ISR states +#define READER_STOPPED 0 // reader not in use +#define READER_IDLING 1 // reader ISR running to preserve timing, but not reading +#define READER_RUNNING 2 // reader reading bits + + +// user interface types +#define INTERFACE_API 0 +#define INTERFACE_CLI 1 + +// comms channel +#define COMMS_NONE 0 +#define COMMS_USB 1 +#define COMMS_UART 2 + +#define MAX_HISTORY 2 // disable most of history for now - memory issue + +// tag write retries +#define TAG_WRITE_RETRY 5 + +// modulation modes - uppdate ModulationSchemes[] in tags.c if you change this +#define MOD_MODE_NONE 0 +#define MOD_MODE_ASK_OOK 1 +#define MOD_MODE_FSK1 2 +#define MOD_MODE_FSK2 3 +#define MOD_MODE_PSK1 4 +#define MOD_MODE_PSK2 5 +#define MOD_MODE_PSK3 6 + +// TAG types - update TagTypes[] in tags.c if you add to this list +#define TAG_TYPE_NONE 0 +#define TAG_TYPE_ASK_RAW 1 +#define TAG_TYPE_FSK1_RAW 2 +#define TAG_TYPE_FSK2_RAW 3 +#define TAG_TYPE_PSK1_RAW 4 +#define TAG_TYPE_PSK2_RAW 5 +#define TAG_TYPE_PSK3_RAW 6 +#define TAG_TYPE_HITAG1 7 +#define TAG_TYPE_HITAG2 8 +#define TAG_TYPE_EM4X02 9 +#define TAG_TYPE_Q5 10 +#define TAG_TYPE_HID_26 11 +#define TAG_TYPE_INDALA_64 12 +#define TAG_TYPE_INDALA_224 13 +#define TAG_TYPE_UNIQUE 14 +#define TAG_TYPE_FDXB 15 +#define TAG_TYPE_T55X7 16 // same as Q5 but different timings and no modulation-defeat +#define TAG_TYPE_AWID_26 17 +#define TAG_TYPE_EM4X05 18 +#define TAG_TYPE_TAMAGOTCHI 19 +#define TAG_TYPE_HDX 20 // same underlying data as FDX-B, but different modulation & telegram + +// various + +#define BINARY 0 +#define HEX 1 + +#define NO_ADDRESS -1 + +#define ACK TRUE +#define NO_ACK FALSE + +#define BLOCK TRUE +#define NO_BLOCK FALSE + +#define DATA TRUE +#define NO_DATA FALSE + +#define DEBUG_PIN_ON HIGH +#define DEBUG_PIN_OFF LOW + +#define FAST FALSE +#define SLOW TRUE + +#define NO_TRIGGER 0 + +#define LOCK TRUE +#define NO_LOCK FALSE + +#define NFC_MODE TRUE +#define NO_NFC_MODE FALSE + +#define ONESHOT_READ TRUE +#define NO_ONESHOT_READ FALSE + +#define RESET TRUE +#define NO_RESET FALSE + +#define SHUTDOWN_CLOCK TRUE +#define NO_SHUTDOWN_CLOCK FALSE + +#define SYNC TRUE +#define NO_SYNC FALSE + +#define VERIFY TRUE +#define NO_VERIFY FALSE + +#define VOLATILE FALSE +#define NON_VOLATILE TRUE + +#define NEWLINE TRUE +#define NO_NEWLINE FALSE + +#define WAIT TRUE +#define NO_WAIT FALSE + +#define WIPER_HIGH 0 +#define WIPER_LOW 1 + +// conversion for time to ticks +#define US_TO_TICKS 1000000L +#define US_OVER_10_TO_TICKS 10000000L +#define US_OVER_100_TO_TICKS 100000000L +// we can't get down to this level on pic, but we want to standardise on timings, so for now we fudge it +#define CONVERT_TO_TICKS(x) ((x / 10) * (GetSystemClock() / US_OVER_10_TO_TICKS)) +#define CONVERT_TICKS_TO_US(x) (x / (GetSystemClock() / US_TO_TICKS)) +#define TIMER5_PRESCALER 16 +#define MAX_TIMER5_TICKS (65535 * TIMER5_PRESCALER) + +// other conversions + +// bits to hex digits +#define HEXDIGITS(x) (x / 4) +#define HEXTOBITS(x) (x * 4) diff --git a/tools/hitag2crack/crack4/util.h b/tools/hitag2crack/crack4/util.h new file mode 100644 index 000000000..c2399c37c --- /dev/null +++ b/tools/hitag2crack/crack4/util.h @@ -0,0 +1,147 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2015 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + +/* + * Hitag Crypto support macros + * These macros reverse the bit order in a byte, or *within* each byte of a + * 16 , 32 or 64 bit unsigned integer. (Not across the whole 16 etc bits.) + */ +#define rev8(X) ((((X) >> 7) &1) + (((X) >> 5) &2) + (((X) >> 3) &4) \ + + (((X) >> 1) &8) + (((X) << 1) &16) + (((X) << 3) &32) \ + + (((X) << 5) &64) + (((X) << 7) &128) ) +#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)) + + +unsigned long hexreversetoulong(BYTE *hex); +unsigned long long hexreversetoulonglong(BYTE *hex); + diff --git a/tools/hitag2crack/crack4/utilpart.c b/tools/hitag2crack/crack4/utilpart.c new file mode 100644 index 000000000..210853ec1 --- /dev/null +++ b/tools/hitag2crack/crack4/utilpart.c @@ -0,0 +1,183 @@ +/*************************************************************************** + * A copy of the GNU GPL is appended to this file. * + * * + * This licence is based on the nmap licence, and we express our gratitude * + * for the work that went into producing it. There is no other connection * + * between RFIDler and nmap either expressed or implied. * + * * + ********************** IMPORTANT RFIDler LICENSE TERMS ******************** + * * + * * + * All references to RFIDler herein imply all it's derivatives, namely: * + * * + * o RFIDler-LF Standard * + * o RFIDler-LF Lite * + * o RFIDler-LF Nekkid * + * * + * * + * RFIDler is (C) 2013-2014 Aperture Labs Ltd. * + * * + * This program is free software; you may redistribute and/or modify it * + * under the terms of the GNU General Public License as published by the * + * Free Software Foundation; Version 2 ("GPL"), BUT ONLY WITH ALL OF THE * + * CLARIFICATIONS AND EXCEPTIONS DESCRIBED HEREIN. This guarantees your * + * right to use, modify, and redistribute this software under certain * + * conditions. If you wish to embed RFIDler technology into proprietary * + * software or hardware, we sell alternative licenses * + * (contact sales@aperturelabs.com). * + * * + * Note that the GPL places important restrictions on "derivative works", * + * yet it does not provide a detailed definition of that term. To avoid * + * misunderstandings, we interpret that term as broadly as copyright law * + * allows. For example, we consider an application to constitute a * + * derivative work for the purpose of this license if it does any of the * + * following with any software or content covered by this license * + * ("Covered Software"): * + * * + * o Integrates source code from Covered Software. * + * * + * o Is designed specifically to execute Covered Software and parse the * + * results (as opposed to typical shell or execution-menu apps, which will * + * execute anything you tell them to). * + * * + * o Includes Covered Software in a proprietary executable installer. The * + * installers produced by InstallShield are an example of this. Including * + * RFIDler with other software in compressed or archival form does not * + * trigger this provision, provided appropriate open source decompression * + * or de-archiving software is widely available for no charge. For the * + * purposes of this license, an installer is considered to include Covered * + * Software even if it actually retrieves a copy of Covered Software from * + * another source during runtime (such as by downloading it from the * + * Internet). * + * * + * o Links (statically or dynamically) to a library which does any of the * + * above. * + * * + * o Executes a helper program, module, or script to do any of the above. * + * * + * This list is not exclusive, but is meant to clarify our interpretation * + * of derived works with some common examples. Other people may interpret * + * the plain GPL differently, so we consider this a special exception to * + * the GPL that we apply to Covered Software. Works which meet any of * + * these conditions must conform to all of the terms of this license, * + * particularly including the GPL Section 3 requirements of providing * + * source code and allowing free redistribution of the work as a whole. * + * * + * As another special exception to the GPL terms, Aperture Labs Ltd. grants* + * permission to link the code of this program with any version of the * + * OpenSSL library which is distributed under a license identical to that * + * listed in the included docs/licenses/OpenSSL.txt file, and distribute * + * linked combinations including the two. * + * * + * Any redistribution of Covered Software, including any derived works, * + * must obey and carry forward all of the terms of this license, including * + * obeying all GPL rules and restrictions. For example, source code of * + * the whole work must be provided and free redistribution must be * + * allowed. All GPL references to "this License", are to be treated as * + * including the terms and conditions of this license text as well. * + * * + * Because this license imposes special exceptions to the GPL, Covered * + * Work may not be combined (even as part of a larger work) with plain GPL * + * software. The terms, conditions, and exceptions of this license must * + * be included as well. This license is incompatible with some other open * + * source licenses as well. In some cases we can relicense portions of * + * RFIDler or grant special permissions to use it in other open source * + * software. Please contact sales@aperturelabs.com with any such requests.* + * Similarly, we don't incorporate incompatible open source software into * + * Covered Software without special permission from the copyright holders. * + * * + * If you have any questions about the licensing restrictions on using * + * RFIDler in other works, are happy to help. As mentioned above, we also * + * offer alternative license to integrate RFIDler into proprietary * + * applications and appliances. These contracts have been sold to dozens * + * of software vendors, and generally include a perpetual license as well * + * as providing for priority support and updates. They also fund the * + * continued development of RFIDler. Please email sales@aperturelabs.com * + * for further information. * + * If you have received a written license agreement or contract for * + * Covered Software stating terms other than these, you may choose to use * + * and redistribute Covered Software under those terms instead of these. * + * * + * Source is provided to this software because we believe users have a * + * right to know exactly what a program is going to do before they run it. * + * This also allows you to audit the software for security holes (none * + * have been found so far). * + * * + * Source code also allows you to port RFIDler to new platforms, fix bugs, * + * and add new features. You are highly encouraged to send your changes * + * to the RFIDler mailing list for possible incorporation into the * + * main distribution. By sending these changes to Aperture Labs Ltd. or * + * one of the Aperture Labs Ltd. development mailing lists, or checking * + * them into the RFIDler source code repository, it is understood (unless * + * you specify otherwise) that you are offering the RFIDler Project * + * (Aperture Labs Ltd.) the unlimited, non-exclusive right to reuse, * + * modify, and relicense the code. RFIDler will always be available Open * + * Source, but this is important because the inability to relicense code * + * has caused devastating problems for other Free Software projects (such * + * as KDE and NASM). We also occasionally relicense the code to third * + * parties as discussed above. If you wish to specify special license * + * conditions of your contributions, just say so when you send them. * + * * + * This program is distributed in the hope that it will be useful, but * + * WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the RFIDler * + * license file for more details (it's in a COPYING file included with * + * RFIDler, and also available from * + * https://github.com/ApertureLabsLtd/RFIDler/COPYING * + * * + ***************************************************************************/ + +// Author: Adam Laurie + + +#include +#include +#include "HardwareProfile.h" +#include "util.h" +#include "rfidler.h" +//#include "comms.h" + +// rtc +rtccTime RTC_time; // time structure +rtccDate RTC_date; // date structure + +// convert byte-reversed 8 digit hex to unsigned long +unsigned long hexreversetoulong(BYTE *hex) +{ + unsigned long ret= 0L; + unsigned int x; + BYTE i; + + if(strlen(hex) != 8) + return 0L; + + for(i= 0 ; i < 4 ; ++i) + { + if(sscanf(hex, "%2X", &x) != 1) + return 0L; + ret += ((unsigned long) x) << i * 8; + hex += 2; + } + return ret; +} + +// convert byte-reversed 12 digit hex to unsigned long +unsigned long long hexreversetoulonglong(BYTE *hex) +{ + unsigned long long ret= 0LL; + BYTE tmp[9]; + + // this may seem an odd way to do it, but weird compiler issues were + // breaking direct conversion! + + tmp[8]= '\0'; + memset(tmp + 4, '0', 4); + memcpy(tmp, hex + 8, 4); + ret= hexreversetoulong(tmp); + ret <<= 32; + memcpy(tmp, hex, 8); + ret += hexreversetoulong(tmp); + return ret; +} + + diff --git a/tools/hitag2crack/readme.md b/tools/hitag2crack/readme.md new file mode 100644 index 000000000..afbc5f4c3 --- /dev/null +++ b/tools/hitag2crack/readme.md @@ -0,0 +1,206 @@ +HiTag2 Cracking Suite +--------------------- + +Author: Kevin Sheldrake + +Introduction +------------ + +These tools are implementations of the four attacks detailed in the papers, +Gone In 360 Seconds - Hijacking With HiTag 2 by Roel Verdult, Flavio Garcia +and Josep Balasch, and Lock It And Still Lose It - on the (In)Security of +Automotive Remote Keyless Entry Systems by Flavio Garcia, David Oswald, +Timo Kasper and Pierre Pavlides. The first three attacks come from the first +paper and the fourth attack comes from the second paper. + +Attack 1 +-------- + +Attack 1 is a nonce replay and length extension attack. This is an attack on +a single HiTag2 RFID tag, given a single encrypted nonce and challenge +response value pair (nR, aR) for the tag's UID. The attack runs entirely on +the RFIDler with it acting like a RWD that replays the same encrypted nonce +and challenge response pair for every interaction; this fixes the key stream +that the tag's PRNG outputs to the same stream for every interaction. + +By brute forcing a subset of the encrypted command space, the RFIDler finds a +single valid encrypted command - invalid commands return a known unencrypted +error response so finding a valid one is simply a case of trying different +values until a response other than the error response is received. + +It then bit flips the valid encrypted command to find the other 15 valid +encrypted commands. By knowing the contents of page 0 - it's the UID that +is presented in clear at the start of each interaction - it tries each +encrypyted response in turn, assuming each to be the encrypted version of +'read page 0 non-inverted' and each response to be the encrypted version of +page 0. + +For each attempted command, it calculates the key stream that would have +correctly generated the encrypted command and response: +command ++ response XOR key stream = encrypted command ++ encrypted response +therefore: +key stream = command ++ response XOR encrypted command ++ encrypted response + +It then tests the potentially recovered key stream by creating an encrypted +command that consumes as much of it as possible, re-initialising with the same +encrypyted nonce and challenge response pair (to set the key stream to the +same stream as that which produced the encrypted command response it is +testing), and then sending this extended encrypted command. If the response +is not the error response, then the key stream is valid and the response is +the encryption of the page 0 contents (the UID). + +When one of the valid encrypted commands satisfies this situation, the +recovered key stream must be the output of the PRNG for the given encrypted +nonce and challenge response pair. + +The RFIDler then uses this key stream to encrypt commands and decrypt the +responses, and therefore requests the contents of all 8 pages. Pages 1 and 2 +contain the encryption key. + +Attack 2 +-------- + +Attack 2 is a time/space trade off to recover the key for situations where the +tag has been configured to prevent reading of pages 1 and 2. This attack uses +a pre-computed table of 2^37 PRNG states and resultant PRNG output, sorted on +the PRNG output. The RFIDler is used to recover 2048 bits of key stream using +a modification of attack 1 and this is used to search the table for matching +PRNG output. When the output is found, it is tested for validity (by testing +previous or following PRNG output) and then the PRNG state is rolled back to +the initialisation state, from which the unecrypted nonce and key can be +recovered. + +Attack 3 +-------- + +Attack 3 is a cryptanalytic attack that focuses on the RWD and a bias in the +PRNG output. By capturing 136 encrypted nonce and challenge response pairs, +candidates for the first 34 bits of the key can be identified, and for each +the remaining 14 bits can be brute forced. + +Attack 4 +-------- + +Attack 4 is a fast correlative attack on the key based on a number of captured +encrypted nonce and challenge response pairs (up to 32, but 16 usually +sufficient). It starts by guessing the first 16 bits of the key and scores +all these guesses against how likely they are to be the correct key, given the +encrypted nonces and the keystream they should produce. Each guess is then +expanded by 1 bit and the process iterates, with only the best guesses taken +forward to the next iteration. + +Usage details +------------- + +Attack 1 requires a valid tag and a valid encrypted nonce and challenge +response pair. The attacker needs to obtain a valid tag and then use this to +obtain a valid encrypted nonce and challenge response pair. This can be +acheived by using the RFIDler 'SNIFF-PWM S' command (having previously cleared +the nonce storage with 'SNIFF-PWM C'), placing the coil on the RWD and +presenting the valid tag. The encrypted nonce and challenge response pairs +can then be read out with the 'SNIFF-PWM L' command. These values can then +be used to attack the tag with 'HITAG2-CRACK '. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture encrypted nonce and challenge response pair (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: HITAG2-CRACK + +Attack 2 requires the same resources as attack 1, plus a pre-computed table. +The table can be generated on a disk with >1.5TB of storage, although it takes +some time (allow a couple of days). +./ht2crack2buildtable +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture encrypted nonce and challenge response pair (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: UID +RFIDler: HITAG2-KEYSTREAM +Copy/paste the key stream to a file. +./ht2crack2search + +Attack 3 requires only interaction with the RWD and does not require a valid +tag, although it does require a HiTag2 tag that the RWD will initially respond +to; e.g. you could potentially use any HiTag2 tag as long as the RWD starts +the crypto handshake with it. It requires >=136 encrypted nonce and challenge +response pairs for the same tag UID. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: SNIFF-PWM S +Capture >=136 encrypted nonce and challenge response pairs (nR, aR). +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L +RFIDler: UID +Copy/paste the encrypted nonce and challenge response pairs into a file. +./ht2crack3 + +Attack 4 requires the same information as attack 3, but only 16-32 encrypted +nonce and challenge response pairs are required. +./ht2crack4 -u -n [-N ] + [-t ] + +Start with -N 16 and -t 500000. If the attack fails to find the key, double +the table size and try again, repeating if it still fails. + +Once the key has been recovered using one of these attacks, the RFIDler can +be configured to operate as a RWD and will capture tags using that key. +RFIDler: SET TAG HITAG2 +RFIDler: HITAG2-READER + +Both the SNIFF-PWM and HITAG2-READER commands can be used as AUTORUN commands +for when the RFIDler is powered from a USB power supply without interaction. + +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM C +RFIDler: AUTORUN SNIFF-PWM S +RFIDler: SAVE +Capture encrypted nonce and challenge response pairs. +RFIDler: SET TAG HITAG2 +RFIDler: SNIFF-PWM L + + +RFIDler: SET TAG HITAG2 +RFIDler: HITAG2-CLEARSTOREDTAGS +RFIDler: AUTORUN HITAG2-READER S +RFIDler: SAVE +Capture tags. +RFIDler: HITAG2-COUNTSTOREDTAGS +RFIDler: HITAG2-LISTSTOREDTAGS [START] [END] + + +Tags can be copied with standard RFIDler commands. + +RFIDler: SET TAG HITAG2 +RFIDler: COPY +RFIDler: VTAG +Replace original tag with a blank tag. +RFIDler: CLONE + +OR: + +RFIDler: SET TAG HITAG2 +RFIDler: SET VTAG HITAG2 +RFIDler: VWRITE 0 +RFIDler: VWRITE 1 +... +RFIDler: VWRITE 7 +RFIDler: VTAG +Place blank tag on coil. +RFIDler: CLONE + +OR: + +RFIDler: SET TAG HITAG2 +RFIDler: SET VTAG HITAG2 +RFIDler: VWRITE 0 +RFIDler: VTAG +Place blank tag on coil. +RFIDler: CLONE + + diff --git a/traces/README.txt b/traces/README.txt index 0f89925a4..5eada015d 100644 --- a/traces/README.txt +++ b/traces/README.txt @@ -30,3 +30,7 @@ securakey-64169.pm3 Securakey Tag BitLen: 26, Card ID: 64169, FC: 0x35 motorola_0437_00072.pm3: Motorola Grey clamshell card, old. (RAW: A0000000E308C0C1) verichip_1022000000084146.pm3: VeriChip, epoxy encased glasschip (ID: 1022-00000000084146) + +sniff-ht2-BC3B8810-acg-reader.pm3: sniffing of Hitag2 being read by an HID ACG LF Multitag reader +sniff-ht2-BC3B8810-frosch-reader.pm3: sniffing of Hitag2 being read by a Frosch Hitag reader +sniff-ht2-BC3B8810-rfidler-reader.pm3: sniffing of Hitag2 being read by a RFIDler diff --git a/traces/sniff-ht2-BC3B8810-acg-reader.pm3 b/traces/sniff-ht2-BC3B8810-acg-reader.pm3 new file mode 100644 index 000000000..720492382 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-acg-reader.pm3 @@ -0,0 +1,2000 @@ +6 +6 +7 +7 +7 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +7 +7 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +7 +6 +6 +6 +6 +6 +6 +6 +6 +7 +7 +6 +6 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +6 +6 +6 +6 +6 +6 +5 +6 +6 +7 +6 +6 +6 +7 +6 +7 +6 +6 +6 +6 +6 +6 +7 +7 +6 +6 +6 +7 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +5 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +5 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +5 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +7 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +6 +7 +6 +6 +6 +7 +6 +5 +6 +6 +6 +5 +5 +-17 +-37 +-55 +-71 +-86 +-98 +-110 +-120 +-127 +3 +5 +-17 +-37 +-3 +59 +63 +46 +37 +41 +48 +47 +43 +39 +37 +36 +35 +33 +31 +29 +4 +-18 +-38 +-56 +-72 +-86 +-98 +-110 +-120 +-127 +18 +21 +-3 +-24 +14 +75 +78 +61 +51 +55 +61 +59 +54 +49 +48 +46 +43 +40 +38 +36 +11 +-13 +-33 +-52 +-68 +-82 +-95 +-107 +-117 +-126 +21 +23 +-1 +-23 +17 +77 +80 +63 +53 +56 +29 +4 +-18 +-38 +-55 +-71 +-85 +-98 +-109 +-119 +38 +41 +15 +-8 +31 +92 +94 +76 +65 +68 +40 +14 +-9 +-30 +-48 +-65 +-79 +-93 +-104 +-114 +44 +47 +21 +-3 +37 +97 +99 +79 +69 +72 +43 +17 +-6 +-28 +-46 +-63 +-77 +-91 +-103 +-113 +46 +48 +22 +-2 +38 +98 +99 +80 +70 +73 +77 +74 +68 +63 +60 +57 +54 +51 +48 +44 +42 +39 +38 +35 +33 +30 +30 +28 +37 +44 +50 +54 +55 +53 +52 +49 +48 +46 +44 +41 +39 +37 +35 +33 +31 +29 +28 +26 +25 +24 +23 +22 +20 +19 +19 +18 +17 +15 +15 +15 +14 +13 +13 +12 +12 +11 +11 +10 +11 +10 +10 +9 +9 +9 +9 +8 +8 +8 +8 +7 +7 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +7 +7 +7 +6 +6 +6 +6 +6 +5 +6 +5 +6 +5 +5 +5 +6 +5 +5 +5 +6 +5 +6 +5 +5 +6 +6 +5 +5 +5 +6 +5 +5 +5 +6 +5 +5 +5 +6 +6 +6 +5 +5 +6 +6 +5 +5 +6 +6 +5 +5 +5 +5 +6 +5 +5 +5 +5 +6 +5 +5 +5 +6 +5 +5 +5 +5 +5 +5 +4 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +6 +5 +5 +5 +5 +5 +5 +4 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +5 +30 +58 +77 +85 +85 +83 +82 +80 +78 +73 +69 +65 +62 +59 +56 +52 +30 +6 +-14 +-30 +-38 +-42 +-44 +-45 +-44 +-43 +-40 +-37 +-35 +-33 +-31 +-29 +-1 +29 +50 +58 +61 +62 +62 +61 +59 +57 +54 +51 +49 +46 +44 +42 +20 +-3 +-23 +-37 +-45 +-49 +-51 +-51 +-50 +-48 +-46 +-43 +-40 +-37 +-35 +-33 +-5 +26 +48 +56 +58 +58 +60 +59 +57 +54 +52 +49 +47 +44 +41 +39 +18 +-4 +-24 +-39 +-46 +-50 +-52 +-52 +-51 +-48 +-46 +-43 +-41 +-38 +-35 +-33 +-6 +25 +47 +56 +58 +58 +59 +59 +57 +54 +51 +49 +47 +44 +41 +39 +18 +-5 +-24 +-40 +-47 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-41 +-38 +-35 +-33 +-6 +24 +46 +55 +58 +58 +58 +58 +57 +54 +51 +48 +46 +44 +42 +39 +18 +-4 +-24 +-39 +-46 +-51 +-52 +-52 +-51 +-50 +-46 +-43 +-41 +-39 +-36 +-33 +-6 +25 +46 +55 +58 +58 +59 +58 +57 +54 +52 +48 +46 +44 +42 +39 +18 +-5 +-24 +-39 +-47 +-51 +-52 +-52 +-51 +-49 +-46 +-43 +-41 +-38 +-36 +-34 +-31 +-28 +-26 +-25 +-22 +-20 +-18 +-17 +-16 +-15 +-12 +-11 +-10 +-10 +-8 +-8 +18 +46 +67 +75 +76 +74 +74 +73 +70 +66 +63 +59 +57 +53 +50 +47 +44 +42 +40 +37 +34 +33 +31 +29 +27 +26 +25 +23 +22 +20 +20 +19 +0 +-22 +-40 +-54 +-60 +-64 +-65 +-65 +-62 +-59 +-56 +-53 +-49 +-46 +-43 +-41 +-13 +19 +41 +49 +52 +53 +55 +55 +53 +50 +48 +46 +44 +41 +38 +36 +16 +-7 +-26 +-41 +-48 +-52 +-54 +-55 +-52 +-50 +-47 +-45 +-42 +-39 +-36 +-34 +-7 +24 +46 +55 +57 +56 +58 +58 +56 +53 +51 +48 +46 +43 +41 +39 +18 +-5 +-24 +-39 +-47 +-50 +-52 +-53 +-52 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-7 +24 +46 +55 +57 +57 +58 +58 +57 +54 +51 +48 +47 +44 +41 +38 +18 +-5 +-25 +-40 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-41 +-39 +-36 +-34 +-32 +-29 +-27 +-24 +-23 +-21 +-19 +-17 +-15 +-14 +-13 +-12 +-10 +-9 +-9 +-9 +18 +47 +67 +74 +75 +74 +75 +72 +70 +66 +63 +59 +56 +53 +50 +47 +26 +2 +-18 +-34 +-41 +-45 +-47 +-48 +-47 +-45 +-42 +-40 +-38 +-35 +-33 +-30 +-4 +27 +49 +58 +60 +60 +60 +60 +59 +55 +52 +49 +47 +45 +42 +39 +18 +-4 +-24 +-39 +-46 +-50 +-51 +-52 +-51 +-49 +-45 +-43 +-40 +-39 +-35 +-33 +-6 +24 +46 +55 +58 +58 +58 +58 +57 +54 +51 +48 +46 +43 +41 +38 +17 +-5 +-25 +-40 +-47 +-51 +-52 +-53 +-51 +-49 +-46 +-43 +-41 +-39 +-36 +-33 +-6 +24 +46 +55 +57 +57 +58 +57 +56 +53 +50 +47 +46 +43 +41 +38 +36 +34 +32 +30 +28 +26 +26 +24 +22 +20 +20 +19 +18 +17 +16 +16 +-3 +-24 +-42 +-56 +-63 +-65 +-67 +-67 +-64 +-61 +-57 +-54 +-51 +-48 +-44 +-41 +-14 +17 +40 +49 +52 +52 +53 +53 +53 +50 +47 +44 +43 +40 +38 +35 +14 +-8 +-27 +-42 +-49 +-52 +-53 +-54 +-53 +-50 +-47 +-45 +-43 +-40 +-37 +-34 +-7 +23 +45 +54 +57 +56 +57 +57 +56 +53 +50 +47 +46 +43 +41 +38 +17 +-5 +-25 +-40 +-47 +-51 +-53 +-53 +-52 +-50 +-46 +-44 +-42 +-39 +-36 +-33 +-31 +-29 +-27 +-25 +-22 +-21 +-19 +-18 +-16 +-15 +-14 +-13 +-11 +-10 +-9 +-9 +17 +47 +66 +73 +74 +74 +74 +72 +69 +65 +62 +58 +55 +52 +49 +46 +44 +40 +38 +36 +35 +32 +30 +28 +28 +25 +24 +22 +21 +20 +19 +18 +-2 +-22 +-40 +-54 +-61 +-64 +-65 +-64 +-63 +-59 +-56 +-53 +-50 +-47 +-43 +-40 +-13 +17 +40 +49 +52 +53 +53 +53 +52 +50 +48 +45 +43 +41 +39 +35 +15 +-7 +-27 +-41 +-49 +-52 +-54 +-54 +-53 +-51 +-48 +-45 +-42 +-40 +-37 +-35 +-7 +23 +44 +53 +56 +57 +57 +56 +55 +53 +50 +47 +45 +42 +40 +38 +17 +-5 +-25 +-39 +-47 +-51 +-53 +-53 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-34 +-31 +-29 +-27 +-25 +-22 +-21 +-19 +-18 +-16 +-15 +-13 +-13 +-11 +-11 +-9 +-9 +17 +46 +66 +73 +74 +73 +73 +72 +69 +65 +62 +59 +56 +52 +49 +46 +25 +1 +-19 +-34 +-42 +-45 +-47 +-48 +-47 +-45 +-42 +-40 +-38 +-36 +-33 +-31 +-3 +26 +47 +56 +59 +58 +59 +58 +57 +54 +52 +48 +46 +44 +41 +39 +18 +-5 +-24 +-39 +-47 +-50 +-52 +-52 +-52 +-49 +-46 +-43 +-41 +-39 +-36 +-34 +-7 +24 +45 +54 +57 +57 +57 +57 +56 +53 +50 +47 +45 +42 +40 +37 +35 +33 +32 +30 +28 +26 +25 +24 +22 +20 +20 +19 +18 +16 +16 +15 +-4 +-25 +-43 +-56 +-63 +-66 +-67 +-67 +-64 +-61 +-58 +-55 +-52 +-48 +-44 +-42 +-39 +-36 +-33 +-31 +-28 +-27 +-24 +-22 +-20 +-19 +-18 +-16 +-14 +-14 +-13 +-12 +15 +44 +63 +70 +72 +72 +72 +70 +68 +64 +61 +57 +54 +51 +49 +46 +24 +0 +-20 +-35 +-42 +-46 +-49 +-49 +-47 +-46 +-43 +-41 +-38 +-36 +-33 +-31 +-5 +27 +48 +56 +58 +58 +59 +58 +56 +54 +51 +49 +46 +43 +41 +39 +18 +-5 +-24 +-39 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-35 +-33 +-6 +24 +45 +54 +57 +56 +57 +57 +56 +53 +49 +47 +45 +42 +39 +37 +16 +-6 +-25 +-40 +-47 +-51 +-52 +-53 +-52 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-8 +24 +45 +54 +56 +56 +57 +57 +56 +52 +50 +47 +45 +42 +40 +37 +16 +-6 +-25 +-40 +-47 +-51 +-52 +-53 +-52 +-50 +-46 +-44 +-42 +-39 +-36 +-34 +-7 +23 +45 +54 +56 +57 +57 +57 +56 +53 +50 +47 +45 +43 +40 +37 +16 +-6 +-25 +-40 +-48 +-51 +-53 +-53 +-52 +-50 +-47 +-44 +-41 +-39 +-36 +-34 +-6 +24 +45 +54 +56 +56 +57 +56 +55 +53 +50 +46 +44 +42 +40 +37 +35 +33 +31 +29 +27 +26 +25 +23 +22 +20 +19 +18 +18 +16 +15 +14 +-5 +-25 +-43 +-57 +-63 +-66 +-67 +-67 +-64 +-61 +-57 +-55 +-51 +-48 +-44 +-42 +-39 +-37 +-33 +-31 +-29 +-28 +-25 +-23 +-21 +-20 +-18 +-16 +-14 +-14 +-13 +-12 +14 +43 +63 +70 +72 +71 +71 +69 +67 +64 +60 +56 +53 +51 +48 +45 +23 +0 +-20 +-35 +-43 +-47 +-49 +-49 +-47 +-46 +-44 +-41 +-38 +-36 +-34 +-32 +-4 +26 +47 +55 +57 +58 +59 +58 +56 +53 +51 +48 +45 +42 +40 +39 +17 +-5 +-25 +-39 +-46 +-50 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-36 +-34 +-8 +23 +45 +54 +56 +56 +57 +57 +55 +52 +50 +47 +45 +42 +39 +37 +16 +-6 +-26 +-40 +-47 +-51 +-53 +-54 +-52 +-49 +-47 +-45 +-42 +-39 +-36 +-34 +-8 +23 +44 +53 +56 +56 +56 +57 +55 +52 +49 +46 +43 +40 +37 +35 +11 +-13 +-35 +-54 +-71 +-85 +-96 +-104 +-107 +-106 +-103 +-99 +-95 +-89 +-83 +-79 +-74 +-69 +-64 +-60 +-56 +-52 +-49 +-45 +-42 +-39 +-36 +-34 +-31 +-29 +-27 +-25 +-22 +-20 +-19 +-18 +-16 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-8 +-6 +-5 +-5 +-5 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +2 +2 +2 +1 +2 +2 +2 +2 +2 +2 +3 +2 +2 +2 +3 +3 +3 +2 +2 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +4 +3 +3 +4 +4 +3 +3 +3 +4 +4 +3 +3 +3 +3 +3 +3 +3 +4 +4 +3 +3 +3 +4 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +4 +3 +4 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +4 +4 +3 +3 +4 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +2 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +3 +3 +3 +3 +3 +3 +4 +4 +4 +3 +4 +4 +4 +3 +3 +3 +3 +3 +3 +3 +4 +3 +3 +3 +4 +3 +3 +3 +4 +4 +4 +3 +4 +3 +4 +3 diff --git a/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 b/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 new file mode 100644 index 000000000..2a6afbf95 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-frosch-reader.pm3 @@ -0,0 +1,5000 @@ +14 +14 +15 +15 +14 +14 +14 +15 +14 +14 +13 +14 +14 +14 +13 +14 +14 +14 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +14 +15 +14 +15 +14 +15 +14 +15 +14 +14 +14 +15 +14 +14 +14 +15 +15 +14 +14 +14 +14 +14 +13 +14 +14 +15 +14 +14 +14 +15 +13 +13 +13 +14 +14 +14 +13 +14 +14 +14 +14 +14 +14 +14 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +13 +14 +13 +14 +13 +14 +14 +14 +14 +13 +13 +14 +14 +14 +14 +14 +14 +13 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +14 +14 +14 +13 +14 +14 +15 +14 +14 +14 +14 +14 +13 +14 +14 +14 +13 +13 +13 +13 +13 +13 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +13 +13 +13 +14 +14 +14 +13 +13 +13 +13 +13 +13 +13 +14 +14 +13 +13 +14 +14 +14 +13 +14 +14 +14 +13 +13 +13 +14 +13 +14 +13 +14 +12 +13 +12 +13 +13 +13 +13 +14 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +13 +13 +14 +14 +13 +13 +13 +13 +14 +13 +14 +13 +14 +13 +14 +13 +14 +14 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +12 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +13 +12 +13 +13 +12 +12 +12 +13 +13 +13 +12 +13 +13 +13 +12 +13 +13 +13 +13 +13 +13 +13 +13 +12 +12 +13 +13 +12 +12 +12 +13 +13 +12 +13 +13 +14 +13 +13 +13 +13 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +13 +13 +13 +13 +13 +13 +12 +12 +12 +13 +12 +12 +12 +12 +12 +12 +12 +12 +13 +13 +12 +13 +13 +13 +12 +12 +12 +13 +13 +12 +12 +12 +12 +12 +12 +13 +12 +13 +11 +12 +12 +12 +12 +12 +12 +12 +13 +12 +12 +12 +13 +12 +12 +12 +13 +13 +12 +12 +12 +12 +11 +12 +12 +12 +12 +11 +11 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +12 +11 +11 +12 +12 +11 +12 +12 +12 +12 +12 +11 +12 +12 +12 +11 +12 +12 +12 +11 +11 +12 +12 +12 +12 +11 +12 +12 +12 +11 +12 +12 +12 +11 +11 +11 +12 +12 +11 +11 +12 +12 +11 +11 +12 +12 +12 +11 +12 +11 +12 +11 +11 +11 +12 +12 +12 +12 +12 +12 +11 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +11 +11 +11 +11 +11 +12 +12 +12 +12 +11 +12 +11 +11 +11 +11 +11 +11 +10 +11 +11 +12 +11 +11 +11 +12 +11 +11 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +10 +11 +10 +10 +11 +11 +11 +-18 +-44 +-67 +-88 +-106 +-122 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-52 +7 +48 +75 +91 +99 +103 +104 +102 +99 +95 +90 +86 +82 +46 +13 +-15 +-41 +-64 +-84 +-102 +-118 +-127 +-127 +-127 +-127 +-127 +-103 +-21 +36 +75 +100 +116 +117 +117 +117 +117 +117 +113 +107 +101 +95 +58 +24 +-6 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-97 +-15 +42 +80 +105 +117 +117 +117 +117 +87 +51 +18 +-11 +-37 +-60 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-75 +7 +64 +103 +117 +117 +117 +117 +117 +102 +64 +30 +0 +-27 +-51 +-72 +-91 +-107 +-123 +-127 +-127 +-127 +-68 +14 +71 +109 +117 +117 +117 +117 +117 +117 +102 +64 +30 +0 +-27 +-51 +-72 +-91 +-108 +-123 +-127 +-127 +-127 +-71 +10 +67 +105 +117 +117 +117 +117 +117 +117 +117 +117 +117 +116 +110 +103 +98 +91 +86 +81 +77 +72 +68 +63 +66 +67 +67 +65 +63 +61 +59 +56 +53 +50 +48 +46 +43 +41 +40 +38 +36 +33 +32 +30 +30 +28 +27 +26 +25 +23 +22 +21 +21 +20 +20 +18 +18 +18 +18 +17 +16 +16 +16 +15 +14 +14 +14 +14 +13 +12 +13 +13 +13 +12 +12 +11 +12 +12 +12 +11 +11 +11 +11 +10 +11 +11 +11 +11 +10 +11 +11 +10 +10 +9 +10 +10 +10 +9 +10 +9 +10 +9 +10 +10 +10 +9 +9 +9 +9 +9 +8 +8 +9 +10 +9 +9 +9 +9 +9 +9 +9 +9 +10 +9 +9 +9 +10 +9 +9 +8 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +9 +8 +8 +9 +9 +9 +9 +9 +10 +10 +10 +9 +10 +9 +9 +8 +9 +9 +9 +8 +8 +9 +9 +9 +9 +9 +9 +10 +10 +9 +9 +9 +9 +9 +9 +8 +9 +8 +8 +8 +9 +9 +9 +9 +9 +9 +9 +8 +8 +8 +16 +24 +30 +34 +37 +39 +40 +39 +38 +37 +37 +35 +34 +32 +31 +29 +18 +10 +4 +-1 +-5 +-8 +-9 +-9 +-10 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +4 +12 +18 +23 +27 +29 +30 +30 +30 +29 +29 +27 +27 +26 +26 +24 +14 +6 +0 +-5 +-9 +-11 +-12 +-12 +-12 +-12 +-12 +-11 +-9 +-9 +-8 +-7 +2 +10 +17 +22 +26 +28 +29 +29 +29 +29 +28 +27 +27 +26 +25 +24 +14 +6 +-1 +-5 +-9 +-11 +-12 +-12 +-13 +-13 +-12 +-11 +-10 +-10 +-8 +-7 +2 +10 +17 +21 +25 +27 +28 +28 +29 +28 +27 +26 +26 +25 +24 +23 +14 +6 +-1 +-6 +-10 +-11 +-12 +-13 +-13 +-13 +-12 +-11 +-10 +-10 +-9 +-8 +2 +10 +17 +22 +26 +27 +28 +28 +29 +28 +27 +26 +25 +25 +24 +23 +13 +5 +-1 +-6 +-10 +-12 +-13 +-13 +-13 +-14 +-12 +-12 +-10 +-10 +-9 +-8 +2 +10 +16 +21 +25 +27 +28 +29 +29 +29 +28 +26 +26 +25 +24 +22 +13 +5 +-1 +-7 +-11 +-12 +-13 +-14 +-14 +-13 +-12 +-11 +-11 +-11 +-9 +-8 +-7 +-7 +-6 +-5 +-3 +-4 +-3 +-2 +0 +0 +0 +1 +1 +2 +2 +2 +11 +19 +25 +29 +32 +33 +35 +35 +34 +33 +33 +31 +30 +27 +26 +25 +25 +23 +22 +21 +21 +20 +19 +18 +18 +17 +16 +15 +15 +15 +15 +13 +5 +-3 +-9 +-14 +-17 +-19 +-19 +-20 +-19 +-19 +-17 +-16 +-15 +-14 +-13 +-12 +-3 +5 +13 +18 +22 +24 +25 +26 +27 +26 +25 +24 +24 +23 +22 +21 +12 +4 +-3 +-8 +-11 +-13 +-14 +-15 +-15 +-14 +-13 +-13 +-12 +-11 +-9 +-9 +0 +8 +16 +20 +24 +25 +27 +27 +28 +27 +26 +26 +25 +24 +22 +22 +12 +5 +-2 +-8 +-11 +-13 +-14 +-15 +-14 +-14 +-13 +-13 +-12 +-11 +-10 +-10 +-1 +7 +16 +21 +24 +25 +27 +28 +28 +27 +26 +25 +25 +24 +22 +22 +13 +4 +-3 +-8 +-10 +-12 +-13 +-15 +-14 +-14 +-13 +-13 +-12 +-11 +-9 +-9 +-8 +-8 +-7 +-5 +-5 +-4 +-3 +-3 +-2 +-2 +-2 +-1 +0 +0 +1 +1 +10 +17 +24 +27 +31 +32 +33 +33 +33 +32 +32 +30 +28 +27 +26 +25 +15 +7 +0 +-5 +-9 +-11 +-12 +-12 +-12 +-12 +-11 +-11 +-10 +-9 +-9 +-8 +1 +10 +16 +21 +24 +26 +27 +27 +27 +26 +26 +25 +24 +23 +23 +21 +12 +4 +-2 +-7 +-11 +-14 +-14 +-15 +-14 +-14 +-13 +-12 +-12 +-11 +-11 +-10 +-1 +7 +14 +19 +23 +25 +26 +26 +26 +26 +26 +24 +24 +23 +23 +21 +11 +4 +-3 +-8 +-11 +-14 +-15 +-15 +-15 +-15 +-14 +-13 +-12 +-11 +-11 +-11 +-1 +7 +15 +19 +23 +25 +27 +26 +26 +26 +25 +24 +23 +22 +22 +20 +19 +18 +18 +16 +16 +15 +14 +14 +14 +13 +12 +12 +12 +11 +11 +10 +2 +-5 +-11 +-16 +-19 +-20 +-21 +-21 +-21 +-19 +-18 +-18 +-17 +-16 +-14 +-13 +-4 +4 +12 +17 +20 +22 +23 +24 +24 +24 +23 +22 +21 +20 +20 +19 +10 +2 +-4 +-10 +-13 +-15 +-16 +-17 +-16 +-16 +-15 +-14 +-14 +-13 +-11 +-11 +-2 +7 +14 +18 +22 +23 +25 +26 +26 +25 +25 +24 +23 +22 +21 +20 +11 +3 +-4 +-9 +-12 +-14 +-15 +-16 +-16 +-15 +-14 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-7 +-6 +-6 +-5 +-4 +-3 +-3 +-3 +-2 +-2 +-2 +-1 +-1 +8 +16 +22 +26 +29 +31 +32 +31 +31 +31 +30 +28 +27 +26 +25 +23 +22 +21 +21 +19 +18 +17 +17 +16 +15 +13 +13 +13 +12 +11 +11 +11 +2 +-6 +-12 +-16 +-19 +-21 +-22 +-22 +-21 +-21 +-20 +-19 +-18 +-17 +-15 +-14 +-5 +4 +11 +15 +19 +22 +24 +24 +24 +23 +23 +22 +21 +20 +20 +19 +10 +1 +-5 +-9 +-12 +-14 +-16 +-17 +-17 +-16 +-16 +-16 +-15 +-14 +-13 +-12 +-3 +6 +13 +18 +21 +23 +26 +26 +26 +24 +24 +23 +22 +20 +20 +19 +10 +2 +-5 +-10 +-12 +-15 +-16 +-17 +-16 +-16 +-16 +-15 +-14 +-13 +-12 +-11 +-10 +-9 +-8 +-8 +-7 +-6 +-5 +-5 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +8 +15 +21 +25 +28 +30 +30 +30 +30 +29 +28 +27 +26 +25 +24 +23 +14 +5 +-1 +-7 +-10 +-13 +-13 +-14 +-15 +-15 +-14 +-14 +-13 +-12 +-11 +-10 +-1 +6 +13 +18 +22 +24 +25 +25 +26 +25 +23 +22 +22 +21 +20 +19 +10 +2 +-5 +-10 +-13 +-15 +-16 +-18 +-17 +-17 +-16 +-16 +-15 +-13 +-12 +-12 +-4 +5 +12 +17 +21 +22 +24 +24 +24 +23 +23 +23 +22 +21 +20 +19 +18 +17 +16 +15 +15 +14 +14 +12 +12 +11 +11 +10 +10 +9 +9 +9 +0 +-8 +-13 +-17 +-20 +-22 +-22 +-23 +-22 +-22 +-21 +-20 +-18 +-18 +-17 +-16 +-15 +-14 +-12 +-12 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +-5 +-4 +-4 +-3 +-3 +5 +13 +20 +24 +27 +27 +29 +29 +29 +28 +27 +26 +25 +24 +22 +21 +11 +3 +-3 +-8 +-11 +-13 +-14 +-16 +-15 +-15 +-14 +-15 +-14 +-13 +-11 +-11 +-3 +6 +13 +18 +21 +22 +24 +24 +24 +24 +23 +22 +21 +20 +19 +18 +9 +1 +-6 +-11 +-14 +-16 +-17 +-18 +-18 +-17 +-16 +-16 +-16 +-15 +-13 +-12 +-3 +5 +13 +17 +20 +21 +23 +24 +24 +23 +23 +22 +21 +19 +19 +18 +9 +1 +-6 +-11 +-14 +-16 +-17 +-18 +-18 +-17 +-16 +-16 +-16 +-14 +-14 +-13 +-4 +4 +12 +17 +20 +22 +24 +24 +24 +23 +22 +22 +21 +20 +19 +18 +9 +0 +-6 +-11 +-14 +-16 +-18 +-18 +-18 +-17 +-16 +-16 +-14 +-14 +-13 +-13 +-3 +5 +12 +16 +20 +21 +22 +22 +22 +22 +22 +21 +19 +18 +19 +18 +8 +0 +-6 +-11 +-14 +-16 +-17 +-17 +-18 +-18 +-18 +-17 +-15 +-15 +-13 +-13 +-4 +4 +11 +15 +19 +21 +22 +23 +22 +22 +22 +21 +20 +19 +19 +18 +17 +15 +15 +13 +13 +12 +12 +11 +11 +10 +9 +8 +8 +8 +8 +7 +-1 +-9 +-14 +-19 +-22 +-23 +-23 +-24 +-24 +-23 +-22 +-20 +-20 +-19 +-17 +-16 +-15 +-14 +-12 +-12 +-10 +-11 +-10 +-9 +-8 +-7 +-7 +-6 +-5 +-4 +-4 +-5 +4 +12 +18 +22 +26 +27 +29 +28 +27 +26 +26 +25 +23 +22 +21 +20 +10 +2 +-4 +-9 +-12 +-15 +-16 +-17 +-16 +-17 +-16 +-16 +-14 +-13 +-13 +-12 +-4 +5 +11 +16 +19 +21 +22 +22 +23 +22 +22 +20 +20 +19 +19 +17 +8 +-1 +-7 +-12 +-14 +-17 +-17 +-18 +-18 +-18 +-18 +-17 +-16 +-16 +-15 +-14 +-5 +3 +10 +15 +19 +21 +22 +23 +23 +22 +22 +20 +19 +18 +17 +16 +7 +-1 +-7 +-12 +-16 +-17 +-18 +-18 +-19 +-19 +-18 +-17 +-16 +-16 +-14 +-13 +-4 +4 +10 +14 +18 +20 +21 +21 +21 +21 +18 +16 +13 +12 +11 +9 +-9 +-28 +-43 +-55 +-61 +-66 +-66 +-66 +-64 +-62 +-59 +-56 +-52 +-50 +-47 +-44 +-41 +-38 +-36 +-33 +-31 +-29 +-27 +-26 +-23 +-22 +-20 +-19 +-16 +-15 +-14 +-14 +-12 +-11 +-10 +-10 +-9 +-8 +-7 +-7 +-7 +-7 +-6 +-6 +-5 +-5 +-4 +-4 +-4 +-4 +-4 +-3 +-2 +-2 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +1 +1 +1 +1 +0 +1 +1 +1 +0 +1 +1 +2 +1 +1 +1 +1 +1 +1 +1 +2 +1 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +2 +1 +1 +0 +1 +1 +1 +1 +1 +1 +2 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +0 +1 +1 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +0 +0 +1 +0 +1 +1 +1 +1 +1 +0 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +1 +1 +1 +0 +1 +1 +1 +0 +0 +0 +1 +1 +0 +0 +1 +1 +1 +1 +1 +1 +1 +0 +0 +1 +1 +1 +0 +0 +1 +0 +0 +0 +1 +1 +1 +0 +1 +1 +1 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +0 +0 +0 +0 +0 +1 +1 +1 +0 +1 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +1 +1 +2 +1 +1 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +-1 +0 +0 +1 +0 +0 +0 +1 +0 +0 +0 +1 +0 +1 +0 +0 +0 +0 +-1 +0 +0 +0 +0 +-1 +-1 +0 +0 +0 +0 +1 +0 +0 +-1 +0 +-1 +0 +-1 +-1 +-1 +0 +0 +0 +0 +0 +1 +0 +0 +0 +1 +0 +0 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +0 +-1 +0 +-1 +0 +-1 +0 +-1 +0 +0 +0 +0 +0 +0 +1 +0 +0 +0 +-1 +-1 +-1 +-1 +0 +0 +0 +-1 +0 +0 +0 +-1 +0 +0 +0 +0 +0 +-1 +0 +-1 +-1 +-1 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +0 +0 +-27 +-51 +-73 +-92 +-109 +-125 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-127 +-64 +-7 +32 +59 +75 +84 +88 +89 +53 +21 +-8 +-34 +-57 +-78 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-96 +-16 +40 +78 +101 +115 +117 +117 +117 +117 +114 +109 +103 +97 +90 +54 +22 +-7 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-105 +-26 +30 +69 +92 +107 +113 +116 +115 +112 +74 +40 +8 +-19 +-44 +-65 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-11 +45 +82 +106 +117 +117 +117 +117 +86 +50 +18 +-10 +-36 +-58 +-79 +-96 +-113 +-127 +-127 +-127 +-127 +-80 +-1 +54 +91 +114 +117 +117 +117 +117 +117 +117 +117 +111 +103 +97 +90 +54 +21 +-7 +-33 +-56 +-77 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-104 +-25 +31 +69 +93 +107 +114 +116 +115 +112 +107 +102 +96 +91 +85 +49 +17 +-11 +-37 +-60 +-80 +-98 +-115 +-127 +-127 +-127 +-127 +-127 +-106 +-28 +28 +66 +90 +105 +111 +114 +113 +75 +40 +10 +-18 +-43 +-65 +-84 +-102 +-117 +-127 +-127 +-127 +-127 +-85 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +117 +113 +106 +101 +94 +88 +52 +20 +-9 +-35 +-58 +-78 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-106 +-27 +30 +67 +91 +105 +113 +115 +114 +75 +41 +9 +-18 +-43 +-64 +-84 +-102 +-117 +-127 +-127 +-127 +-127 +-127 +-81 +0 +56 +95 +117 +117 +117 +117 +117 +117 +117 +117 +112 +106 +99 +62 +28 +-1 +-28 +-51 +-73 +-91 +-109 +-123 +-127 +-127 +-127 +-127 +-101 +-22 +33 +71 +95 +109 +116 +117 +117 +78 +43 +12 +-16 +-41 +-63 +-83 +-101 +-116 +-127 +-127 +-127 +-127 +-84 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +85 +50 +18 +-11 +-36 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-83 +-5 +50 +87 +110 +117 +117 +117 +117 +117 +117 +113 +107 +100 +95 +58 +25 +-5 +-31 +-54 +-75 +-94 +-110 +-125 +-127 +-127 +-127 +-127 +-102 +-24 +32 +68 +93 +107 +114 +115 +114 +111 +73 +39 +8 +-19 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-10 +45 +82 +105 +117 +117 +117 +117 +85 +49 +18 +-11 +-36 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-81 +-2 +52 +90 +113 +117 +117 +117 +117 +117 +117 +115 +108 +102 +95 +90 +53 +21 +-8 +-34 +-57 +-78 +-96 +-112 +-127 +-127 +-127 +-127 +-127 +-104 +-27 +29 +66 +90 +104 +112 +113 +113 +74 +40 +9 +-18 +-43 +-65 +-85 +-102 +-118 +-127 +-127 +-127 +-127 +-85 +-6 +49 +86 +108 +117 +117 +117 +117 +117 +117 +112 +106 +99 +93 +56 +24 +-6 +-32 +-55 +-76 +-95 +-111 +-126 +-127 +-127 +-127 +-127 +-103 +-25 +30 +68 +92 +106 +113 +116 +115 +111 +73 +39 +8 +-20 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-89 +-11 +44 +82 +105 +117 +117 +117 +117 +84 +48 +17 +-11 +-37 +-59 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-82 +-3 +53 +90 +112 +117 +117 +117 +117 +117 +117 +115 +108 +102 +94 +88 +52 +20 +-9 +-35 +-58 +-78 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-105 +-27 +29 +66 +90 +103 +111 +113 +113 +74 +40 +9 +-18 +-43 +-65 +-85 +-102 +-118 +-127 +-127 +-127 +-127 +-85 +-7 +48 +85 +108 +117 +117 +117 +117 +117 +117 +112 +105 +99 +93 +56 +23 +-6 +-32 +-56 +-76 +-95 +-111 +-126 +-127 +-127 +-127 +-127 +-103 +-25 +30 +67 +91 +104 +112 +114 +112 +109 +105 +100 +95 +89 +83 +78 +44 +12 +-16 +-41 +-64 +-84 +-101 +-117 +-127 +-127 +-127 +-127 +-127 +-109 +-31 +24 +61 +85 +100 +107 +110 +108 +71 +36 +6 +-21 +-46 +-67 +-87 +-104 +-119 +-127 +-127 +-127 +-127 +-87 +-9 +46 +83 +106 +117 +117 +117 +117 +117 +116 +110 +103 +98 +92 +86 +50 +18 +-11 +-37 +-60 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-127 +-106 +-28 +27 +64 +88 +102 +109 +112 +112 +73 +39 +8 +-19 +-44 +-66 +-85 +-103 +-118 +-127 +-127 +-127 +-127 +-86 +-8 +47 +83 +107 +117 +117 +117 +117 +117 +116 +110 +104 +97 +92 +85 +50 +18 +-11 +-37 +-59 +-80 +-98 +-114 +-127 +-127 +-127 +-127 +-127 +-107 +-29 +26 +63 +87 +102 +109 +111 +110 +72 +37 +7 +-21 +-45 +-67 +-86 +-103 +-118 +-127 +-127 +-127 +-127 +-87 +-9 +47 +84 +107 +117 +117 +117 +117 +86 +50 +19 +-10 +-35 +-58 +-78 +-97 +-112 +-127 +-127 +-127 +-127 +-80 +-3 +52 +88 +111 +117 +117 +117 +117 +117 +117 +114 +106 +100 +93 +88 +51 +20 +-10 +-35 +-58 +-79 +-97 +-113 +-127 +-127 +-127 +-127 +-127 +-105 +-27 +28 +65 +89 +103 +110 +112 +111 +72 +38 +7 +-20 +-44 +-66 +-86 +-103 +-118 +-127 +-127 +-127 +-127 +-87 +-8 +47 +84 +106 +117 +117 +117 +117 +117 +115 +109 +104 +97 +91 +84 +79 +74 +69 +64 +59 +55 +51 +47 +44 +54 +68 +75 +78 +78 +77 +74 +71 +67 +64 +59 +56 +52 +49 +45 +42 +39 +37 +33 +31 +28 +26 +24 +22 +21 +20 +18 +16 +15 +14 +12 +11 +9 +8 +8 +7 +6 +5 +4 +4 +4 +3 +2 +2 +2 +2 +1 +1 +0 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-2 +-2 +-2 +-2 +-3 +-3 +-3 +-3 +-2 +-3 +-3 +-3 +-3 +-3 +-3 +-4 +-3 +-3 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-3 +-4 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-4 +-4 +-4 +-4 +-5 +-4 +-5 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-4 +-5 +-5 +-4 +-4 +-5 +-4 +-4 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-4 +-4 +-5 +-4 +-4 +-3 +-5 +-4 +-5 +-4 +-5 +-5 +-5 +-4 +-4 +-4 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +2 +11 +16 +20 +22 +24 +24 +24 +23 +22 +21 +21 +19 +17 +16 +15 +6 +-2 +-9 +-14 +-17 +-19 +-22 +-22 +-22 +-22 +-21 +-21 +-21 +-19 +-19 +-18 +-10 +-1 +5 +10 +13 +14 +16 +16 +16 +15 +15 +14 +13 +12 +10 +10 +1 +-6 +-13 +-17 +-20 +-22 +-24 +-24 +-24 +-23 +-23 +-23 +-23 +-21 +-21 +-20 +-12 +-3 +4 +9 +11 +14 +15 +16 +15 +15 +14 +14 +13 +11 +11 +10 +1 +-7 +-13 +-17 +-21 +-23 +-24 +-25 +-24 +-24 +-24 +-23 +-22 +-21 +-21 +-20 +-11 +-3 +4 +9 +11 +14 +15 +16 +15 +14 +14 +13 +12 +11 +10 +10 +1 +-7 +-14 +-18 +-21 +-23 +-25 +-25 +-25 +-24 +-25 +-24 +-23 +-21 +-20 +-19 +-11 +-3 +4 +9 +11 +13 +15 +16 +15 +14 +13 +13 +12 +11 +10 +9 +0 +-7 +-14 +-18 +-21 +-23 +-24 +-24 +-25 +-24 +-24 +-23 +-22 +-21 +-20 +-20 +-19 +-18 +-17 +-16 +-16 +-15 +-14 +-14 +-14 +-13 +-13 +-12 +-12 +-12 +-11 +-10 +-3 +5 +11 +15 +18 +20 +20 +21 +20 +20 +19 +18 +16 +15 +13 +13 +2 +-5 +-11 +-15 +-19 +-21 +-23 +-23 +-23 +-23 +-23 +-22 +-21 +-20 +-20 +-19 +-11 +-2 +4 +9 +12 +14 +15 +15 +15 +15 +14 +14 +12 +12 +11 +10 +0 +-7 +-13 +-18 +-21 +-23 +-24 +-24 +-25 +-24 +-24 +-23 +-22 +-21 +-20 +-20 +-11 +-4 +2 +8 +11 +13 +14 +14 +14 +14 +13 +12 +11 +11 +10 +9 +0 +-7 +-14 +-18 +-22 +-23 +-25 +-25 +-26 +-25 +-24 +-22 +-22 +-22 +-21 +-20 +-12 +-4 +2 +8 +11 +13 +13 +14 +14 +14 +13 +13 +12 +11 +10 +9 +-1 +-8 +-14 +-19 +-22 +-23 +-25 +-25 +-26 +-25 +-25 +-24 +-23 +-23 +-22 +-20 +-12 +-4 +2 +8 +11 +13 +14 +14 +15 +14 +13 +13 +12 +11 +10 +9 +8 +7 +6 +6 +5 +5 +4 +3 +2 +2 +1 +1 +0 +-1 +-1 +0 +-9 +-16 +-22 +-25 +-29 +-31 +-32 +-32 +-31 +-30 +-30 +-29 +-27 +-26 +-25 +-24 +-16 +-7 +0 +4 +8 +11 +13 +13 +12 +12 +12 +11 +10 +9 +8 +8 +-2 +-10 +-15 +-19 +-22 +-24 +-26 +-26 +-26 +-26 +-25 +-24 +-24 +-22 +-22 +-21 +-21 +-19 +-19 +-18 +-17 +-16 +-15 +-15 +-15 +-14 +-13 +-12 +-12 +-12 +-11 +-11 +-3 +4 +11 +15 +18 +19 +20 +20 +20 +19 +18 +17 +15 +15 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +3 +2 +2 +1 +1 +0 +0 +-9 +-16 +-22 +-25 +-28 +-30 +-31 +-31 +-30 +-29 +-29 +-28 +-27 +-25 +-25 +-23 +-23 +-21 +-21 +-20 +-19 +-17 +-17 +-16 +-16 +-14 +-14 +-13 +-13 +-12 +-12 +-12 +-5 +4 +10 +14 +16 +18 +19 +19 +18 +17 +16 +16 +14 +13 +12 +12 +10 +9 +8 +7 +6 +6 +5 +4 +4 +3 +2 +2 +1 +1 +1 +0 +-9 +-15 +-21 +-26 +-29 +-30 +-31 +-31 +-31 +-30 +-30 +-28 +-28 +-27 +-25 +-24 +-22 +-22 +-21 +-20 +-19 +-18 +-18 +-17 +-16 +-15 +-14 +-14 +-14 +-13 +-12 +-12 +-5 +4 +9 +14 +16 +18 +19 +19 +18 +18 +17 +16 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +4 +3 +3 +1 +1 +1 +1 +0 +-1 +-9 +-16 +-21 +-26 +-29 +-31 +-31 +-31 +-31 +-30 +-29 +-28 +-27 +-26 +-25 +-24 +-22 +-21 +-21 +-20 +-19 +-18 +-18 +-17 +-17 +-15 +-15 +-15 +-14 +-13 +-13 +-13 +-5 +3 +10 +14 +16 +18 +19 +19 +18 +17 +17 +16 +14 +13 +12 +11 +10 +9 +8 +7 +6 +5 +4 +3 +2 +2 +1 +1 +0 +1 +0 +0 +-9 +-16 +-22 +-26 +-30 +-31 +-31 +-31 +-32 +-30 +-30 +-28 +-27 +-26 +-25 +-24 +-23 +-22 +-21 +-20 +-19 +-18 +-18 +-17 +-16 +-15 +-15 +-14 +-13 +-12 +-12 +-12 +-5 +3 +9 +13 +15 +17 +18 +19 +18 +17 +16 +15 +14 +12 +11 +10 +1 +-6 +-13 +-17 +-20 +-22 +-24 +-24 +-25 +-24 +-24 +-24 +-23 +-22 +-21 +-21 +-12 +-4 +3 +7 +10 +12 +13 +14 +13 +13 +12 +12 +10 +9 +8 +8 +7 +6 +5 +5 +4 +3 +2 +2 +1 +1 +-1 +0 +-1 +-1 +-3 +-2 +-11 +-17 +-23 +-27 +-30 +-31 +-32 +-33 +-32 +-31 +-30 +-29 +-28 +-26 +-25 +-23 +-24 +-22 +-21 +-20 +-19 +-18 +-17 +-16 +-16 +-16 +-15 +-14 +-14 +-13 +-13 +-12 +-5 +3 +8 +12 +15 +17 +18 +18 +17 +17 +16 +14 +13 +13 +11 +10 +0 +-7 +-13 +-18 +-22 +-24 +-25 +-25 +-25 +-25 +-25 +-24 +-23 +-22 +-22 +-21 +-12 +-4 +2 +7 +10 +13 +13 +14 +13 +13 +12 +12 +10 +10 +9 +8 +6 +5 +5 +4 +4 +3 +2 +1 +1 +0 +-1 +0 +-1 +0 +-2 +-2 +-11 +-17 +-24 +-28 +-31 +-32 +-33 +-33 +-32 +-31 +-30 +-29 +-28 +-27 +-26 +-25 +-24 +-23 +-21 +-20 +-20 +-19 +-18 +-17 +-17 +-16 +-16 +-14 +-14 +-14 +-14 +-13 +-5 +3 +8 +13 +16 +17 +17 +17 +17 +17 +15 +14 +13 +13 +11 +10 +0 +-7 +-13 +-18 +-21 +-23 +-24 +-25 +-26 +-25 +-25 +-24 +-23 +-22 +-21 +-20 +-12 +-4 +2 +7 +9 +12 +12 +13 +12 +12 +11 +11 +10 +9 +8 +7 +-2 +-9 +-15 +-20 +-23 +-25 +-26 +-26 +-27 +-27 +-26 +-25 +-24 +-23 +-23 +-22 +-13 +-5 +1 +5 +9 +11 +12 +12 +12 +12 +11 +10 +9 +9 +8 +7 +-2 +-10 +-16 +-20 +-24 +-26 +-27 +-27 +-27 +-27 +-26 +-25 +-24 +-24 +-23 +-22 +-13 +-5 +1 +5 +9 +11 +11 +11 +12 +12 +11 +10 +9 +9 +8 +6 +5 +5 +4 +4 +2 +2 +1 +1 +0 +0 +0 +0 +-1 +-2 +-2 +-2 +-11 +-18 +-24 +-28 +-31 +-32 +-33 +-33 +-32 +-31 +-31 +-30 +-29 +-27 +-26 +-25 +-24 +-22 +-22 +-21 +-21 +-20 +-19 +-17 +-17 +-17 +-16 +-15 +-14 +-14 +-14 +-13 +-5 +2 +8 +12 +15 +17 +17 +17 +17 +17 +15 +14 +13 +12 +11 +10 +8 +7 +6 +5 +4 +3 +2 +2 +2 +2 +0 +0 +-1 +-1 +-3 +-3 +-11 +-17 +-23 +-27 +-30 +-32 +-33 +-33 +-33 +-31 +-30 +-29 +-29 +-27 +-26 +-25 +-25 +-23 +-22 +-21 +-20 +-19 +-19 +-17 +-17 +-16 +-16 +-15 +-15 +-15 +-15 +-14 +-7 +1 +7 +11 +14 +17 +16 +17 +16 +16 +15 +14 +12 +12 +11 +9 +8 +7 +6 +5 +4 +3 +3 +2 +1 +0 +0 +0 +-1 +-1 +-3 +-2 +-11 +-18 +-24 +-27 +-30 +-31 +-32 +-32 +-32 +-31 +-30 +-30 +-29 +-28 +-27 +-25 +-25 +-23 +-22 +-21 +-21 +-20 +-19 +-18 +-17 +-16 +-16 +-15 +-15 +-14 +-14 +-14 +-5 +2 +8 +11 +14 +16 +17 +16 +16 +16 +15 +14 +12 +12 +10 +9 +0 +-7 +-14 +-18 +-22 +-24 +-25 +-26 +-27 +-27 +-26 +-25 +-24 +-24 +-23 +-22 +-13 +-5 +1 +6 +9 +11 +11 +12 +12 +12 +8 +5 +3 +2 +1 +0 +-18 +-36 +-51 +-62 +-69 +-72 +-73 +-72 +-71 +-69 +-67 +-63 +-59 +-56 +-54 +-51 +-48 +-45 +-43 +-41 +-39 +-36 +-35 +-33 +-31 +-29 +-28 +-26 +-25 +-24 +-23 +-22 +-22 +-20 +-19 +-18 +-18 +-17 +-17 +-16 +-16 +-15 +-15 +-14 +-13 +-13 +-13 +-13 +-13 +-12 +-13 +-12 +-12 +-11 +-12 +-11 +-11 +-10 +-10 +-10 +-10 +-9 +-9 +-9 +-10 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-7 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-7 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-8 +-9 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-7 +-8 +-9 +-9 +-9 +-9 +-9 +-10 +-9 +-9 +-8 +-10 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-7 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-10 +-9 +-9 +-9 +-10 +-10 +-9 +-9 +-9 +-10 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-9 +-8 +-9 +-9 +-10 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-10 +-10 +-10 +-9 +-9 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-9 +-8 +-8 +-9 +-9 +-8 +-8 +-8 +-9 +-8 +-9 +-8 +-9 +-9 +-9 +-8 +-9 +-9 +-9 +-9 +-8 +-8 +-8 +-8 +-8 +-8 +-8 +-9 +-8 +-8 +-8 +-8 +-8 +-7 +-7 +-7 +-8 +-7 diff --git a/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 b/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 new file mode 100644 index 000000000..3be1e7cb5 --- /dev/null +++ b/traces/sniff-ht2-BC3B8810-rfidler-reader.pm3 @@ -0,0 +1,4200 @@ +-2 +-1 +0 +0 +-1 +0 +-1 +0 +-1 +-2 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-2 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +-1 +0 +0 +-1 +-1 +-2 +-2 +-2 +-2 +-2 +-2 +-2 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-2 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-1 +-21 +-39 +-55 +-69 +-82 +-94 +-104 +-113 +-113 +2 +57 +66 +53 +36 +22 +13 +12 +16 +20 +22 +22 +21 +19 +18 +16 +14 +13 +12 +12 +10 +-11 +-30 +-47 +-62 +-75 +-88 +-98 +-108 +-106 +10 +64 +72 +60 +42 +28 +19 +18 +20 +24 +26 +27 +25 +23 +21 +18 +17 +16 +14 +14 +13 +-8 +-27 +-44 +-60 +-74 +-86 +-97 +-107 +-105 +9 +61 +68 +56 +39 +26 +19 +18 +21 +25 +27 +28 +26 +3 +-17 +-35 +-52 +-66 +-79 +-91 +-101 +-99 +16 +69 +75 +62 +44 +30 +22 +22 +24 +28 +30 +30 +28 +5 +-15 +-33 +-50 +-65 +-78 +-90 +-100 +-97 +20 +73 +79 +65 +46 +30 +21 +21 +24 +28 +30 +30 +28 +5 +-15 +-34 +-50 +-65 +-78 +-90 +-100 +-96 +21 +75 +82 +68 +49 +32 +22 +21 +25 +29 +31 +31 +29 +27 +23 +22 +20 +19 +17 +15 +14 +13 +12 +11 +11 +10 +9 +8 +12 +17 +22 +28 +31 +33 +33 +33 +31 +30 +28 +28 +26 +24 +22 +20 +20 +18 +17 +16 +15 +14 +12 +11 +10 +10 +10 +9 +8 +7 +6 +5 +5 +5 +5 +5 +3 +3 +3 +3 +2 +3 +2 +2 +2 +1 +1 +2 +2 +1 +-1 +-1 +-1 +-1 +-1 +0 +0 +0 +0 +0 +-1 +0 +1 +0 +-1 +0 +-1 +0 +-1 +0 +0 +0 +-1 +-2 +-2 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +-2 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-1 +-1 +-1 +-1 +0 +-1 +-1 +-2 +-2 +-2 +-2 +-5 +-6 +-6 +-4 +-3 +-1 +0 +1 +1 +2 +1 +0 +0 +0 +0 +2 +2 +3 +3 +3 +3 +4 +3 +3 +3 +3 +3 +2 +1 +1 +1 +2 +1 +2 +1 +1 +0 +0 +-1 +0 +0 +0 +0 +0 +0 +0 +-1 +-1 +-1 +0 +0 +0 +-1 +-1 +-1 +-2 +-2 +-2 +5 +24 +42 +57 +66 +69 +68 +65 +61 +57 +53 +50 +46 +44 +40 +37 +27 +10 +-7 +-23 +-36 +-44 +-47 +-46 +-46 +-45 +-43 +-41 +-39 +-37 +-35 +-34 +-25 +-6 +14 +31 +42 +48 +49 +48 +46 +45 +41 +39 +37 +35 +33 +30 +21 +5 +-12 +-27 +-40 +-47 +-49 +-48 +-49 +-47 +-46 +-43 +-41 +-39 +-36 +-35 +-27 +-8 +12 +29 +39 +46 +47 +46 +45 +43 +40 +38 +36 +35 +33 +29 +21 +5 +-13 +-28 +-40 +-47 +-49 +-49 +-50 +-48 +-46 +-43 +-41 +-38 +-36 +-35 +-27 +-9 +13 +30 +40 +46 +46 +46 +43 +41 +38 +37 +36 +35 +32 +28 +20 +4 +-13 +-28 +-40 +-47 +-51 +-52 +-51 +-48 +-45 +-42 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +39 +45 +46 +45 +44 +41 +39 +37 +35 +33 +31 +28 +20 +4 +-13 +-29 +-41 +-47 +-50 +-51 +-49 +-47 +-45 +-42 +-41 +-38 +-36 +-35 +-28 +-9 +12 +29 +39 +45 +46 +46 +43 +41 +38 +36 +35 +33 +31 +29 +20 +4 +-13 +-29 +-41 +-48 +-50 +-51 +-50 +-47 +-44 +-42 +-40 +-37 +-36 +-35 +-34 +-33 +-31 +-28 +-27 +-25 +-23 +-21 +-19 +-18 +-17 +-16 +-15 +-13 +-13 +-14 +-6 +12 +31 +47 +56 +61 +61 +58 +55 +52 +49 +46 +43 +42 +39 +36 +32 +29 +26 +26 +24 +23 +22 +21 +20 +18 +16 +16 +14 +14 +12 +10 +3 +-12 +-28 +-42 +-54 +-59 +-62 +-62 +-60 +-57 +-53 +-50 +-48 +-44 +-42 +-41 +-33 +-14 +7 +24 +34 +40 +42 +42 +40 +37 +35 +34 +32 +31 +28 +26 +17 +1 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-48 +-45 +-43 +-41 +-38 +-37 +-36 +-29 +-10 +12 +29 +39 +45 +47 +45 +42 +39 +37 +37 +34 +33 +30 +28 +19 +3 +-14 +-29 +-41 +-48 +-51 +-52 +-51 +-47 +-44 +-41 +-40 +-37 +-36 +-36 +-28 +-9 +12 +30 +40 +45 +46 +45 +43 +41 +38 +37 +35 +33 +30 +27 +19 +4 +-13 +-28 +-41 +-48 +-52 +-52 +-50 +-46 +-43 +-41 +-40 +-38 +-36 +-35 +-34 +-32 +-30 +-28 +-27 +-26 +-24 +-21 +-19 +-18 +-17 +-15 +-15 +-14 +-14 +-15 +-6 +12 +31 +46 +55 +61 +60 +58 +55 +52 +49 +46 +43 +42 +39 +36 +25 +8 +-10 +-25 +-38 +-45 +-48 +-47 +-46 +-44 +-42 +-39 +-36 +-35 +-34 +-33 +-25 +-5 +15 +33 +43 +49 +48 +46 +44 +42 +39 +37 +35 +34 +31 +28 +18 +2 +-15 +-30 +-42 +-49 +-52 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-36 +-35 +-26 +-8 +13 +31 +41 +47 +46 +45 +43 +41 +38 +36 +34 +33 +30 +26 +18 +2 +-15 +-30 +-43 +-50 +-53 +-52 +-51 +-47 +-43 +-41 +-39 +-37 +-36 +-35 +-27 +-8 +13 +32 +41 +47 +47 +45 +43 +41 +39 +37 +34 +33 +30 +26 +24 +22 +21 +21 +19 +18 +17 +16 +14 +14 +14 +13 +12 +11 +9 +7 +0 +-14 +-31 +-44 +-55 +-62 +-65 +-64 +-60 +-56 +-53 +-50 +-47 +-45 +-44 +-44 +-35 +-15 +6 +23 +33 +40 +42 +41 +38 +36 +34 +33 +31 +29 +27 +25 +16 +0 +-16 +-31 +-43 +-51 +-54 +-53 +-51 +-48 +-45 +-42 +-40 +-38 +-38 +-37 +-29 +-9 +11 +28 +38 +44 +45 +44 +42 +40 +38 +36 +33 +32 +29 +27 +18 +3 +-15 +-29 +-42 +-49 +-53 +-51 +-49 +-46 +-44 +-42 +-40 +-38 +-37 +-36 +-34 +-32 +-31 +-29 +-28 +-25 +-24 +-21 +-19 +-18 +-17 +-17 +-16 +-14 +-14 +-14 +-7 +12 +31 +46 +55 +60 +60 +58 +54 +51 +48 +45 +43 +40 +38 +35 +32 +28 +26 +25 +24 +23 +21 +20 +19 +18 +16 +16 +15 +14 +12 +9 +1 +-13 +-29 +-43 +-54 +-60 +-63 +-62 +-59 +-56 +-52 +-49 +-47 +-45 +-44 +-43 +-34 +-14 +7 +25 +35 +41 +42 +41 +39 +38 +35 +33 +31 +30 +28 +25 +16 +1 +-16 +-31 +-43 +-51 +-53 +-52 +-51 +-48 +-45 +-43 +-41 +-39 +-38 +-36 +-28 +-10 +11 +27 +38 +44 +45 +44 +42 +40 +37 +35 +33 +32 +30 +27 +19 +3 +-15 +-30 +-42 +-50 +-52 +-51 +-49 +-47 +-44 +-42 +-40 +-38 +-36 +-36 +-34 +-33 +-32 +-29 +-27 +-25 +-23 +-21 +-19 +-18 +-18 +-17 +-16 +-15 +-14 +-15 +-7 +11 +31 +46 +55 +60 +61 +58 +55 +51 +48 +45 +42 +40 +38 +35 +25 +8 +-10 +-26 +-38 +-46 +-49 +-47 +-46 +-44 +-42 +-39 +-37 +-35 +-33 +-33 +-24 +-5 +15 +32 +42 +48 +48 +47 +44 +41 +38 +36 +34 +33 +31 +28 +18 +2 +-15 +-30 +-43 +-50 +-52 +-52 +-50 +-47 +-44 +-41 +-39 +-37 +-36 +-35 +-27 +-8 +13 +31 +41 +47 +47 +45 +43 +41 +38 +36 +34 +33 +30 +26 +24 +22 +21 +20 +18 +18 +16 +16 +14 +14 +13 +13 +11 +10 +9 +7 +-1 +-15 +-31 +-44 +-56 +-63 +-65 +-64 +-61 +-58 +-54 +-51 +-48 +-46 +-44 +-44 +-42 +-39 +-37 +-34 +-33 +-30 +-28 +-26 +-24 +-22 +-20 +-19 +-19 +-18 +-18 +-17 +-10 +9 +29 +45 +53 +58 +58 +56 +53 +49 +46 +44 +41 +39 +36 +33 +24 +7 +-11 +-27 +-39 +-45 +-48 +-49 +-47 +-44 +-42 +-40 +-38 +-35 +-33 +-33 +-25 +-6 +15 +33 +42 +48 +48 +46 +43 +40 +38 +37 +35 +33 +30 +27 +18 +2 +-15 +-30 +-43 +-50 +-53 +-53 +-50 +-46 +-43 +-41 +-40 +-38 +-37 +-36 +-27 +-8 +13 +31 +41 +46 +47 +46 +43 +41 +38 +36 +33 +32 +29 +26 +18 +2 +-15 +-31 +-43 +-50 +-53 +-53 +-51 +-47 +-44 +-42 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +40 +45 +46 +45 +43 +40 +37 +35 +33 +32 +30 +27 +18 +2 +-16 +-31 +-43 +-51 +-54 +-53 +-51 +-47 +-44 +-41 +-40 +-38 +-36 +-35 +-27 +-8 +13 +30 +40 +46 +46 +46 +43 +41 +37 +35 +33 +32 +29 +26 +18 +2 +-16 +-31 +-44 +-51 +-54 +-53 +-50 +-47 +-44 +-41 +-40 +-37 +-35 +-34 +-26 +-8 +13 +29 +39 +45 +47 +46 +43 +39 +37 +35 +33 +32 +29 +26 +24 +22 +19 +19 +18 +17 +16 +15 +14 +13 +13 +12 +11 +11 +10 +7 +-1 +-15 +-31 +-45 +-56 +-63 +-65 +-64 +-61 +-58 +-54 +-50 +-48 +-46 +-44 +-43 +-42 +-40 +-38 +-35 +-32 +-29 +-28 +-26 +-25 +-22 +-21 +-20 +-19 +-17 +-17 +-18 +-10 +9 +29 +45 +53 +58 +58 +55 +52 +49 +46 +44 +41 +38 +36 +33 +24 +7 +-11 +-26 +-39 +-47 +-51 +-50 +-47 +-44 +-42 +-40 +-37 +-35 +-35 +-34 +-25 +-5 +15 +31 +41 +47 +48 +46 +44 +41 +38 +36 +34 +32 +30 +28 +18 +2 +-16 +-31 +-43 +-50 +-53 +-52 +-50 +-47 +-45 +-41 +-39 +-36 +-36 +-36 +-27 +-8 +13 +30 +40 +46 +48 +45 +42 +40 +37 +36 +33 +32 +29 +26 +17 +1 +-16 +-31 +-43 +-51 +-54 +-54 +-51 +-47 +-44 +-41 +-40 +-37 +-37 +-36 +-28 +-8 +14 +31 +40 +45 +46 +45 +42 +39 +37 +34 +30 +28 +25 +22 +7 +-13 +-33 +-50 +-66 +-80 +-92 +-101 +-107 +-109 +-108 +-105 +-100 +-93 +-87 +-80 +-76 +-71 +-66 +-62 +-58 +-54 +-50 +-45 +-43 +-40 +-39 +-36 +-34 +-33 +-31 +-28 +-26 +-24 +-24 +-22 +-21 +-20 +-19 +-18 +-16 +-15 +-16 +-15 +-14 +-13 +-13 +-12 +-11 +-10 +-11 +-11 +-10 +-9 +-9 +-8 +-8 +-7 +-8 +-7 +-8 +-8 +-7 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-5 +-5 +-4 +-5 +-4 +-5 +-5 +-6 +-6 +-5 +-4 +-4 +-4 +-5 +-4 +-4 +-4 +-4 +-3 +-4 +-3 +-5 +-4 +-4 +-3 +-4 +-3 +-3 +-3 +-3 +-4 +-4 +-3 +-3 +-3 +-4 +-4 +-24 +-41 +-57 +-70 +-83 +-94 +-104 +-112 +-116 +-5 +49 +57 +45 +28 +13 +5 +3 +9 +15 +19 +20 +18 +-4 +-23 +-40 +-56 +-70 +-82 +-93 +-102 +-105 +9 +63 +71 +57 +40 +24 +15 +15 +19 +23 +27 +28 +27 +23 +21 +19 +18 +17 +16 +16 +15 +-6 +-25 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +6 +58 +66 +53 +36 +20 +12 +12 +16 +20 +24 +25 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +65 +72 +59 +42 +26 +17 +16 +20 +24 +27 +28 +27 +4 +-16 +-34 +-50 +-65 +-78 +-89 +-99 +-101 +14 +67 +74 +60 +42 +27 +18 +17 +21 +25 +29 +29 +28 +25 +23 +21 +19 +18 +18 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-104 +-107 +7 +60 +68 +54 +37 +21 +13 +13 +18 +22 +25 +26 +25 +22 +20 +18 +17 +16 +15 +14 +14 +-7 +-26 +-43 +-59 +-72 +-84 +-95 +-104 +-107 +6 +60 +67 +53 +36 +21 +12 +11 +17 +21 +25 +25 +23 +1 +-19 +-37 +-53 +-67 +-79 +-91 +-100 +-103 +12 +66 +73 +59 +42 +26 +17 +16 +19 +24 +28 +29 +28 +24 +22 +20 +18 +17 +17 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-103 +-106 +6 +60 +67 +53 +36 +21 +13 +13 +17 +21 +24 +25 +24 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +13 +65 +72 +59 +41 +25 +16 +16 +21 +26 +28 +28 +27 +23 +21 +19 +19 +18 +17 +16 +15 +-6 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +7 +60 +68 +54 +37 +21 +12 +11 +15 +21 +26 +26 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-103 +11 +65 +73 +59 +41 +25 +17 +15 +19 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-77 +-89 +-99 +-101 +13 +66 +75 +61 +43 +27 +18 +17 +21 +25 +29 +30 +28 +25 +22 +20 +19 +19 +18 +17 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-103 +-107 +6 +59 +67 +53 +37 +21 +12 +11 +16 +21 +25 +26 +24 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +66 +72 +58 +41 +25 +17 +15 +19 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-78 +-89 +-99 +-101 +14 +66 +74 +59 +41 +26 +18 +17 +21 +25 +29 +29 +27 +24 +22 +21 +20 +18 +17 +16 +16 +-6 +-25 +-43 +-58 +-72 +-83 +-94 +-104 +-106 +7 +60 +68 +54 +36 +21 +12 +12 +17 +22 +25 +25 +24 +1 +-18 +-36 +-52 +-67 +-79 +-90 +-100 +-103 +12 +65 +73 +59 +41 +26 +17 +15 +20 +25 +29 +29 +27 +24 +22 +19 +18 +18 +18 +17 +16 +-6 +-25 +-43 +-58 +-72 +-83 +-95 +-104 +-107 +5 +58 +67 +53 +36 +21 +13 +12 +16 +20 +24 +26 +25 +2 +-18 +-36 +-52 +-66 +-79 +-90 +-100 +-102 +12 +65 +72 +58 +41 +24 +16 +16 +21 +25 +27 +28 +27 +4 +-16 +-35 +-51 +-65 +-78 +-89 +-99 +-101 +14 +67 +74 +60 +42 +26 +17 +16 +21 +26 +29 +29 +28 +24 +22 +20 +19 +18 +18 +16 +15 +-7 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +6 +60 +67 +54 +36 +21 +13 +12 +17 +22 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +13 +66 +73 +58 +40 +25 +17 +16 +20 +25 +28 +29 +27 +24 +22 +20 +19 +17 +16 +16 +16 +-6 +-25 +-42 +-57 +-71 +-83 +-94 +-104 +-106 +6 +58 +66 +52 +35 +20 +12 +11 +17 +22 +25 +25 +24 +21 +19 +17 +16 +15 +15 +14 +13 +-8 +-27 +-44 +-59 +-73 +-85 +-96 +-105 +-108 +5 +59 +66 +52 +35 +20 +12 +11 +16 +21 +24 +25 +23 +0 +-19 +-37 +-53 +-67 +-80 +-91 +-100 +-103 +12 +65 +73 +59 +41 +24 +16 +16 +21 +25 +28 +29 +27 +23 +20 +18 +18 +18 +17 +15 +15 +-7 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +5 +58 +66 +53 +36 +21 +13 +12 +17 +22 +25 +26 +24 +2 +-18 +-36 +-52 +-67 +-79 +-90 +-100 +-102 +13 +65 +72 +58 +40 +24 +16 +15 +20 +25 +28 +28 +26 +23 +22 +20 +19 +18 +17 +15 +14 +-7 +-27 +-44 +-59 +-72 +-84 +-95 +-104 +-107 +5 +59 +67 +54 +36 +20 +12 +11 +16 +21 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +11 +64 +72 +58 +41 +25 +16 +15 +20 +24 +28 +29 +27 +4 +-16 +-34 +-50 +-65 +-77 +-89 +-99 +-101 +14 +66 +73 +60 +42 +26 +17 +16 +21 +25 +28 +29 +28 +25 +22 +20 +18 +17 +18 +16 +15 +-6 +-26 +-43 +-58 +-72 +-84 +-95 +-104 +-107 +5 +59 +66 +52 +35 +20 +12 +11 +16 +21 +25 +26 +24 +1 +-19 +-37 +-52 +-67 +-79 +-91 +-100 +-102 +13 +65 +73 +59 +41 +25 +17 +16 +20 +24 +28 +30 +28 +24 +22 +20 +19 +17 +16 +16 +16 +14 +13 +11 +11 +10 +9 +8 +8 +15 +26 +36 +46 +54 +60 +62 +61 +60 +56 +52 +48 +45 +43 +41 +38 +35 +33 +30 +29 +26 +24 +23 +21 +19 +17 +16 +15 +15 +14 +12 +11 +9 +9 +8 +7 +6 +5 +3 +0 +-3 +-2 +-1 +1 +2 +3 +3 +3 +2 +2 +2 +3 +2 +2 +1 +1 +1 +0 +0 +0 +0 +0 +-1 +-1 +-2 +-1 +-2 +-2 +-1 +-1 +-2 +-3 +-3 +-2 +-3 +-2 +-3 +-2 +-3 +-2 +-3 +-3 +-3 +-2 +-2 +-3 +-3 +-3 +-3 +-4 +-4 +-3 +-3 +-3 +-3 +-3 +-4 +-4 +-5 +-4 +-3 +-3 +-3 +-4 +-4 +-4 +-4 +-4 +-4 +-3 +-3 +-3 +-4 +-4 +-5 +-4 +-4 +-4 +-4 +-4 +-3 +-3 +-3 +-1 +-1 +0 +-1 +0 +0 +0 +-1 +-1 +-1 +0 +-1 +-1 +-1 +-1 +-2 +-2 +-2 +-1 +-1 +-2 +-3 +-2 +-3 +-2 +-3 +-2 +-2 +-2 +-3 +-4 +-3 +-3 +-3 +-3 +-4 +-3 +-4 +-4 +-5 +-4 +-4 +-3 +3 +21 +40 +54 +62 +65 +63 +61 +57 +54 +50 +47 +44 +41 +37 +34 +25 +8 +-10 +-26 +-39 +-46 +-48 +-47 +-47 +-46 +-45 +-43 +-41 +-39 +-36 +-35 +-27 +-9 +12 +29 +39 +45 +46 +45 +43 +41 +38 +36 +35 +33 +30 +27 +18 +3 +-14 +-29 +-42 +-48 +-51 +-52 +-52 +-49 +-47 +-44 +-43 +-40 +-38 +-38 +-29 +-10 +11 +29 +37 +43 +44 +44 +42 +39 +37 +35 +33 +32 +29 +26 +18 +3 +-15 +-30 +-43 +-49 +-52 +-52 +-51 +-49 +-46 +-45 +-43 +-40 +-38 +-36 +-29 +-10 +10 +27 +37 +42 +44 +44 +41 +38 +36 +34 +33 +31 +28 +26 +18 +2 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-49 +-47 +-44 +-42 +-39 +-38 +-37 +-30 +-10 +10 +28 +38 +43 +44 +43 +41 +39 +36 +35 +33 +32 +28 +26 +17 +1 +-16 +-31 +-43 +-49 +-52 +-53 +-51 +-49 +-46 +-44 +-42 +-39 +-38 +-38 +-37 +-35 +-33 +-30 +-29 +-27 +-25 +-23 +-21 +-21 +-20 +-18 +-17 +-16 +-16 +-16 +-9 +9 +29 +45 +54 +59 +59 +55 +52 +50 +47 +44 +41 +40 +36 +33 +23 +6 +-11 +-27 +-39 +-46 +-49 +-50 +-48 +-47 +-44 +-41 +-39 +-36 +-36 +-35 +-26 +-7 +14 +30 +41 +47 +46 +44 +42 +40 +38 +36 +33 +32 +29 +26 +16 +1 +-16 +-31 +-43 +-50 +-53 +-53 +-51 +-48 +-46 +-42 +-40 +-39 +-38 +-37 +-28 +-8 +12 +29 +39 +45 +45 +43 +41 +39 +37 +35 +32 +30 +27 +25 +16 +0 +-17 +-32 +-44 +-52 +-54 +-53 +-51 +-48 +-46 +-43 +-41 +-39 +-39 +-37 +-28 +-9 +12 +28 +38 +44 +44 +43 +41 +39 +36 +34 +31 +31 +28 +25 +16 +0 +-17 +-32 +-44 +-52 +-54 +-53 +-51 +-49 +-47 +-44 +-41 +-39 +-38 +-37 +-28 +-9 +11 +28 +38 +45 +45 +44 +40 +39 +36 +34 +32 +31 +29 +25 +22 +21 +19 +19 +17 +15 +14 +14 +13 +12 +11 +11 +10 +9 +6 +5 +-2 +-16 +-32 +-46 +-57 +-64 +-67 +-65 +-62 +-58 +-54 +-52 +-50 +-48 +-45 +-44 +-36 +-16 +4 +22 +31 +37 +39 +39 +37 +35 +32 +30 +28 +27 +25 +22 +14 +-1 +-18 +-32 +-45 +-52 +-55 +-54 +-52 +-49 +-46 +-44 +-43 +-40 +-38 +-37 +-37 +-35 +-33 +-31 +-30 +-28 +-25 +-23 +-21 +-20 +-19 +-19 +-18 +-17 +-17 +-16 +-8 +9 +28 +44 +53 +58 +58 +55 +52 +49 +46 +43 +39 +38 +35 +32 +29 +26 +24 +23 +21 +20 +19 +19 +18 +16 +14 +13 +12 +11 +9 +8 +0 +-14 +-30 +-44 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-51 +-49 +-45 +-43 +-43 +-42 +-40 +-38 +-36 +-35 +-31 +-29 +-26 +-25 +-24 +-23 +-21 +-20 +-19 +-18 +-18 +-11 +7 +26 +43 +52 +57 +56 +54 +51 +48 +44 +42 +40 +38 +35 +31 +28 +26 +24 +23 +21 +20 +19 +18 +16 +15 +14 +14 +13 +11 +9 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-65 +-62 +-58 +-54 +-51 +-49 +-46 +-45 +-45 +-43 +-40 +-37 +-34 +-33 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-19 +-19 +-19 +-11 +7 +27 +43 +52 +56 +55 +54 +51 +48 +45 +42 +39 +38 +35 +31 +29 +26 +24 +22 +20 +19 +18 +18 +16 +15 +14 +14 +12 +11 +9 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-52 +-49 +-46 +-45 +-45 +-43 +-41 +-38 +-36 +-34 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-19 +-18 +-19 +-11 +7 +26 +43 +52 +57 +56 +53 +50 +48 +45 +42 +40 +38 +35 +31 +28 +26 +25 +23 +20 +20 +18 +17 +16 +15 +14 +13 +12 +10 +9 +7 +-1 +-15 +-31 +-44 +-55 +-62 +-66 +-64 +-61 +-57 +-54 +-51 +-49 +-46 +-46 +-45 +-43 +-40 +-38 +-35 +-34 +-31 +-29 +-27 +-26 +-23 +-22 +-20 +-19 +-19 +-19 +-19 +-11 +7 +27 +44 +52 +56 +55 +53 +51 +48 +45 +42 +40 +38 +34 +30 +22 +5 +-12 +-27 +-40 +-47 +-50 +-50 +-49 +-46 +-43 +-40 +-39 +-37 +-36 +-35 +-27 +-8 +13 +30 +40 +46 +46 +44 +42 +39 +36 +34 +32 +31 +28 +25 +22 +21 +20 +19 +16 +16 +15 +14 +13 +12 +11 +11 +10 +8 +7 +5 +-2 +-16 +-32 +-46 +-57 +-63 +-67 +-66 +-63 +-58 +-55 +-52 +-50 +-47 +-46 +-45 +-44 +-41 +-38 +-35 +-34 +-31 +-29 +-27 +-26 +-24 +-22 +-20 +-20 +-20 +-19 +-19 +-11 +7 +27 +43 +52 +56 +55 +54 +51 +48 +45 +42 +39 +37 +34 +31 +22 +6 +-12 +-27 +-40 +-47 +-50 +-50 +-48 +-46 +-43 +-41 +-40 +-37 +-36 +-35 +-26 +-8 +13 +30 +39 +45 +45 +44 +42 +39 +36 +34 +32 +31 +28 +25 +22 +21 +19 +18 +16 +16 +15 +14 +13 +12 +11 +11 +9 +8 +7 +6 +-1 +-16 +-32 +-45 +-56 +-63 +-66 +-65 +-62 +-59 +-56 +-53 +-50 +-47 +-46 +-45 +-44 +-41 +-38 +-36 +-34 +-32 +-30 +-28 +-26 +-24 +-23 +-20 +-20 +-19 +-20 +-19 +-11 +7 +27 +42 +51 +56 +55 +53 +51 +48 +44 +41 +39 +37 +34 +30 +21 +5 +-12 +-28 +-41 +-48 +-50 +-50 +-48 +-46 +-44 +-41 +-39 +-37 +-36 +-35 +-26 +-8 +12 +30 +40 +46 +46 +44 +41 +39 +36 +34 +32 +31 +28 +25 +15 +0 +-17 +-32 +-44 +-51 +-54 +-54 +-52 +-49 +-45 +-43 +-41 +-39 +-38 +-37 +-28 +-9 +12 +29 +39 +44 +43 +42 +40 +38 +35 +33 +32 +30 +27 +24 +15 +0 +-17 +-32 +-45 +-52 +-55 +-54 +-52 +-49 +-45 +-42 +-41 +-39 +-38 +-37 +-28 +-9 +12 +29 +38 +43 +43 +42 +40 +38 +35 +33 +31 +29 +27 +24 +22 +21 +19 +17 +15 +14 +14 +13 +12 +11 +10 +10 +9 +8 +6 +5 +-2 +-17 +-33 +-46 +-57 +-63 +-66 +-65 +-62 +-59 +-55 +-52 +-50 +-47 +-46 +-45 +-43 +-41 +-38 +-36 +-34 +-32 +-30 +-27 +-26 +-24 +-22 +-21 +-20 +-20 +-20 +-19 +-11 +7 +26 +42 +51 +55 +54 +53 +50 +47 +44 +41 +39 +37 +34 +30 +27 +25 +23 +22 +20 +19 +17 +17 +16 +14 +14 +13 +11 +10 +8 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-61 +-57 +-54 +-52 +-49 +-47 +-46 +-45 +-43 +-41 +-38 +-36 +-34 +-32 +-29 +-27 +-25 +-24 +-22 +-21 +-20 +-19 +-19 +-18 +-11 +6 +26 +41 +51 +56 +55 +53 +50 +48 +45 +42 +39 +37 +34 +30 +27 +25 +23 +22 +19 +19 +18 +17 +16 +14 +13 +13 +11 +10 +8 +7 +0 +-15 +-31 +-45 +-56 +-62 +-65 +-64 +-62 +-58 +-55 +-52 +-50 +-46 +-45 +-44 +-43 +-41 +-39 +-35 +-34 +-31 +-29 +-27 +-25 +-24 +-23 +-21 +-20 +-19 +-19 +-20 +-12 +7 +27 +42 +51 +56 +56 +53 +50 +47 +45 +42 +39 +37 +33 +31 +21 +5 +-12 +-28 +-40 +-47 +-51 +-51 +-48 +-45 +-43 +-41 +-39 +-37 +-37 +-37 +-28 +-8 +13 +29 +39 +44 +45 +44 +41 +39 +36 +33 +29 +26 +23 +20 +5 +-15 +-34 +-51 +-67 +-80 +-93 +-102 +-108 +-110 +-109 +-106 +-102 +-97 +-93 +-88 +-83 +-77 +-73 +-68 +-61 +-56 +-52 +-50 +-49 +-47 +-44 +-41 +-40 +-38 +-36 +-34 +-33 +-31 +-29 +-25 +-23 +-21 +-21 +-20 +-17 +-17 +-17 +-18 +-17 +-16 +-16 +-16 +-17 +-15 +-14 +-12 +-12 +-12 +-12 +-13 +-15 +-14 +-14 +-13 +-14 +-13 +-13 +-12 +-11 +-12 +-11 +-10 +-10 +-10 +-10 +-9 +-9 +-8 +-9 +-9 +-8 +-7 +-7 +-8 +-8 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-7 +-6 +-6 +-6 +-7 +-7 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-6 +-5 +-6 +-6 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-6 +-5 +-5 +-6 +-6 +-6 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-6 +-6 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-5 +-5 +-4 +-5 +-6 +-6 +-5 +-5 +-4 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-4 +-5 +-6 +-5 +-5 +-4 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-6 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-5 +-6 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5 +-6 +-5 +-5 +-5 +-5 +-5 +-5 +-4 +-5 +-5 +-6 +-5 +-5 +-5