From 4e12287d19650c3e446deb83e87aa40121d65c18 Mon Sep 17 00:00:00 2001 From: Ralf Spenneberg Date: Fri, 4 Mar 2016 17:28:05 +0100 Subject: [PATCH 1/7] Experimental HitagS support --- armsrc/Makefile | 2 +- armsrc/appmain.c | 13 + armsrc/apps.h | 8 + armsrc/hitag2.c | 2 +- armsrc/hitagS.c | 2147 ++++++++++++++++++++++++++++++++++ client/cmdlfhitag.c | 139 ++- client/hid-flasher/usb_cmd.h | 6 + include/hitag2.h | 10 +- include/hitagS.h | 54 + include/usb_cmd.h | 7 + 10 files changed, 2376 insertions(+), 12 deletions(-) create mode 100644 armsrc/hitagS.c create mode 100644 include/hitagS.h diff --git a/armsrc/Makefile b/armsrc/Makefile index 69ea2300..0b540b84 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -15,7 +15,7 @@ APP_CFLAGS = -DWITH_ISO14443a_StandAlone -DWITH_LF -DWITH_ISO15693 -DWITH_ISO144 #-DWITH_LCD #SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2.c lfsampling.c pcf7931.c lfdemod.c protocols.c +SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c protocols.c SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO14443a = epa.c iso14443a.c mifareutil.c mifarecmd.c mifaresniff.c SRC_ISO14443b = iso14443b.c diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 782c57fa..475b1c1b 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -23,6 +23,7 @@ #include "legicrf.h" #include +#include #include "lfsampling.h" #include "BigBuf.h" #include "mifareutil.h" @@ -1016,6 +1017,18 @@ void UsbPacketReceived(uint8_t *packet, int len) case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); break; + case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content + SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes); + break; + case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file + check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes); + break; + case CMD_READ_HITAG_S://Reader for only Hitag S tags, args = key or challenge + ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); + break; + case CMD_WR_HITAG_S://writer for Hitag tags args=data to write,page and key or challenge + WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); + break; #endif #ifdef WITH_ISO15693 diff --git a/armsrc/apps.h b/armsrc/apps.h index c8397c38..4d4c8083 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -16,6 +16,7 @@ #include #include "common.h" #include "hitag2.h" +#include "hitagS.h" #include "mifare.h" #include "../common/crc32.h" #include "BigBuf.h" @@ -179,6 +180,13 @@ void SnoopHitag(uint32_t type); void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); void ReaderHitag(hitag_function htf, hitag_data* htd); +//hitagS.h +void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data); +void ReadHitagS(hitag_function htf, hitag_data* htd); +void WritePageHitagS(hitag_function htf, hitag_data* htd,int page); +void check_challenges(bool file_given, byte_t* data); + + // cmd.h bool cmd_receive(UsbCommand* cmd); bool cmd_send(uint32_t cmd, uint32_t arg0, uint32_t arg1, uint32_t arg2, void* data, size_t len); diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 508157de..46432d83 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -1148,7 +1148,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { case RHT2F_CRYPTO: { DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key,4); //HACK; 4 or 6?? I read both in the code. + memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code. Dbhexdump(6,key,false); blocknr = 0; bQuiet = false; diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c new file mode 100644 index 00000000..99565f1b --- /dev/null +++ b/armsrc/hitagS.c @@ -0,0 +1,2147 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// HitagS emulation (preliminary test version) +// +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- +// Some code was copied from Hitag2.c +//----------------------------------------------------------------------------- + + +#include +#include +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "hitagS.h" +#include "hitag2.h" +#include "string.h" +#include "BigBuf.h" + +#define CRC_PRESET 0xFF +#define CRC_POLYNOM 0x1D + +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) + +static bool bQuiet; +static bool bSuccessful; +static struct hitagS_tag tag; +static byte_t page_to_be_written = 0; +static int block_data_left = 0; +typedef enum modulation { + AC2K = 0, AC4K, MC4K, MC8K +} MOD; +static MOD m = AC2K; //used modulation +static uint32_t temp_uid; +static int temp2 = 0; +static int sof_bits; //number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; //password bytes +static uint32_t rnd = 0x74124485; //randomnumber +static int test = 0; +size_t blocknr; +bool end=false; + +// Single bit Hitag2 functions: +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 +#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) +#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) +#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) +#define uf20bs u32 + +static u32 f20(const u64 x) { + u32 i5; + + i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 + + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 + + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 + + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 + + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; + + return (ht2_f5c >> i5) & 1; +} +static u64 hitag2_round(u64 *state) { + u64 x = *state; + + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) + ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) + ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) + & 1) << 47); + + *state = x; + return f20(x); +} +static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) { + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; + for (i = 0; i < 32; i++) { + x >>= 1; + x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; + } + return x; +} +static u32 hitag2_byte(u64 *x) { + u32 i, c; + + for (i = 0, c = 0; i < 8; i++) + c += (u32) hitag2_round(x) << (i ^ 7); + return c; +} + +// Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) +// TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz +// Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) +// T0 = TIMER_CLOCK1 / 125000 = 192 +#define T0 192 + +#define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) + +#define HITAG_FRAME_LEN 20 +#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ +#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_1_MIN 25 /* 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_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ + +#define HITAG_T_TAG_ONE_HALF_PERIOD 10 +#define HITAG_T_TAG_TWO_HALF_PERIOD 25 +#define HITAG_T_TAG_THREE_HALF_PERIOD 41 +#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 + +#define HITAG_T_TAG_HALF_PERIOD 16 +#define HITAG_T_TAG_FULL_PERIOD 32 + +#define HITAG_T_TAG_CAPTURE_ONE_HALF 13 +#define HITAG_T_TAG_CAPTURE_TWO_HALF 25 +#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 +#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 + +#define DEBUG 0 + +/* + * Implementation of the crc8 calculation from Hitag S + * from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf + */ +void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) { + *crc ^= data; // crc = crc (exor) data + do { + if (*crc & 0x80) // if (MSB-CRC == 1) + { + *crc <<= 1; // CRC = CRC Bit-shift left + *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM + } else { + *crc <<= 1; // CRC = CRC Bit-shift left + } + } while (--Bitcount); +} + +static void hitag_send_bit(int bit) { + LED_A_ON(); + // Reset clock for the next bit + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + + switch (m) { + case AC2K: + if (bit == 0) { + // AC Coding --__ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 64) + ; + } else { + // AC coding -_-_ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) + ; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 48) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 64) + ;; + } + LED_A_OFF(); + break; + case AC4K: + if (bit == 0) { + // AC Coding --__ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD) + ; + } else { + // AC coding -_-_ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 24) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) + ;; + } + LED_A_OFF(); + break; + case MC4K: + if (bit == 0) { + // Manchester: Unloaded, then loaded |__--| + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) + ; + } else { + // Manchester: Loaded, then unloaded |--__| + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) + ; + } + LED_A_OFF(); + break; + case MC8K: + if (bit == 0) { + // Manchester: Unloaded, then loaded |__--| + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) + ; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + } else { + // Manchester: Loaded, then unloaded |--__| + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) + ; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) + ; + } + LED_A_OFF(); + break; + default: + break; + } +} + +static void hitag_send_frame(const byte_t* frame, size_t frame_len) { +// Send start of frame + + for (size_t i = 0; i < sof_bits; i++) { + hitag_send_bit(1); + } + +// Send the content of the frame + for (size_t i = 0; i < frame_len; i++) { + hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + } +// Drop the modulation + LOW(GPIO_SSC_DOUT); +} + +static void hitag_reader_send_bit(int bit) { +//Dbprintf("BIT: %d",bit); + LED_A_ON(); +// Reset clock for the next bit + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + +// Binary puls length modulation (BPLM) is used to encode the data stream +// This means that a transmission of a one takes longer than that of a zero + +// Enable modulation, which means, drop the the field + HIGH(GPIO_SSC_DOUT); + if (test == 1) { + // Wait for 4-10 times the carrier period + while (AT91C_BASE_TC0->TC_CV < T0 * 6) + ; + // SpinDelayUs(8*8); + + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); + + if (bit == 0) { + // Zero bit: |_-| + while (AT91C_BASE_TC0->TC_CV < T0 * 11) + ; + // SpinDelayUs(16*8); + } else { + // One bit: |_--| + while (AT91C_BASE_TC0->TC_CV < T0 * 14) + ; + // SpinDelayUs(22*8); + } + } else { + // Wait for 4-10 times the carrier period + while (AT91C_BASE_TC0->TC_CV < T0 * 6) + ; + // SpinDelayUs(8*8); + + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); + + if (bit == 0) { + // Zero bit: |_-| + while (AT91C_BASE_TC0->TC_CV < T0 * 22) + ; + // SpinDelayUs(16*8); + } else { + // One bit: |_--| + while (AT91C_BASE_TC0->TC_CV < T0 * 28) + ; + // SpinDelayUs(22*8); + } + } + + LED_A_OFF(); +} + +static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) { +// Send the content of the frame + for (size_t i = 0; i < frame_len; i++) { + if (frame[0] == 0xf8) { + //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); + } + hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + } +// Send EOF + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; +// Enable modulation, which means, drop the the field + HIGH(GPIO_SSC_DOUT); +// Wait for 4-10 times the carrier period + while (AT91C_BASE_TC0->TC_CV < T0 * 6) + ; +// Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); +} + +/* + * to check if the right uid was selected + */ +static int check_select(byte_t* rx, uint32_t uid) { + unsigned char resp[48]; + int i; + uint32_t ans = 0x0; + for (i = 0; i < 48; i++) + resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; + for (i = 0; i < 32; i++) + ans += resp[5 + i] << (31 - i); + /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 + && rx[4] == 0x65 && rx[5] == 0x38) + Dbprintf("got uid %X", ans);*/ + temp_uid = ans; + if (ans == tag.uid) + return 1; + return 0; +} + +/* + * handles all commands from a reader + */ +static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen, + byte_t* tx, size_t* txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; + byte_t page; + int i; + u64 state; + unsigned char crc; + +// Copy the (original) received frame how it is send over the air + memcpy(rx_air, rx, nbytes(rxlen)); +// Reset the transmission frame length + *txlen = 0; +// Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + case 5: { + //UID request with a selected response protocol mode + tag.pstate = READY; + tag.tstate = NO_OP; + if ((rx[0] & 0xf0) == 0x30) { + tag.mode = STANDARD; + sof_bits = 1; + m = AC2K; + } + if ((rx[0] & 0xf0) == 0xc0) { + tag.mode = ADVANCED; + sof_bits = 3; + m = AC2K; + } + + if ((rx[0] & 0xf0) == 0xd0) { + tag.mode = FAST_ADVANCED; + sof_bits = 3; + m = AC4K; + } + //send uid as a response + *txlen = 32; + for (i = 0; i < 4; i++) + tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff; + } + break; + case 45: { + //select command from reader received + if (check_select(rx, tag.uid) == 1) { + //if the right tag was selected + *txlen = 32; + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + + //send configuration + for (i = 0; i < 4; i++) + tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff; + tx[3] = 0xff; + if (tag.mode != STANDARD) { + *txlen = 40; + crc = CRC_PRESET; + for (i = 0; i < 4; i++) + calc_crc(&crc, tx[i], 8); + tx[4] = crc; + } + } + } + break; + case 64: { + //challenge message received + Dbprintf("Challenge for UID: %X", temp_uid); + temp2++; + *txlen = 32; + state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), + rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); + Dbprintf( + ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", + rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + + for (i = 0; i < 4; i++) + hitag2_byte(&state); + //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response + tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); + tx[1] = hitag2_byte(&state) ^ tag.pwdh0; + tx[2] = hitag2_byte(&state) ^ tag.pwdl0; + tx[3] = hitag2_byte(&state) ^ tag.pwdl1; + if (tag.mode != STANDARD) { + //add crc8 + *txlen = 40; + crc = CRC_PRESET; + calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8); + calc_crc(&crc, tag.pwdh0, 8); + calc_crc(&crc, tag.pwdl0, 8); + calc_crc(&crc, tag.pwdl1, 8); + tx[4] = (crc ^ hitag2_byte(&state)); + } + /* + * some readers do not allow to authenticate multiple times in a row with the same tag. + * use this to change the uid between authentications. + */ + + /* + if (temp2 % 2 == 0) { + tag.uid = 0x11223344; + tag.pages[0][0] = 0x44332211; + } else { + tag.uid = 0x55667788; + tag.pages[0][0] = 0x88776655; + } + */ + } + case 40: + //data received to be written + if (tag.tstate == WRITING_PAGE_DATA) { + tag.tstate = NO_OP; + tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] + << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24); + //send ack + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = 0; + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + } else if (tag.tstate == WRITING_BLOCK_DATA) { + tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] + << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3]; + //send ack + *txlen = 2; + tx[0] = 0x40; + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + page_to_be_written++; + block_data_left--; + if (block_data_left == 0) { + tag.tstate = NO_OP; + page_to_be_written = 0; + } + } + break; + case 20: { + //write page, write block, read page or read block command received + if ((rx[0] & 0xf0) == 0xc0) //read page + { + //send page data + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + *txlen = 32; + tx[0] = (tag.pages[page / 4][page % 4]) & 0xff; + tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; + tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; + tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; + if (tag.LKP && page == 1) + tx[3] = 0xff; + + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + + if (tag.mode != STANDARD) { + //add crc8 + *txlen = 40; + crc = CRC_PRESET; + for (i = 0; i < 4; i++) + calc_crc(&crc, tx[i], 8); + tx[4] = crc; + } + + if (tag.LKP && (page == 2 || page == 3)) { + //if reader asks for key or password and the LKP-mark is set do not respond + sof_bits = 0; + *txlen = 0; + } + } else if ((rx[0] & 0xf0) == 0xd0) //read block + { + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + *txlen = 32 * 4; + //send page,...,page+3 data + for (i = 0; i < 4; i++) { + tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff; + tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; + tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; + tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; + page++; + } + + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + + if (tag.mode != STANDARD) { + //add crc8 + *txlen = 32 * 4 + 8; + crc = CRC_PRESET; + for (i = 0; i < 16; i++) + calc_crc(&crc, tx[i], 8); + tx[16] = crc; + } + + if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) { + sof_bits = 0; + *txlen = 0; + } + } else if ((rx[0] & 0xf0) == 0x80) //write page + { + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + if ((tag.LCON && page == 1) + || (tag.LKP && (page == 2 || page == 3))) { + //deny + *txlen = 0; + } else { + //allow + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = page; + tag.tstate = WRITING_PAGE_DATA; + } + + } else if ((rx[0] & 0xf0) == 0x90) //write block + { + page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16); + switch (tag.mode) { + case STANDARD: + sof_bits = 1; + m = MC4K; + break; + case ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + if (page % 4 != 0 || page == 0) { + //deny + *txlen = 0; + } else { + //allow + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = page; + block_data_left = 4; + tag.tstate = WRITING_BLOCK_DATA; + } + } + } + break; + default: + + break; + } +} + +/* + * to autenticate to a tag with the given key or challenge + */ +static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, const size_t rxlen, byte_t* tx, + size_t* txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; + int response_bit[200]; + int i, j, z, k; + unsigned char mask = 1; + unsigned char uid[32]; + byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; + unsigned char crc; + u64 state; + byte_t auth_ks[4]; + byte_t conf_pages[3]; + memcpy(rx_air, rx, nbytes(rxlen)); + *txlen = 0; + + if (tag.pstate == READY && rxlen >= 67) { + //received uid + if(end==true) { + Dbprintf("authentication failed!"); + return -1; + } + z = 0; + for (i = 0; i < 10; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 5; i < z; i += 2) { + uid[k] = response_bit[i]; + k++; + if (k > 31) + break; + } + uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) + | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; + uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) + | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; + uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) + | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; + uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) + | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; + if (DEBUG) + Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); + tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); + + //select uid + *txlen = 45; + crc = CRC_PRESET; + calc_crc(&crc, 0x00, 5); + calc_crc(&crc, uid1, 8); + calc_crc(&crc, uid2, 8); + calc_crc(&crc, uid3, 8); + calc_crc(&crc, uid4, 8); + for (i = 0; i < 100; i++) { + response_bit[i] = 0; + } + for (i = 0; i < 5; i++) { + response_bit[i] = 0; + } + for (i = 5; i < 37; i++) { + response_bit[i] = uid[i - 5]; + } + for (j = 0; j < 8; j++) { + response_bit[i] = 0; + if ((crc & ((mask << 7) >> j)) != 0) + response_bit[i] = 1; + i++; + } + k = 0; + for (i = 0; i < 6; i++) { + tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) | response_bit[k + 7]; + k += 8; + } + tag.pstate = INIT; + } else if (tag.pstate == INIT && rxlen == 44) { + // received configuration after select command + z = 0; + for (i = 0; i < 6; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6) + | (response_bit[6] << 5) | (response_bit[7] << 4) + | (response_bit[8] << 3) | (response_bit[9] << 2) + | (response_bit[10] << 1) | response_bit[11]); + //check wich memorysize this tag has + if (response_bit[10] == 0 && response_bit[11] == 0) + tag.max_page = 32 / 32; + if (response_bit[10] == 0 && response_bit[11] == 1) + tag.max_page = 256 / 32; + if (response_bit[10] == 1 && response_bit[11] == 0) + tag.max_page = 2048 / 32; + conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6) + | (response_bit[14] << 5) | (response_bit[15] << 4) + | (response_bit[16] << 3) | (response_bit[17] << 2) + | (response_bit[18] << 1) | response_bit[19]); + tag.auth = response_bit[12]; + tag.TTFC = response_bit[13]; + //tag.TTFDR in response_bit[14] and response_bit[15] + //tag.TTFM in response_bit[16] and response_bit[17] + tag.LCON = response_bit[18]; + tag.LKP = response_bit[19]; + conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6) + | (response_bit[22] << 5) | (response_bit[23] << 4) + | (response_bit[24] << 3) | (response_bit[25] << 2) + | (response_bit[26] << 1) | response_bit[27]); + tag.LCK7 = response_bit[20]; + tag.LCK6 = response_bit[21]; + tag.LCK5 = response_bit[22]; + tag.LCK4 = response_bit[23]; + tag.LCK3 = response_bit[24]; + tag.LCK2 = response_bit[25]; + tag.LCK1 = response_bit[26]; + tag.LCK0 = response_bit[27]; + + if (DEBUG) + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], + conf_pages[1], conf_pages[2]); + if (tag.auth == 1) { + //if the tag is in authentication mode try the key or challenge + *txlen = 64; + if(end!=true){ + if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY + state = hitag2_init(rev64(key), rev32(tag.uid), + rev32(rnd)); + + for (i = 0; i < 4; i++) { + auth_ks[i] = hitag2_byte(&state) ^ 0xff; + } + *txlen = 64; + tx[0] = rnd & 0xff; + tx[1] = (rnd >> 8) & 0xff; + tx[2] = (rnd >> 16) & 0xff; + tx[3] = (rnd >> 24) & 0xff; + + tx[4] = auth_ks[0]; + tx[5] = auth_ks[1]; + tx[6] = auth_ks[2]; + tx[7] = auth_ks[3]; + if (DEBUG) + Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], + tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); + } else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE + for (i = 0; i < 8; i++) + tx[i]=((NrAr>>(56-(i*8)))&0xff); + } + end=true; + tag.pstate = AUTHENTICATE; + } else { + Dbprintf("authentication failed!"); + return -1; + } + } else if (tag.auth == 0) { + tag.pstate = SELECTED; + } + + } else if (tag.pstate == AUTHENTICATE && rxlen == 44) { + //encrypted con2,password received. + crc = CRC_PRESET; + calc_crc(&crc, 0x80, 1); + calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8); + if (DEBUG) { + Dbprintf("UID:::%X", tag.uid); + Dbprintf("RND:::%X", rnd); + } + + //decrypt password + pwdh0=0; + pwdl0=0; + pwdl1=0; + if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY + { + state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); + for (i = 0; i < 5; i++) + hitag2_byte(&state); + pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) + ^ hitag2_byte(&state); + } + + if (DEBUG) + Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); + + + //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); + //rnd += 1; + } + tag.pstate = SELECTED; //tag is now ready for read/write commands + } + return 0; + +} + +/* + * Emulates a Hitag S Tag with the given data from the .hts file + */ +void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { + int frame_count; + int response; + int overflow; + int i, j; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; +//bool bQuitTraceFull = false; + bQuiet = false; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + BigBuf_free(); + +// Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + + DbpString("Starting HitagS simulation"); + LED_D_ON(); + + tag.pstate = READY; + tag.tstate = NO_OP; + for (i = 0; i < 16; i++) + for (j = 0; j < 4; j++) + tag.pages[i][j] = 0x0; + //read tag data into memory + if (tag_mem_supplied) { + DbpString("Loading hitagS memory..."); + memcpy((byte_t*)tag.pages,data,4*64); + } + tag.uid=(uint32_t)tag.pages[0]; + Dbprintf("Hitag S simulation started"); + tag.key=(intptr_t)tag.pages[3]; + tag.key<<=16; + tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1]; + tag.pwdl0=tag.pages[2][3]; + tag.pwdl1=tag.pages[2][2]; + tag.pwdh0=tag.pages[1][0]; + //con0 + tag.max_page=64; + if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1) + tag.max_page=8; + if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0) + tag.max_page=0; + //con1 + tag.auth=0; + if((tag.pages[1][2]&0x80)==1) + tag.auth=1; + tag.LCON=0; + if((tag.pages[1][2]&0x2)==1) + tag.LCON=1; + tag.LKP=0; + if((tag.pages[1][2]&0x1)==1) + tag.LKP=1; + //con2 + //0=read write 1=read only + tag.LCK7=0; + if((tag.pages[1][1]&0x80)==1) + tag.LCK7=1; + tag.LCK6=0; + if((tag.pages[1][1]&0x40)==1) + tag.LCK6=1; + tag.LCK5=0; + if((tag.pages[1][1]&0x20)==1) + tag.LCK5=1; + tag.LCK4=0; + if((tag.pages[1][1]&0x10)==1) + tag.LCK4=1; + tag.LCK3=0; + if((tag.pages[1][1]&0x8)==1) + tag.LCK3=1; + tag.LCK2=0; + if((tag.pages[1][1]&0x4)==1) + tag.LCK2=1; + tag.LCK1=0; + if((tag.pages[1][1]&0x2)==1) + tag.LCK1=1; + tag.LCK0=0; + if((tag.pages[1][1]&0x1)==1) + tag.LCK0=1; + +// Set up simulator mode, frequency divisor which will drive the FPGA +// and analog mux selection. + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); + +// Configure output pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + +// Disable modulation at default, which means release resistance + LOW(GPIO_SSC_DOUT); + +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + +// Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + +// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on rising edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; + +// Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; + +// Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + while (!BUTTON_PRESS()) { + // 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) + overflow; + overflow = 0; + + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + 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 + } + } + } + + // Check if frame was captured + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, true)) { + DbpString("Trace full"); + clear_trace(); + } + } + + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + + // Process the incoming frame (rx) and prepare the outgoing frame (tx) + hitagS_handle_reader_command(rx, rxlen, tx, &txlen); + + // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, + // not that since the clock counts since the rising edge, but T_Wait1 is + // 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)) + ; + + // Send and store the tag answer (if there is any) + if (txlen > 0) { + // Transmit the tag frame + hitag_send_frame(tx, txlen); + // Store the frame in the trace + if (!bQuiet) { + if (!LogTraceHitag(tx, txlen, 0, 0, false)) { + DbpString("Trace full"); + clear_trace(); + } + } + } + + // Reset the received frame and response timing info + memset(rx, 0x00, sizeof(rx)); + response = 0; + + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + LED_B_OFF(); + } + // Reset the frame length + rxlen = 0; + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV / T0); + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); +} + +/* + * Authenticates to the Tag with the given key or challenge. + * If the key was given the password will be decrypted. + * Reads every page of a hitag S transpoder. + */ +void ReadHitagS(hitag_function htf, hitag_data* htd) { + int i, j, z, k; + int frame_count; + int response_bit[200]; + int response; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop; + bool bQuitTraceFull = false; + int sendNum = 0; + unsigned char mask = 1; + unsigned char crc; + unsigned char pageData[32]; + page_to_be_written = 0; + + //read given key/challenge + byte_t NrAr_[8]; + uint64_t key=0; + uint64_t NrAr=0; + byte_t key_[6]; + switch(htf) { + case 01: { //RHTS_CHALLENGE + DbpString("Authenticating using nr,ar pair:"); + memcpy(NrAr_,htd->auth.NrAr,8); + Dbhexdump(8,NrAr_,false); + NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | + ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + } break; + case 02: { //RHTS_KEY + DbpString("Authenticating using key:"); + memcpy(key_,htd->crypto.key,6); + Dbhexdump(6,key_,false); + key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + } break; + default: { + Dbprintf("Error , unknown function: %d",htf); + return; + } break; + } + + + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); +// Reset the return status + bSuccessful = false; + +// Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + + bQuiet = false; + bQuitTraceFull = true; + + LED_D_ON(); + +// Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + +// Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + +// Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); + +// Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); + +// Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); + +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + +// Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + +// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on falling edge of TIOA. + 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; + +// Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; + + reset_sof = 1; + t_wait = 200; + + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } + + // By default reset the transmission buffer + tx = txbuf; + txlen = 0; + + if (rxlen == 0) { + //start authentication + txlen = 5; + memcpy(tx, "\xc0", nbytes(txlen)); + tag.pstate = READY; + tag.tstate = NO_OP; + } else if (tag.pstate != SELECTED) { + if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1) + bStop = !false; + } + if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) { + //send read request + tag.tstate = READING_PAGE; + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0xc0 + (sendNum / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); + tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + } else if (tag.pstate == SELECTED && tag.tstate == READING_PAGE + && rxlen > 0) { + //save received data + z = 0; + for (i = 0; i < 5; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 4; i < 36; i++) { + pageData[k] = response_bit[i]; + k++; + } + for (i = 0; i < 4; i++) + tag.pages[sendNum / 4][sendNum % 4] = 0x0; + for (i = 0; i < 4; i++) { + tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7) + | (pageData[1 + (i * 8)] << 6) + | (pageData[2 + (i * 8)] << 5) + | (pageData[3 + (i * 8)] << 4) + | (pageData[4 + (i * 8)] << 3) + | (pageData[5 + (i * 8)] << 2) + | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)]) + << (i * 8); + } + if (tag.auth && tag.LKP && sendNum == 1) { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0, + (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, + tag.pages[sendNum / 4][sendNum % 4] & 0xff); + } else { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, + (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, + tag.pages[sendNum / 4][sendNum % 4] & 0xff); + } + + sendNum++; + //display key and password if possible + if (sendNum == 2 && tag.auth == 1 && tag.LKP) { + if (htf == 02) { //RHTS_KEY + Dbprintf("Page[ 2]: %02X %02X %02X %02X", + (byte_t)(key >> 8) & 0xff, + (byte_t) key & 0xff, pwdl1, pwdl0); + Dbprintf("Page[ 3]: %02X %02X %02X %02X", + (byte_t)(key >> 40) & 0xff, + (byte_t)(key >> 32) & 0xff, + (byte_t)(key >> 24) & 0xff, + (byte_t)(key >> 16) & 0xff); + } else { + //if the authentication is done with a challenge the key and password are unknown + Dbprintf("Page[ 2]: __ __ __ __"); + Dbprintf("Page[ 3]: __ __ __ __"); + } + } + + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0xc0 + (sendNum / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); + tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + if (sendNum >= tag.max_page) { + bStop = !false; + } + } + + // 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 occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; + + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); + + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } + + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 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); + + // 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) { + //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 + } + } + + // 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; + } + } + } + end=false; + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); +} + +/* + * Authenticates to the Tag with the given Key or Challenge. + * Writes the given 32Bit data into page_ + */ +void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop; + bool bQuitTraceFull = false; + int page = page_; + unsigned char crc; + byte_t data[4]= {0,0,0,0}; + + //read given key/challenge, the page and the data + byte_t NrAr_[8]; + uint64_t key=0; + uint64_t NrAr=0; + byte_t key_[6]; + switch(htf) { + case 03: { //WHTS_CHALLENGE + memcpy(data,htd->auth.data,4); + DbpString("Authenticating using nr,ar pair:"); + memcpy(NrAr_,htd->auth.NrAr,8); + Dbhexdump(8,NrAr_,false); + NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | + ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + } break; + case 04: { //WHTS_KEY + memcpy(data,htd->crypto.data,4); + DbpString("Authenticating using key:"); + memcpy(key_,htd->crypto.key,6); + Dbhexdump(6,key_,false); + key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + } break; + default: { + Dbprintf("Error , unknown function: %d",htf); + return; + } break; + } + + Dbprintf("Page: %d",page_); + Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); +// Reset the return status + bSuccessful = false; + + tag.pstate = READY; + tag.tstate = NO_OP; + +// Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + + bQuiet = false; + bQuitTraceFull = true; + + LED_D_ON(); + +// Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + +// Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + +// Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); + +// Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); + +// Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); + +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + +// Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + +// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on falling edge of TIOA. + 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; + +// Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; + + reset_sof = 1; + t_wait = 200; + + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } + + //check for valid input + if (page == 0) { + Dbprintf( + "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); + bStop = !false; + } + + // By default reset the transmission buffer + tx = txbuf; + txlen = 0; + + if (rxlen == 0 && tag.tstate == WRITING_PAGE_ACK) { + //no write access on this page + Dbprintf("no write access on page %d", page_); + bStop = !false; + } else if (rxlen == 0 && tag.tstate != WRITING_PAGE_DATA) { + //start the authetication + txlen = 5; + memcpy(tx, "\xc0", nbytes(txlen)); + tag.pstate = READY; + tag.tstate = NO_OP; + } else if (tag.pstate != SELECTED) { + //try to authenticate with the given key or challenge + if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1) + bStop = !false; + } + if (tag.pstate == SELECTED && tag.tstate == NO_OP && rxlen > 0) { + //check if the given page exists + if (page > tag.max_page) { + Dbprintf("page number too big"); + bStop = !false; + } + //ask Tag for write permission + tag.tstate = WRITING_PAGE_ACK; + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0x90 + (page / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((page % 16) * 16), 4); + tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_ACK + && rxlen == 6 && rx[0] == 0xf4) { + //ACK recieved to write the page. send data + tag.tstate = WRITING_PAGE_DATA; + txlen = 40; + crc = CRC_PRESET; + calc_crc(&crc, data[3], 8); + calc_crc(&crc, data[2], 8); + calc_crc(&crc, data[1], 8); + calc_crc(&crc, data[0], 8); + tx[0] = data[3]; + tx[1] = data[2]; + tx[2] = data[1]; + tx[3] = data[0]; + tx[4] = crc; + } else if (tag.pstate == SELECTED && tag.tstate == WRITING_PAGE_DATA + && rxlen == 6 && rx[0] == 0xf4) { + //received ACK + Dbprintf("Successful!"); + bStop = !false; + } + + // 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 occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; + + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); + + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } + + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 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); + + // 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) { + //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 + } + } + + // 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; + } + } + } + end=false; + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); +} + +/* + * Tries to authenticate to a Hitag S Transponder with the given challenges from a .cc file. + * Displays all Challenges that failed. + * When collecting Challenges to break the key it is possible that some data + * is not received correctly due to Antenna problems. This function + * detects these challenges. + */ +void check_challenges(bool file_given, byte_t* data) { + int i, j, z, k; + byte_t uid_byte[4]; + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; + byte_t unlocker[60][8]; + int u1 = 0; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + int STATE = 0; + bool bStop; + bool bQuitTraceFull = false; + int response_bit[200]; + unsigned char mask = 1; + unsigned char uid[32]; + unsigned char crc; + + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); +// Reset the return status + bSuccessful = false; + +// Clean up trace and prepare it for storing frames + set_tracing(TRUE); + clear_trace(); + + bQuiet = false; + bQuitTraceFull = true; + + LED_D_ON(); + +// Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + +// Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + +// Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); + +// Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); + +// Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); + +// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + +// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + +// Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + +// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, +// external trigger rising edge, load RA on falling edge of TIOA. + 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; + +// Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; + + reset_sof = 1; + t_wait = 200; + + if (file_given) { + DbpString("Loading challenges..."); + memcpy((byte_t*)unlocker,data,60*8); + } + + while (file_given && !bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); + + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } + + tx = txbuf; + txlen = 0; + if (rxlen == 0) { + if (STATE == 2) + // challenge failed + Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X", + unlocker[u1 - 1][0], unlocker[u1 - 1][1], + unlocker[u1 - 1][2], unlocker[u1 - 1][3], + unlocker[u1 - 1][4], unlocker[u1 - 1][5], + unlocker[u1 - 1][6], unlocker[u1 - 1][7]); + STATE = 0; + txlen = 5; + //start new authentication + memcpy(tx, "\xc0", nbytes(txlen)); + } else if (rxlen >= 67 && STATE == 0) { + //received uid + z = 0; + for (i = 0; i < 10; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 5; i < z; i += 2) { + uid[k] = response_bit[i]; + k++; + if (k > 31) + break; + } + uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) + | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2) + | (uid[6] << 1) | uid[7]; + uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) + | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2) + | (uid[14] << 1) | uid[15]; + uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) + | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2) + | (uid[22] << 1) | uid[23]; + uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) + | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2) + | (uid[30] << 1) | uid[31]; + //Dbhexdump(10, rx, rxlen); + STATE = 1; + txlen = 45; + crc = CRC_PRESET; + calc_crc(&crc, 0x00, 5); + calc_crc(&crc, uid_byte[0], 8); + calc_crc(&crc, uid_byte[1], 8); + calc_crc(&crc, uid_byte[2], 8); + calc_crc(&crc, uid_byte[3], 8); + for (i = 0; i < 100; i++) { + response_bit[i] = 0; + } + for (i = 0; i < 5; i++) { + response_bit[i] = 0; + } + for (i = 5; i < 37; i++) { + response_bit[i] = uid[i - 5]; + } + for (j = 0; j < 8; j++) { + response_bit[i] = 0; + if ((crc & ((mask << 7) >> j)) != 0) + response_bit[i] = 1; + i++; + } + k = 0; + for (i = 0; i < 6; i++) { + tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) + | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) + | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) | response_bit[k + 7]; + k += 8; + } + + } else if (STATE == 1 && rxlen == 44) { + //received configuration + STATE = 2; + z = 0; + for (i = 0; i < 6; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + txlen = 64; + + if (u1 >= (sizeof(unlocker) / sizeof(unlocker[0]))) + bStop = !false; + for (i = 0; i < 8; i++) + tx[i] = unlocker[u1][i]; + u1++; + + } else if (STATE == 2 && rxlen >= 44) { + STATE = 0; + } + + // 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 occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; + + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); + + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } + + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 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); + + // 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) { + //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 + } + } + + // 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; + } + } + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); +} + + + diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index fe5ba587..07247364 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -18,6 +18,7 @@ #include "common.h" #include "util.h" #include "hitag2.h" +#include "hitagS.h" #include "sleep.h" #include "cmdmain.h" @@ -190,14 +191,20 @@ int CmdLFHitagSim(const char *Cmd) { } int CmdLFHitagReader(const char *Cmd) { -// UsbCommand c = {CMD_READER_HITAG}; - -// param_get32ex(Cmd,1,0,16); UsbCommand c = {CMD_READER_HITAG};//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}}; hitag_data* htd = (hitag_data*)c.d.asBytes; hitag_function htf = param_get32ex(Cmd,0,0,10); switch (htf) { + case 01: { //RHTSF_CHALLENGE + c = (UsbCommand){ CMD_READ_HITAG_S }; + num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->auth.NrAr); + num_to_bytes(param_get32ex(Cmd,2,0,16),4,htd->auth.NrAr+4); + } break; + case 02: { //RHTSF_KEY + c = (UsbCommand){ CMD_READ_HITAG_S }; + num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key); + } break; case RHT2F_PASSWORD: { num_to_bytes(param_get32ex(Cmd,1,0,16),4,htd->pwd.password); } break; @@ -216,6 +223,8 @@ int CmdLFHitagReader(const char *Cmd) { PrintAndLog("Error: unkown reader function %d",htf); PrintAndLog("Hitag reader functions"); PrintAndLog(" HitagS (0*)"); + PrintAndLog(" 01 (Challenge) read all pages from a Hitag S tag"); + PrintAndLog(" 02 (set to 0 if no authentication is needed) read all pages from a Hitag S tag"); PrintAndLog(" Hitag1 (1*)"); PrintAndLog(" Hitag2 (2*)"); PrintAndLog(" 21 (password mode)"); @@ -257,14 +266,126 @@ int CmdLFHitagReader(const char *Cmd) { return 0; } + +int CmdLFHitagSimS(const char *Cmd) { + UsbCommand c = { CMD_SIMULATE_HITAG_S }; + char filename[FILE_PATH_SIZE] = { 0x00 }; + FILE* pf; + bool tag_mem_supplied; + int len = strlen(Cmd); + if (len > FILE_PATH_SIZE) + len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); + + if (strlen(filename) > 0) { + if ((pf = fopen(filename, "rb+")) == NULL) { + PrintAndLog("Error: Could not open file [%s]", filename); + return 1; + } + tag_mem_supplied = true; + if (fread(c.d.asBytes, 4*64, 1, pf) == 0) { + PrintAndLog("Error: File reading error"); + fclose(pf); + return 1; + } + fclose(pf); + } else { + tag_mem_supplied = false; + } + + // Does the tag comes with memory + c.arg[0] = (uint32_t) tag_mem_supplied; + + SendCommand(&c); + return 0; +} + +int CmdLFHitagCheckChallenges(const char *Cmd) { + UsbCommand c = { CMD_TEST_HITAGS_TRACES }; + char filename[FILE_PATH_SIZE] = { 0x00 }; + FILE* pf; + bool file_given; + int len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); + + if (strlen(filename) > 0) { + if ((pf = fopen(filename,"rb+")) == NULL) { + PrintAndLog("Error: Could not open file [%s]",filename); + return 1; + } + file_given = true; + if (fread(c.d.asBytes,8*60,1,pf) == 0) { + PrintAndLog("Error: File reading error"); + fclose(pf); + return 1; + } + fclose(pf); + } else { + file_given = false; + } + + //file with all the challenges to try + c.arg[0] = (uint32_t)file_given; + + SendCommand(&c); + return 0; +} + + +int CmdLFHitagWP(const char *Cmd) { + UsbCommand c = { CMD_WR_HITAG_S }; + hitag_data* htd = (hitag_data*)c.d.asBytes; + hitag_function htf = param_get32ex(Cmd,0,0,10); + switch (htf) { + case 03: { //WHTSF_CHALLENGE + num_to_bytes(param_get64ex(Cmd,1,0,16),8,htd->auth.NrAr); + c.arg[2]= param_get32ex(Cmd, 2, 0, 10); + num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->auth.data); + } break; + case 04: { //WHTSF_KEY + num_to_bytes(param_get64ex(Cmd,1,0,16),6,htd->crypto.key); + c.arg[2]= param_get32ex(Cmd, 2, 0, 10); + num_to_bytes(param_get32ex(Cmd,3,0,16),4,htd->crypto.data); + + } break; + default: { + PrintAndLog("Error: unkown writer function %d",htf); + PrintAndLog("Hitag writer functions"); + PrintAndLog(" HitagS (0*)"); + PrintAndLog(" 03 (Challenge) write page on a Hitag S tag"); + PrintAndLog(" 04 (set to 0 if no authentication is needed) write page on a Hitag S tag"); + PrintAndLog(" Hitag1 (1*)"); + PrintAndLog(" Hitag2 (2*)"); + return 1; + } break; + } + // Copy the hitag function into the first argument + c.arg[0] = htf; + + // Send the command to the proxmark + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + // Check the return status, stored in the first argument + if (resp.arg[0] == false) return 1; + return 0; +} + + static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdLFHitagList, 1, " List Hitag trace history"}, - {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, - {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, - {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"list", CmdLFHitagList, 1, " List Hitag trace history"}, + {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, + {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, + {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, + {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, + {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, + {"checkChallenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, { + NULL,NULL, 0, NULL } }; int CmdLFHitag(const char *Cmd) diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 46738181..bdf18912 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -107,6 +107,12 @@ typedef struct { #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 +#define CMD_SIMULATE_HITAG_S 0x0368 +#define CMD_TEST_HITAGS_TRACES 0x0367 +#define CMD_READ_HITAG_S 0x0373 +#define CMD_WR_HITAG_S 0x0375 +#define CMD_EMU_HITAG_S 0x0376 + #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 #define CMD_SNOOP_ISO_14443B 0x0382 #define CMD_SNOOP_ISO_14443a 0x0383 diff --git a/include/hitag2.h b/include/hitag2.h index ca15d81d..284b5ecb 100644 --- a/include/hitag2.h +++ b/include/hitag2.h @@ -7,11 +7,17 @@ //----------------------------------------------------------------------------- // Hitag2 type prototyping //----------------------------------------------------------------------------- +// HitagS added +//----------------------------------------------------------------------------- #ifndef _HITAG2_H_ #define _HITAG2_H_ typedef enum { + RHTSF_CHALLENGE = 01, + RHTSF_KEY = 02, + WHTSF_CHALLENGE = 03, + WHTSF_KEY = 04, RHT2F_PASSWORD = 21, RHT2F_AUTHENTICATE = 22, RHT2F_CRYPTO = 23, @@ -24,10 +30,12 @@ typedef struct { typedef struct { byte_t NrAr[8]; + byte_t data[4]; } PACKED rht2d_authenticate; typedef struct { - byte_t key[4]; + byte_t key[6]; + byte_t data[4]; } PACKED rht2d_crypto; typedef union { diff --git a/include/hitagS.h b/include/hitagS.h new file mode 100644 index 00000000..870efb8d --- /dev/null +++ b/include/hitagS.h @@ -0,0 +1,54 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// HitagS emulation (preliminary test version) +// +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + + +#include +#include +#include +#include + +#ifndef _HITAGS_H_ +#define _HITAGS_H_ + +typedef enum PROTO_STATE {READY=0,INIT,AUTHENTICATE,SELECTED,QUIET,TTF,FAIL} PSTATE; //protocol-state +typedef enum TAG_STATE {NO_OP=0,READING_PAGE,WRITING_PAGE_ACK,WRITING_PAGE_DATA,WRITING_BLOCK_DATA} TSATE; //tag-state +typedef enum SOF_TYPE {STANDARD=0,ADVANCED,FAST_ADVANCED,ONE,NO_BITS} stype; //number of start-of-frame bits + +struct hitagS_tag { + PSTATE pstate; //protocol-state + TSATE tstate; //tag-state + uint32_t uid; + uint32_t pages[16][4]; + uint64_t key; + byte_t pwdl0,pwdl1,pwdh0; + //con0 + int max_page; + stype mode; + //con1 + bool auth; //0=Plain 1=Auth + bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase + int TTFDR; //data rate in TTF Mode + int TTFM; //the number of pages that are sent to the RWD + bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP + bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode + //con2 + //0=read write 1=read only + bool LCK7; //page4/5 + bool LCK6; //page6/7 + bool LCK5; //page8-11 + bool LCK4; //page12-15 + bool LCK3; //page16-23 + bool LCK2; //page24-31 + bool LCK1; //page32-47 + bool LCK0; //page48-63 +} ; + +#endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 38f8617a..8448b06a 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -124,6 +124,13 @@ typedef struct{ #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 +#define CMD_SIMULATE_HITAG_S 0x0368 +#define CMD_TEST_HITAGS_TRACES 0x0367 +#define CMD_READ_HITAG_S 0x0373 +#define CMD_WR_HITAG_S 0x0375 +#define CMD_EMU_HITAG_S 0x0376 + + #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 #define CMD_SNOOP_ISO_14443B 0x0382 #define CMD_SNOOP_ISO_14443a 0x0383 From a78238349cc481d241da6674801a2cb7ee58cdea Mon Sep 17 00:00:00 2001 From: Pavel Zhovner Date: Wed, 9 Mar 2016 02:41:20 +0300 Subject: [PATCH 2/7] Optional decryption of communication using keystream --- tools/mfkey/mfkey64.c | 69 +++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 15 deletions(-) diff --git a/tools/mfkey/mfkey64.c b/tools/mfkey/mfkey64.c index 448cb2ac..eeb9bb65 100755 --- a/tools/mfkey/mfkey64.c +++ b/tools/mfkey/mfkey64.c @@ -6,6 +6,7 @@ // Test-file: test2.c #include "crapto1.h" #include +#include int main (int argc, char *argv[]) { struct Crypto1State *revstate; @@ -21,32 +22,50 @@ int main (int argc, char *argv[]) { printf("MIFARE Classic key recovery - based 64 bits of keystream\n"); printf("Recover key from only one complete authentication!\n\n"); - if (argc < 6) { - printf(" syntax: %s <{nr}> <{ar}> <{at}>\n\n",argv[0]); + if (argc < 6 ) { + printf(" syntax: %s <{nr}> <{ar}> <{at}> <[enc]> [enc...]\n\n", argv[0]); return 1; } - sscanf(argv[1],"%x",&uid); - sscanf(argv[2],"%x",&nt); - sscanf(argv[3],"%x",&nr_enc); - sscanf(argv[4],"%x",&ar_enc); - sscanf(argv[5],"%x",&at_enc); + int encc = argc - 6; + int enclen[encc]; + uint8_t enc[encc][120]; + sscanf(argv[1], "%x", &uid); + sscanf(argv[2], "%x", &nt); + sscanf(argv[3], "%x", &nr_enc); + sscanf(argv[4], "%x", &ar_enc); + sscanf(argv[5], "%x", &at_enc); + for (int i = 0; i < encc; i++) { + enclen[i] = strlen(argv[i + 6]) / 2; + for (int i2 = 0; i2 < enclen[i]; i2++) { + sscanf(argv[i+6] + i2*2,"%2x", (uint8_t*)&enc[i][i2]); + } + } printf("Recovering key for:\n"); - printf(" uid: %08x\n",uid); - printf(" nt: %08x\n",nt); - printf(" {nr}: %08x\n",nr_enc); - printf(" {ar}: %08x\n",ar_enc); - printf(" {at}: %08x\n",at_enc); -/* + printf(" uid: %08x\n", uid); + printf(" nt: %08x\n", nt); + printf(" {nr}: %08x\n", nr_enc); + printf(" {ar}: %08x\n", ar_enc); + printf(" {at}: %08x\n", at_enc); + for (int i = 0; i < encc; i++) { + printf("{enc%d}: ", i); + for (int i2 = 0; i2 < enclen[i]; i2++) { + printf("%02x", enc[i][i2]); + } + printf("\n"); + } + + + /* uint32_t uid = 0x9c599b32; uint32_t tag_challenge = 0x82a4166c; uint32_t nr_enc = 0xa1e458ce; uint32_t reader_response = 0x6eea41e0; uint32_t tag_response = 0x5cadf439; */ - // Generate lfsr succesors of the tag challenge + // Generate lfsr succesors of the tag challenge printf("\nLFSR succesors of the tag challenge:\n"); printf(" nt': %08x\n",prng_successor(nt, 64)); printf(" nt'': %08x\n",prng_successor(nt, 96)); @@ -59,6 +78,26 @@ int main (int argc, char *argv[]) { printf(" ks3: %08x\n",ks3); revstate = lfsr_recovery64(ks2, ks3); + + // Decrypting communication using keystream if presented + if (argc > 6 ) { + printf("\nDecrypted communication:\n"); + uint8_t ks4; + int rollb = 0; + for (int i = 0; i < encc; i++) { + printf("{dec%d}: ", i); + for (int i2 = 0; i2 < enclen[i]; i2++) { + ks4 = crypto1_byte(revstate, 0, 0); + printf("%02x", ks4 ^ enc[i][i2]); + rollb += 1; + } + printf("\n"); + } + for (int i = 0; i < rollb; i++) { + lfsr_rollback_byte(revstate, 0, 0); + } + } + lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, nr_enc, 1); @@ -68,4 +107,4 @@ int main (int argc, char *argv[]) { crypto1_destroy(revstate); return 0; -} +} \ No newline at end of file From 8eea1dc2645de1d9067a3c17b4c2144832a95f4d Mon Sep 17 00:00:00 2001 From: Pavel Zhovner Date: Wed, 9 Mar 2016 03:32:39 +0300 Subject: [PATCH 3/7] Optional decryption of communication using keystream --- tools/mfkey/example_trace.txt | 64 ++++++++++++++++++++++++++++++++++ tools/mfkey/mfkey32 | Bin 0 -> 22044 bytes tools/mfkey/mfkey64 | Bin 0 -> 22132 bytes tools/mfkey/mfkey64.c | 4 +-- 4 files changed, 66 insertions(+), 2 deletions(-) create mode 100755 tools/mfkey/mfkey32 create mode 100755 tools/mfkey/mfkey64 diff --git a/tools/mfkey/example_trace.txt b/tools/mfkey/example_trace.txt index f2587fcd..73eb75ad 100644 --- a/tools/mfkey/example_trace.txt +++ b/tools/mfkey/example_trace.txt @@ -13,3 +13,67 @@ ./mfkey64 9c599b32 82a4166c a1e458ce 6eea41e0 5cadf439 + + +### Communication decryption + + +RDR 26 +TAG 04 00 +RDR 93 20 +TAG 14 57 9f 69 b5 +RDR 93 70 14 57 9f 69 b5 2e 51 +TAG 08 b6 dd +RDR 60 14 50 2d +TAG ce 84 42 61 +RDR f8 04 9c cb 05 25 c8 4f +TAG 94 31 cc 40 +RDR 70 93 df 99 +TAG 99 72 42 8c e2 e8 52 3f 45 6b 99 c8 31 e7 69 dc ed 09 +RDR 8c a6 82 7b +TAG ab 79 7f d3 69 e8 b9 3a 86 77 6b 40 da e3 ef 68 6e fd +RDR c3 c3 81 ba +TAG 49 e2 c9 de f4 86 8d 17 77 67 0e 58 4c 27 23 02 86 f4 +RDR fb dc d7 c1 +TAG 4a bd 96 4b 07 d3 56 3a a0 66 ed 0a 2e ac 7f 63 12 bf +RDR 9f 91 49 ea + + +./mfkey64 14579f69 ce844261 f8049ccb 0525c84f 9431cc40 7093df99 9972428ce2e8523f456b99c831e769dced09 8ca6827b ab797fd369e8b93a86776b40dae3ef686efd c3c381ba 49e2c9def4868d1777670e584c27230286f4 fbdcd7c1 4abd964b07d3563aa066ed0a2eac7f6312bf 9f9149ea + +Recovering key for: + uid: 14579f69 + nt: ce844261 + {nr}: f8049ccb + {ar}: 0525c84f + {at}: 9431cc40 +{enc0}: 7093df99 +{enc1}: 9972428ce2e8523f456b99c831e769dced09 +{enc2}: 8ca6827b +{enc3}: ab797fd369e8b93a86776b40dae3ef686efd +{enc4}: c3c381ba +{enc5}: 49e2c9def4868d1777670e584c27230286f4 +{enc6}: fbdcd7c1 +{enc7}: 4abd964b07d3563aa066ed0a2eac7f6312bf +{enc8}: 9f9149ea + +LFSR succesors of the tag challenge: + nt': 76d4468d + nt'': d5f3c476 + +Keystream used to generate {ar} and {at}: + ks2: 73f18ec2 + ks3: 41c20836 + +Decrypted communication: +{dec0}: 3014a7fe +{dec1}: c26935cfdb95c4b4a27a84b8217ae9e48217 +{dec2}: 30152eef +{dec3}: 493167c536c30f8e220b09675687067d4b31 +{dec4}: 3016b5dd +{dec5}: 493167c536c30f8e220b09675687067d4b31 +{dec6}: 30173ccc +{dec7}: 0000000000007e178869000000000000c4f2 +{dec8}: 61148834 + +Found Key: [091e639cb715] \ No newline at end of file diff --git a/tools/mfkey/mfkey32 b/tools/mfkey/mfkey32 new file mode 100755 index 0000000000000000000000000000000000000000..0f44ffab87e6f8848f540068ab7e9ae6da6488ba GIT binary patch literal 22044 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 literal 0 HcmV?d00001 diff --git a/tools/mfkey/mfkey64 b/tools/mfkey/mfkey64 new file mode 100755 index 0000000000000000000000000000000000000000..abe0b4aec22f4ee05776797c947040cd3dc8063c GIT binary patch literal 22132 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 <{nr}> <{ar}> <{at}> <[enc]> [enc...]\n\n", argv[0]); + printf(" syntax: %s <{nr}> <{ar}> <{at}> [enc] [enc...]\n\n", argv[0]); return 1; } @@ -107,4 +107,4 @@ int main (int argc, char *argv[]) { crypto1_destroy(revstate); return 0; -} \ No newline at end of file +} From c36d994b32a8bb7f39d642f770e6cfb0074cb046 Mon Sep 17 00:00:00 2001 From: Pavel Zhovner Date: Wed, 9 Mar 2016 03:52:54 +0300 Subject: [PATCH 4/7] remove binary files --- tools/mfkey/mfkey32 | Bin 22044 -> 0 bytes tools/mfkey/mfkey64 | Bin 22132 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100755 tools/mfkey/mfkey32 delete mode 100755 tools/mfkey/mfkey64 diff --git a/tools/mfkey/mfkey32 b/tools/mfkey/mfkey32 deleted file mode 100755 index 0f44ffab87e6f8848f540068ab7e9ae6da6488ba..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22044 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 diff --git a/tools/mfkey/mfkey64 b/tools/mfkey/mfkey64 deleted file mode 100755 index abe0b4aec22f4ee05776797c947040cd3dc8063c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22132 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 Date: Tue, 5 Apr 2016 08:52:53 +0200 Subject: [PATCH 5/7] Changelog modified --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3d71de5..7055d087 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac ## [unreleased][unreleased] ### Added +- Added experimental HitagS support (Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg) + see https://media.ccc.de/v/32c3-7166-sicherheit_von_125khz_transpondern_am_beispiel_hitag_s + English video available - Added a LF ASK Sequence Terminator detection option to the standard ask demod - and applied it to `lf search u`, `lf t55xx detect`, and `data rawdemod am s` (marshmellow) - `lf t55xx bruteforce [i <*.dic>]` - Simple bruteforce attack to find password - (iceman and others) - `lf viking clone`- clone viking tag to t55x7 or Q5 from 4byte hex ID input From 39d56ec88be1ee4c8d13f1a08aa40daccab273d6 Mon Sep 17 00:00:00 2001 From: Ondrej Mikle Date: Sat, 23 Apr 2016 10:01:19 +0200 Subject: [PATCH 6/7] Fix hitagS sources to compile on gcc 4.9.3 --- armsrc/hitagS.c | 1 - include/hitagS.h | 1 - 2 files changed, 2 deletions(-) diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 99565f1b..58e09a45 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -12,7 +12,6 @@ //----------------------------------------------------------------------------- -#include #include #include "proxmark3.h" #include "apps.h" diff --git a/include/hitagS.h b/include/hitagS.h index 870efb8d..351ca86c 100644 --- a/include/hitagS.h +++ b/include/hitagS.h @@ -10,7 +10,6 @@ //----------------------------------------------------------------------------- -#include #include #include #include From f9ce1c3a00739699685a94f8ced20a124d61a0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A1s=20Veres-Szentkir=C3=A1lyi?= Date: Tue, 10 May 2016 10:33:30 +0200 Subject: [PATCH 7/7] removed unused variable --- client/cmdlf.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 93a1398d..34e0c1c7 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -62,7 +62,6 @@ int CmdLFCommandRead(const char *Cmd) bool errors = FALSE; //uint8_t divisor = 95; //125khz uint8_t cmdp = 0; - int strLength = 0; while(param_getchar(Cmd, cmdp) != 0x00) { switch(param_getchar(Cmd, cmdp)) @@ -78,7 +77,7 @@ int CmdLFCommandRead(const char *Cmd) cmdp++; break; case 'c': - strLength = param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes); + param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes); cmdp+=2; break; case 'd':