From: pwpiwi Date: Wed, 13 Mar 2019 09:53:40 +0000 (+0100) Subject: fix hitag functions (issue #798) (#800) X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/commitdiff_plain/5866c187ef916dd683eacbe4698914c6a1394589?ds=sidebyside;hp=1523527f94c4c294d0c04d0fd3396ce7eda095e4 fix hitag functions (issue #798) (#800) * ... and whitespace formating --- diff --git a/armsrc/apps.h b/armsrc/apps.h index aaa128ab..5b8516eb 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -161,18 +161,6 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); -// hitag2.h -void SnoopHitag(uint32_t type); -void SimulateHitagTag(bool tag_mem_supplied, byte_t* data); -void ReaderHitag(hitag_function htf, hitag_data* htd); -void WriterHitag(hitag_function htf, hitag_data* htd, int page); - -//hitagS.h -void ReadHitagSCmd(hitag_function htf, hitag_data* htd, uint64_t startPage, uint64_t tagMode, bool readBlock); -void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data); -void WritePageHitagS(hitag_function htf, hitag_data* htd,int page); -void check_challenges_cmd(bool file_given, byte_t* data, uint64_t tagMode); - // 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 0fd8d745..270958ce 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -16,10 +16,12 @@ // (c) 2012 Roel Verdult //----------------------------------------------------------------------------- +#include "hitag2.h" + #include "proxmark3.h" #include "apps.h" #include "util.h" -#include "hitag2.h" +#include "hitag.h" #include "string.h" #include "BigBuf.h" #include "fpgaloader.h" @@ -48,21 +50,21 @@ struct hitag2_tag { }; static struct hitag2_tag tag = { - .state = TAG_STATE_RESET, - .sectors = { // Password mode: | Crypto mode: - [0] = { 0x02, 0x4e, 0x02, 0x20}, // UID | UID - [1] = { 0x4d, 0x49, 0x4b, 0x52}, // Password RWD | 32 bit LSB key - [2] = { 0x20, 0xf0, 0x4f, 0x4e}, // Reserved | 16 bit MSB key, 16 bit reserved - [3] = { 0x0e, 0xaa, 0x48, 0x54}, // Configuration, password TAG | Configuration, password TAG - [4] = { 0x46, 0x5f, 0x4f, 0x4b}, // Data: F_OK - [5] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU - [6] = { 0xaa, 0xaa, 0xaa, 0xaa}, // Data: .... - [7] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU - [8] = { 0x00, 0x00, 0x00, 0x00}, // RSK Low - [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High - [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF - [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC - }, + .state = TAG_STATE_RESET, + .sectors = { // Password mode: | Crypto mode: + [0] = { 0x02, 0x4e, 0x02, 0x20}, // UID | UID + [1] = { 0x4d, 0x49, 0x4b, 0x52}, // Password RWD | 32 bit LSB key + [2] = { 0x20, 0xf0, 0x4f, 0x4e}, // Reserved | 16 bit MSB key, 16 bit reserved + [3] = { 0x0e, 0xaa, 0x48, 0x54}, // Configuration, password TAG | Configuration, password TAG + [4] = { 0x46, 0x5f, 0x4f, 0x4b}, // Data: F_OK + [5] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU + [6] = { 0xaa, 0xaa, 0xaa, 0xaa}, // Data: .... + [7] = { 0x55, 0x55, 0x55, 0x55}, // Data: UUUU + [8] = { 0x00, 0x00, 0x00, 0x00}, // RSK Low + [9] = { 0x00, 0x00, 0x00, 0x00}, // RSK High + [10] = { 0x00, 0x00, 0x00, 0x00}, // RCF + [11] = { 0x00, 0x00, 0x00, 0x00}, // SYNC + }, }; static enum { @@ -70,9 +72,9 @@ static enum { WRITE_STATE_PAGENUM_WRITTEN, WRITE_STATE_PROG } writestate; - -// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. + +// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. // Historically it used to be FREE_BUFFER_SIZE, which was 2744. #define AUTH_TABLE_LENGTH 2744 static byte_t* auth_table; @@ -93,30 +95,30 @@ static uint64_t cipher_state; // Basic macros: -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) // Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 static u32 _f20 (const u64 x) { - u32 i5; - + 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 @@ -128,8 +130,8 @@ static u32 _f20 (const u64 x) static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; for (i = 0; i < 32; i++) { @@ -141,7 +143,7 @@ static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV) static u64 _hitag2_round (u64 *state) { - u64 x = *state; + u64 x = *state; x = (x >> 1) + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) @@ -155,7 +157,7 @@ static u64 _hitag2_round (u64 *state) static u32 _hitag2_byte (u64 * x) { - u32 i, c; + u32 i, c; for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7); return c; @@ -170,7 +172,7 @@ static int hitag2_reset(void) static int hitag2_init(void) { -// memcpy(&tag, &resetdata, sizeof(tag)); +// memcpy(&tag, &resetdata, sizeof(tag)); hitag2_reset(); return 0; } @@ -218,40 +220,40 @@ static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int byt // T0 = TIMER_CLOCK1 / 125000 = 192 #define T0 192 -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#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_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_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_PROG 614 -#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_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_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 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 static void hitag_send_bit(int bit) { LED_A_ON(); - // Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + // Fixed modulation, earlier proxmark version used inverted signal if(bit == 0) { // Manchester: Unloaded, then loaded |__--| @@ -289,20 +291,20 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len) static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { byte_t rx_air[HITAG_FRAME_LEN]; - + // Copy the (original) received frame how it is send over the air memcpy(rx_air,rx,nbytes(rxlen)); if(tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8); } - - // Reset the transmission frame length + + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { - // Received 11000 from the reader, request for UID, send UID + // Received 11000 from the reader, request for UID, send UID case 05: { // Always send over the air in the clear plaintext mode if(rx_air[0] != 0xC0) { @@ -315,7 +317,7 @@ static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* } break; - // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number + // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number case 10: { unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07); // Verify complement of sector index @@ -330,7 +332,7 @@ static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* memcpy(tx,tag.sectors[sector],4); *txlen = 32; break; - + // Inverted Read command: 01xx x10y case 0x44: for (size_t i=0; i<4; i++) { @@ -347,7 +349,7 @@ static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tag.active_sector = sector; tag.state=TAG_STATE_WRITING; break; - + // Unknown command default: Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]); @@ -405,9 +407,9 @@ static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* break; } -// LogTraceHitag(rx,rxlen,0,0,false); -// LogTraceHitag(tx,*txlen,0,0,true); - +// LogTraceHitag(rx,rxlen,0,0,false); +// LogTraceHitag(tx,*txlen,0,0,true); + if(tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8); } @@ -415,30 +417,30 @@ static void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* static void hitag_reader_send_bit(int bit) { LED_A_ON(); - // Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + // Binary puls length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero - + // Enable modulation, which means, drop the field HIGH(GPIO_SSC_DOUT); - + // Wait for 4-10 times the carrier period while(AT91C_BASE_TC0->TC_CV < T0*6); - // SpinDelayUs(8*8); - + // 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); + // SpinDelayUs(16*8); } else { // One bit: |_--| while(AT91C_BASE_TC0->TC_CV < T0*28); - // SpinDelayUs(22*8); + // SpinDelayUs(22*8); } LED_A_OFF(); } @@ -450,7 +452,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) for(size_t i=0; i> (7-(i%8)))&1); } - // Send EOF + // Send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Enable modulation, which means, drop the field HIGH(GPIO_SSC_DOUT); @@ -465,7 +467,7 @@ size_t blocknr; static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -478,7 +480,7 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* *txlen = 5; memcpy(tx,"\xc0",nbytes(*txlen)); } break; - + // Received UID, tag password case 32: { if (!bPwd) { @@ -488,14 +490,14 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* memcpy(tag.sectors[blocknr],rx,4); blocknr++; } else { - + if(blocknr == 1){ //store password in block1, the TAG answers with Block3, but we need the password in memory memcpy(tag.sectors[blocknr],tx,4); }else{ memcpy(tag.sectors[blocknr],rx,4); } - + blocknr++; if (blocknr > 7) { DbpString("Read succesful!"); @@ -507,7 +509,7 @@ static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx[1] = ((blocknr^7) << 6); } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d",rxlen); @@ -529,8 +531,8 @@ static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t case WRITE_STATE_PAGENUM_WRITTEN: // Check if page number was received correctly if ((rxlen == 10) && - (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) && - (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) { + (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) && + (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) { *txlen = 32; memset(tx, 0, HITAG_FRAME_LEN); memcpy(tx, writedata, 4); @@ -562,7 +564,7 @@ static bool hitag2_write_page(byte_t* rx, const size_t rxlen, byte_t* tx, size_t static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen, bool write) { // Reset the transmission frame length *txlen = 0; - + if(bCrypto) { hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8); @@ -651,7 +653,7 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx } } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d",rxlen); @@ -659,7 +661,7 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx } break; } } - + if(bCrypto) { // We have to return now to avoid double encryption if (!bAuthenticating) { @@ -672,9 +674,9 @@ static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* tx static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { - // Reset the transmission frame length + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -687,7 +689,7 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size *txlen = 5; memcpy(tx,"\xc0",nbytes(*txlen)); } break; - + // Received UID, crypto tag answer case 32: { if (!bCrypto) { @@ -700,23 +702,23 @@ static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size return false; } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d",rxlen); return false; } break; } - + return true; } static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { - // Reset the transmission frame length + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -740,8 +742,8 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx } *txlen = 5; memcpy(tx,"\xc0",nbytes(*txlen)); - } break; - + } break; + // Received UID, crypto tag answer, or read block response case 32: { if (!bCrypto) { @@ -758,13 +760,13 @@ static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx memcpy(NrAr,auth_table+auth_table_pos,8); } } break; - + default: { Dbprintf("Uknown frame length: %d",rxlen); return false; } break; } - + return true; } @@ -816,13 +818,13 @@ void SnoopHitag(uint32_t type) { int tag_sof; byte_t rx[HITAG_FRAME_LEN] = {0}; size_t rxlen=0; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); - + auth_table_len = 0; auth_table_pos = 0; @@ -832,36 +834,36 @@ void SnoopHitag(uint32_t type) { DbpString("Starting Hitag2 snoop"); LED_D_ON(); - + // Set up eavesdropping mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); - + // Configure output pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Disable modulation, we are going to eavesdrop, not modulate ;) LOW(GPIO_SSC_DOUT); - + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration + + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; AT91C_BASE_TC1->TC_CMR = t1_channel_mode; - + // Enable and reset counter 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; @@ -870,18 +872,18 @@ void SnoopHitag(uint32_t type) { lastbit = 1; bSkip = true; tag_sof = 4; - + 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 + // Retrieve the new timing values int ra = (AT91C_BASE_TC1->TC_RA/T0); - + // Find out if we are dealing with a rising or falling edge rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; @@ -893,17 +895,17 @@ void SnoopHitag(uint32_t type) { 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 @@ -914,11 +916,11 @@ void SnoopHitag(uint32_t type) { // 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 + // '1' bit rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; } else if(ra >= HITAG_T_0_MIN) { - // '0' bit + // '0' bit rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; } else { @@ -944,7 +946,7 @@ void SnoopHitag(uint32_t type) { // 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 + // 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++; @@ -967,7 +969,7 @@ void SnoopHitag(uint32_t type) { } } } - + // Check if frame was captured if(rxlen > 0) { frame_count++; @@ -984,7 +986,7 @@ void SnoopHitag(uint32_t type) { auth_table_len += 8; } } - + // Reset the received frame and response timing info memset(rx,0x00,sizeof(rx)); response = 0; @@ -993,7 +995,7 @@ void SnoopHitag(uint32_t type) { bSkip = true; tag_sof = 4; overflow = 0; - + LED_B_OFF(); LED_C_OFF(); } else { @@ -1013,10 +1015,10 @@ void SnoopHitag(uint32_t type) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_A_OFF(); - -// Dbprintf("frame received: %d",frame_count); -// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); -// DbpString("All done"); + +// Dbprintf("frame received: %d",frame_count); +// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); +// DbpString("All done"); } void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { @@ -1029,7 +1031,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { size_t txlen=0; bool bQuitTraceFull = false; bQuiet = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Clean up trace and prepare it for storing frames @@ -1046,7 +1048,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { DbpString("Starting Hitag2 simulation"); LED_D_ON(); hitag2_init(); - + if (tag_mem_supplied) { DbpString("Loading hitag2 memory..."); memcpy((byte_t*)tag.sectors,data,48); @@ -1060,7 +1062,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { } Dbprintf("| %d | %08x |",i,block); } - + // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); @@ -1074,21 +1076,25 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // 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 + + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - + // Reset the received frame, frame count and timing info memset(rx,0x00,sizeof(rx)); frame_count = 0; @@ -1097,24 +1103,24 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // 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 + // 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) { @@ -1123,11 +1129,11 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // 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 + // '1' bit rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; } else if(ra >= HITAG_T_0_MIN) { - // '0' bit + // '0' bit rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; } else { @@ -1135,7 +1141,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { } } } - + // Check if frame was captured if(rxlen > 4) { frame_count++; @@ -1149,17 +1155,17 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { } } } - + // 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) hitag2_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 + // 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)); @@ -1179,11 +1185,11 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { } } } - + // 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(); @@ -1200,9 +1206,9 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + DbpString("Sim Stopped"); - + } void ReaderHitag(hitag_function htf, hitag_data* htd) { @@ -1215,16 +1221,16 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { size_t txlen=0; int lastbit; bool bSkip; - int reset_sof; + int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; bool bQuitTraceFull = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status bSuccessful = false; - + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -1250,10 +1256,10 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { bAuthenticating = false; bQuitTraceFull = true; } break; - case RHT2F_CRYPTO: + case RHT2F_CRYPTO: { DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key,6); //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; @@ -1281,14 +1287,14 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { return; } break; } - + 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); @@ -1302,21 +1308,25 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // 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 + + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - + // 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; @@ -1350,7 +1360,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { while(!bStop && !BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); - + // Check if frame was captured and store it if(rxlen > 0) { frame_count++; @@ -1365,7 +1375,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { } } } - + // By default reset the transmission buffer tx = txbuf; switch(htf) { @@ -1404,7 +1414,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); //Dbprintf("DEBUG: Sending reader frame"); - + // Transmit the reader frame hitag_reader_send_frame(tx,txlen); @@ -1440,14 +1450,14 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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 + // 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) { @@ -1461,7 +1471,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { //need to test to verify we don't exceed memory... //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; + // break; //} rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; @@ -1469,14 +1479,14 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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; + // 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 + // 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++; @@ -1488,7 +1498,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { //need to test to verify we don't exceed memory... //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; + // break; //} if (tag_sof) { // Ignore bits that are transmitted during SOF @@ -1513,7 +1523,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { } } //Dbprintf("DEBUG: Done waiting for frame"); - + LED_B_OFF(); LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1538,16 +1548,16 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { size_t txlen=0; int lastbit; bool bSkip; - int reset_sof; + int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; bool bQuitTraceFull = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status bSuccessful = false; - + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -1559,7 +1569,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { case WHT2F_CRYPTO: { DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key,6); //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. memcpy(writedata, htd->crypto.data, 4); Dbhexdump(6,key,false); blocknr = page; @@ -1574,14 +1584,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { return; } break; } - + 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); @@ -1595,21 +1605,25 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { // 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 + + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - + // 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; @@ -1643,7 +1657,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { while(!bStop && !BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); - + // Check if frame was captured and store it if(rxlen > 0) { frame_count++; @@ -1658,7 +1672,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { } } } - + // By default reset the transmission buffer tx = txbuf; switch(htf) { @@ -1670,24 +1684,24 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { return; } 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 occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); - + //Dbprintf("DEBUG: Sending reader frame"); - + // Transmit the reader frame hitag_reader_send_frame(tx,txlen); - // Enable and reset external trigger in timer for capturing future frames + // 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 @@ -1719,14 +1733,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { 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 + // 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) { @@ -1740,7 +1754,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { //need to test to verify we don't exceed memory... //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; + // break; //} rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; @@ -1748,14 +1762,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { 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; + // 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 + // 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++; @@ -1767,7 +1781,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { //need to test to verify we don't exceed memory... //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; + // break; //} if (tag_sof) { // Ignore bits that are transmitted during SOF @@ -1790,7 +1804,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { if (rxlen>0) break; } } - + // Wait some extra time for flash to be programmed if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) { @@ -1799,7 +1813,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { } } //Dbprintf("DEBUG: Done waiting for frame"); - + LED_B_OFF(); LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h new file mode 100644 index 00000000..555f04ee --- /dev/null +++ b/armsrc/hitag2.h @@ -0,0 +1,24 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Hitag2 emulation +// +// (c) 2009 Henryk Plötz +// (c) 2012 Roel Verdult +//----------------------------------------------------------------------------- + +#ifndef HITAG2_H__ +#define HITAG2_H__ + +#include +#include +#include "hitag.h" + +void SnoopHitag(uint32_t type); +void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data); +void ReaderHitag(hitag_function htf, hitag_data* htd); +void WriterHitag(hitag_function htf, hitag_data* htd, int page); + +#endif diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 8a451606..9e8f1432 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -12,12 +12,13 @@ //----------------------------------------------------------------------------- +#include "hitagS.h" + #include #include "proxmark3.h" #include "apps.h" #include "util.h" -#include "hitagS.h" -#include "hitag2.h" +#include "hitag.h" #include "string.h" #include "BigBuf.h" #include "fpgaloader.h" @@ -25,17 +26,17 @@ #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))) +#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; @@ -45,25 +46,25 @@ static int block_data_left = 0; typedef enum modulation { AC2K = 0, AC4K, MC4K, MC8K } MOD; -static MOD m = AC2K; //used modulation +static MOD m = AC2K; //used modulation static uint32_t temp_uid; static int temp2 = 0; -static int sof_bits; //number of start-of-frame bits -static byte_t pwdh0, pwdl0, pwdl1; //password bytes -static uint32_t rnd = 0x74124485; //randomnumber +static int sof_bits; //number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; //password bytes +static uint32_t rnd = 0x74124485; //randomnumber static int test = 0; size_t blocknr; bool end=false; // Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 -#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) -#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) -#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) -#define uf20bs u32 +#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; @@ -109,34 +110,34 @@ static u32 hitag2_byte(u64 *x) { // 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 T0 192 -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#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_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 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 @@ -290,7 +291,7 @@ static void hitag_reader_send_bit(int bit) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) ; - // SpinDelayUs(8*8); + // SpinDelayUs(8*8); // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); @@ -299,18 +300,18 @@ static void hitag_reader_send_bit(int bit) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 11) ; - // SpinDelayUs(16*8); + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 14) ; - // SpinDelayUs(22*8); + // SpinDelayUs(22*8); } } else { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) ; - // SpinDelayUs(8*8); + // SpinDelayUs(8*8); // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); @@ -319,12 +320,12 @@ static void hitag_reader_send_bit(int bit) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 22) ; - // SpinDelayUs(16*8); + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 28) ; - // SpinDelayUs(22*8); + // SpinDelayUs(22*8); } } @@ -403,11 +404,11 @@ static void hitag_decode_frame_MC(int bitRate, int sofBits, byte_t* rx, size_t* } else { // Ignore wierd value, is to small to mean anything } - } + } *rxlenOrg = rxlen; } -/* +/* static void hitag_decode_frame_AC2K_rising(byte_t* rx, size_t* rxlenOrg, int* response, int rawMod[], int rawLen) { int tag_sof = 1; //skip start of frame size_t rxlen = 0; @@ -461,7 +462,7 @@ static void hitag_decode_frame_AC(int bitRate, int sofBits, byte_t* rx, size_t* if (bitRate == 4) { timing = 2; } - + for (int i=0; i < rawLen; i++) { int ra = rawMod[i]; @@ -534,11 +535,11 @@ static void hitag_receive_frame(byte_t* rx, size_t* rxlen, int* response) { break; case ADVANCED: m = AC2K; - sofBits = 5; //3 sof bits but 5 captures + sofBits = 5; //3 sof bits but 5 captures break; case FAST_ADVANCED: m = AC4K; - sofBits = 5; //3 sof bits but 5 captures + sofBits = 5; //3 sof bits but 5 captures break; default: break; @@ -561,7 +562,7 @@ static void hitag_receive_frame(byte_t* rx, size_t* rxlen, int* response) { break; } } - + //rising AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; @@ -596,7 +597,7 @@ static void hitag_receive_frame(byte_t* rx, size_t* rxlen, int* response) { if (DEBUG >= 2) { for (i=0; i < rawLen; i+=20) { - Dbprintf("raw modulation: - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", + Dbprintf("raw modulation: - %d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", rawMod[i],rawMod[i+1],rawMod[i+2],rawMod[i+3], rawMod[i+4],rawMod[i+5],rawMod[i+6],rawMod[i+7], rawMod[i+8],rawMod[i+9],rawMod[i+10],rawMod[i+11], rawMod[i+12],rawMod[i+13],rawMod[i+14],rawMod[i+15], rawMod[i+16],rawMod[i+17],rawMod[i+18],rawMod[i+19] @@ -608,8 +609,8 @@ static void hitag_receive_frame(byte_t* rx, size_t* rxlen, int* response) { // DATA | 1 | 0 | 1 | 1 | 0 | // Manchester |--__|__--|--__|--__|__--| // Anti Collision |-_-_|--__|-_-_|-_-_|--__| - // |<-->| - // | T | + // |<-->| + // | T | case AC2K: if (DEBUG >= 2) { Dbprintf("decoding frame with modulation AC2K"); } hitag_decode_frame_AC(2, sofBits, rx, rxlen, response, rawMod, rawLen); @@ -683,7 +684,7 @@ static int hitag_read_page(hitag_function htf, uint64_t key, byte_t* rx, size_t* calc_crc(&crc, tx[0], 8); calc_crc(&crc, 0x00 + ((pageNum % 16) * 16), 4); tx[1] = 0x00 + ((pageNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; + tx[2] = 0x00 + (crc % 16) * 16; } else if (tag.pstate == SELECTED && tag.tstate == READING_PAGE && *rxlen > 0) { //save received data z = 0; @@ -704,9 +705,9 @@ static int hitag_read_page(hitag_function htf, uint64_t key, byte_t* rx, size_t* tag.pages[pageNum][i] = 0x0; } for (i = 0; i < 4; i++) { - tag.pages[pageNum][i] += ((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) | + tag.pages[pageNum][i] += ((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)]); } @@ -715,11 +716,11 @@ static int hitag_read_page(hitag_function htf, uint64_t key, byte_t* rx, size_t* tag.pages[pageNum][2], tag.pages[pageNum][1], tag.pages[pageNum][0]); } else { Dbprintf("Page[%2d]: %02X %02X %02X %02X", pageNum, - tag.pages[pageNum][3], tag.pages[pageNum][2], + tag.pages[pageNum][3], tag.pages[pageNum][2], tag.pages[pageNum][1], tag.pages[pageNum][0]); } - + //display key and password if possible if (pageNum == 1 && tag.auth == 1 && tag.LKP) { if (htf == 02) { //RHTS_KEY @@ -771,7 +772,7 @@ static int hitag_read_block(hitag_function htf, uint64_t key, byte_t* rx, size_t calc_crc(&crc, tx[0], 8); calc_crc(&crc, 0x00 + ((blockNum % 16) * 16), 4); tx[1] = 0x00 + ((blockNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; + tx[2] = 0x00 + (crc % 16) * 16; } else if (tag.pstate == SELECTED && tag.tstate == READING_BLOCK && *rxlen > 0) { //save received data z = 0; @@ -796,16 +797,16 @@ static int hitag_read_block(hitag_function htf, uint64_t key, byte_t* rx, size_t for (z = 0; z < 4; z++) { //4 pages for (i = 0; i < 4; i++) { j = (i * 8) + (z*32); //bit in page + pageStart - tag.pages[blockNum+z][i] = ((blockData[j] << 7) | (blockData[1 + j] << 6) | - (blockData[2 + j] << 5) | (blockData[3 + j] << 4) | - (blockData[4 + j] << 3) | (blockData[5 + j] << 2) | + tag.pages[blockNum+z][i] = ((blockData[j] << 7) | (blockData[1 + j] << 6) | + (blockData[2 + j] << 5) | (blockData[3 + j] << 4) | + (blockData[4 + j] << 3) | (blockData[5 + j] << 2) | (blockData[6 + j] << 1) | blockData[7 + j]); } } if (DEBUG) { - for (z = 0; z < 4; z++) { + for (z = 0; z < 4; z++) { Dbprintf("Page[%2d]: %02X %02X %02X %02X", blockNum+z, - tag.pages[blockNum+z][3], tag.pages[blockNum+z][2], + tag.pages[blockNum+z][3], tag.pages[blockNum+z][2], tag.pages[blockNum+z][1], tag.pages[blockNum+z][0]); } } @@ -1055,7 +1056,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen, tx[1] = tag.pages[page][1]; tx[2] = tag.pages[page][2]; tx[3] = tag.pages[page][3]; - + if (tag.LKP && page == 1) tx[3] = 0xff; @@ -1206,7 +1207,7 @@ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen, /* * to autenticate to a tag with the given key or challenge */ -static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, +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] = {0}; @@ -1222,8 +1223,8 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr *txlen = 0; if (DEBUG) { - Dbprintf("START hitagS_handle_tag_auth - rxlen: %d, tagstate=%d", rxlen, (int)tag.pstate); - } + Dbprintf("START hitagS_handle_tag_auth - rxlen: %d, tagstate=%d", rxlen, (int)tag.pstate); + } if (tag.pstate == READY && rxlen >= 32) { //received uid @@ -1243,7 +1244,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr for (i = 0; i < 32; i++) { uid[i] = response_bit[i]; } - + 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) @@ -1251,7 +1252,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr 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]; + | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); @@ -1269,7 +1270,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr response_bit[i] = 0; } - //skip the first 5 + //skip the first 5 for (i = 5; i < 37; i++) { response_bit[i] = uid[i - 5]; } @@ -1322,7 +1323,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr //tag.TTFM in response_bit[12] and response_bit[13] tag.LCON = response_bit[14]; tag.LKP = response_bit[15]; - + //CON2 tag.LCK7 = response_bit[16]; tag.LCK6 = response_bit[17]; @@ -1357,9 +1358,9 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); /* - Dbprintf("key: %02X %02X\n\n", key, rev64(key)); - Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, rev32(tag.uid)); - Dbprintf("rnd: %02X %02X\n\n", rnd, rev32(rnd)); + Dbprintf("key: %02X %02X\n\n", key, rev64(key)); + Dbprintf("tag.uid: %02X %02X\n\n", tag.uid, rev32(tag.uid)); + Dbprintf("rnd: %02X %02X\n\n", rnd, rev32(rnd)); */ for (i = 0; i < 4; i++) { auth_ks[i] = hitag2_byte(&state) ^ 0xff; @@ -1390,7 +1391,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr } else if (tag.auth == 0) { tag.pstate = SELECTED; } - + } else if (tag.pstate == AUTHENTICATE && rxlen >= 32) { //encrypted con2,password received. if (DEBUG) { @@ -1418,8 +1419,8 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr } if (DEBUG) { - Dbprintf("END hitagS_handle_tag_auth - tagstate=%d", (int)tag.pstate); - } + Dbprintf("END hitagS_handle_tag_auth - tagstate=%d", (int)tag.pstate); + } return 0; } @@ -1459,7 +1460,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { } } - for (i = 0; i < 64; i++) { + for (i = 0; i < 64; i++) { for (j = 0; j < 4; j++) { tag.pages[i][j] = data[(i*4)+j]; } @@ -1491,7 +1492,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { //tag.TTFM in response_bit[12] and response_bit[13] tag.LCON = ((con1 & 0x2) == 0x2) ? 1 : 0; tag.LKP = ((con1 & 0x1) == 0x1) ? 1 : 0; - + //CON2 tag.LCK7 = ((con2 & 0x80) == 0x80) ? 1 : 0; tag.LCK6 = ((con2 & 0x40) == 0x40) ? 1 : 0; @@ -1535,9 +1536,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; @@ -1677,7 +1682,7 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st bool bQuitTraceFull = false; page_to_be_written = 0; - + //read given key/challenge byte_t NrAr_[8]; uint64_t key=0; @@ -1690,12 +1695,12 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st 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; + ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; } break; case 02: case 04: { //RHTS_KEY DbpString("Authenticating using key:"); - memcpy(key_,htd->crypto.key,6); + 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; @@ -1708,10 +1713,10 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status + // Reset the return status bSuccessful = false; -// Clean up trace and prepare it for storing frames + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -1719,43 +1724,47 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); -// Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. + // 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 + // 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 + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, 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 + // 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 + // Reset the received frame, frame count and timing info frame_count = 0; response = 0; lastbit = 1; @@ -1808,8 +1817,8 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st txlen = 0; if (DEBUG >= 2) { - Dbprintf("FRO %d rxlen: %d, pstate=%d, tstate=%d", frame_count, rxlen, (int)tag.pstate, (int)tag.tstate); - } + Dbprintf("FRO %d rxlen: %d, pstate=%d, tstate=%d", frame_count, rxlen, (int)tag.pstate, (int)tag.tstate); + } if (rxlen == 0) { //start authentication @@ -1822,7 +1831,7 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st } - + if (readBlock && tag.pstate == SELECTED && (tag.tstate == READING_BLOCK || tag.tstate == NO_OP) && rxlen > 0) { i = hitag_read_block(htf, key, rx, &rxlen, tx, &txlen, sendNum); if (i > 0) { sendNum+=4; } @@ -1863,8 +1872,8 @@ void ReadHitagSintern(hitag_function htf, hitag_data* htd, stype tagMode, int st lastbit = 1; response = 0; - // get tag id in anti-collision mode (proprietary data format, so switch off manchester and read at double the data rate, for 4 x the data bits) - hitag_receive_frame(rx, &rxlen, &response); + // get tag id in anti-collision mode (proprietary data format, so switch off manchester and read at double the data rate, for 4 x the data bits) + hitag_receive_frame(rx, &rxlen, &response); } end=false; LED_B_OFF(); @@ -1885,7 +1894,7 @@ void ReadHitagSCmd(hitag_function htf, hitag_data* htd, uint64_t startPage, uint } else { Dbprintf("ReadHitagS in mode=STANDARD, blockRead=%d, startPage=%d", readBlock, startPage); ReadHitagSintern(htf, htd, STANDARD, (int)startPage, readBlock); - } + } } @@ -1909,7 +1918,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { 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; @@ -1922,12 +1931,12 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { 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; + ((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); + 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; @@ -1940,13 +1949,13 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { 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 + // Reset the return status bSuccessful = false; tag.pstate = READY; tag.tstate = NO_OP; -// Clean up trace and prepare it for storing frames + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -1954,45 +1963,49 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); -// Set Frequency divisor which will drive the FPGA and analog mux selection + // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. + // 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 + // 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 + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, 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 + // 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 + // Reset the received frame, frame count and timing info frame_count = 0; response = 0; lastbit = 1; @@ -2181,10 +2194,10 @@ void check_challenges_cmd(bool file_given, byte_t* data, uint64_t tagMode) { FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status + // Reset the return status bSuccessful = false; -// Clean up trace and prepare it for storing frames + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -2192,44 +2205,48 @@ void check_challenges_cmd(bool file_given, byte_t* data, uint64_t tagMode) { LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord( FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); -// Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. + // 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 + // 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 + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, 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 + // 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 + // Reset the received frame, frame count and timing info frame_count = 0; response = 0; lastbit = 1; diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h new file mode 100644 index 00000000..8451b2cf --- /dev/null +++ b/armsrc/hitagS.h @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// 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 +//----------------------------------------------------------------------------- + +#ifndef HITAGS_H__ +#define HITAGS_H__ + +#include +#include +#include "hitag.h" + +void ReadHitagSCmd(hitag_function htf, hitag_data* htd, uint64_t startPage, uint64_t tagMode, bool readBlock); +void SimulateHitagSTag(bool tag_mem_supplied, uint8_t* data); +void WritePageHitagS(hitag_function htf, hitag_data* htd, int page); +void check_challenges_cmd(bool file_given, uint8_t* data, uint64_t tagMode); + +#endif \ No newline at end of file diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 84fb5458..cd23f88c 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -19,8 +19,7 @@ #include "common.h" #include "util.h" #include "parity.h" -#include "hitag2.h" -#include "hitagS.h" +#include "hitag.h" #include "cmdmain.h" static int CmdHelp(const char *Cmd); diff --git a/include/hitag.h b/include/hitag.h new file mode 100644 index 00000000..35660dcb --- /dev/null +++ b/include/hitag.h @@ -0,0 +1,93 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Hitag2, HitagS +// +// (c) 2012 Roel Verdult +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + + +#ifndef HITAG_H__ +#define HITAG_H__ + +#ifdef _MSC_VER +#define PACKED +#else +#define PACKED __attribute__((packed)) +#endif + +typedef enum { + RHTSF_CHALLENGE = 01, + RHTSF_KEY = 02, + WHTSF_CHALLENGE = 03, + WHTSF_KEY = 04, + RHT2F_PASSWORD = 21, + RHT2F_AUTHENTICATE = 22, + RHT2F_CRYPTO = 23, + WHT2F_CRYPTO = 24, + RHT2F_TEST_AUTH_ATTEMPTS = 25, + RHT2F_UID_ONLY = 26, +} hitag_function; + +typedef struct { + uint8_t password[4]; +} PACKED rht2d_password; + +typedef struct { + uint8_t NrAr[8]; + uint8_t data[4]; +} PACKED rht2d_authenticate; + +typedef struct { + uint8_t key[6]; + uint8_t data[4]; +} PACKED rht2d_crypto; + +typedef union { + rht2d_password pwd; + rht2d_authenticate auth; + rht2d_crypto crypto; +} hitag_data; + + +//--------------------------------------------------------- +// Hitag S +//--------------------------------------------------------- +typedef enum PROTO_STATE {READY=0,INIT,AUTHENTICATE,SELECTED,QUIET,TTF,FAIL} PSTATE; //protocol-state +typedef enum TAG_STATE {NO_OP=0,READING_PAGE,READING_BLOCK,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; + uint8_t pages[64][4]; + uint64_t key; + uint8_t pwdl0, pwdl1, pwdh0; + //con0 + int max_page; + stype mode; + //con1 + bool auth; //0=Plain 1=Auth + bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase + int TTFDR; //data rate in TTF Mode + int TTFM; //the number of pages that are sent to the RWD + bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP + bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode + //con2 + //0=read write 1=read only + bool LCK7; //page4/5 + bool LCK6; //page6/7 + bool LCK5; //page8-11 + bool LCK4; //page12-15 + bool LCK3; //page16-23 + bool LCK2; //page24-31 + bool LCK1; //page32-47 + bool LCK0; //page48-63 +} ; + +#endif diff --git a/include/hitag2.h b/include/hitag2.h deleted file mode 100644 index 2406c649..00000000 --- a/include/hitag2.h +++ /dev/null @@ -1,55 +0,0 @@ -//----------------------------------------------------------------------------- -// (c) 2012 Roel Verdult -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Hitag2 type prototyping -//----------------------------------------------------------------------------- -// HitagS added -//----------------------------------------------------------------------------- - -#ifndef _HITAG2_H_ -#define _HITAG2_H_ - -#ifdef _MSC_VER -#define PACKED -#else -#define PACKED __attribute__((packed)) -#endif - -typedef enum { - RHTSF_CHALLENGE = 01, - RHTSF_KEY = 02, - WHTSF_CHALLENGE = 03, - WHTSF_KEY = 04, - RHT2F_PASSWORD = 21, - RHT2F_AUTHENTICATE = 22, - RHT2F_CRYPTO = 23, - WHT2F_CRYPTO = 24, - RHT2F_TEST_AUTH_ATTEMPTS = 25, - RHT2F_UID_ONLY = 26, -} hitag_function; - -typedef struct { - byte_t password[4]; -} PACKED rht2d_password; - -typedef struct { - byte_t NrAr[8]; - byte_t data[4]; -} PACKED rht2d_authenticate; - -typedef struct { - byte_t key[6]; - byte_t data[4]; -} PACKED rht2d_crypto; - -typedef union { - rht2d_password pwd; - rht2d_authenticate auth; - rht2d_crypto crypto; -} hitag_data; - -#endif diff --git a/include/hitagS.h b/include/hitagS.h deleted file mode 100644 index 6fd31841..00000000 --- a/include/hitagS.h +++ /dev/null @@ -1,51 +0,0 @@ -//----------------------------------------------------------------------------- -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// HitagS emulation (preliminary test version) -// -// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg -// -//----------------------------------------------------------------------------- - - -#ifndef _HITAGS_H_ -#define _HITAGS_H_ - -#include "hitag2.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,READING_BLOCK,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; - uint8_t pages[64][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