diff --git a/armsrc/apps.h b/armsrc/apps.h index 31071a8ad..62fce3931 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -222,18 +222,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 SniffHitag(uint32_t type); -void SimulateHitagTag(bool tag_mem_supplied, byte_t *data); -void ReaderHitag(hitag_function htf, hitag_data *htd); -void WriterHitag(hitag_function htf, hitag_data *htd, int page); - -//hitagS.h -void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data); -void ReadHitagS(hitag_function htf, hitag_data *htd); -void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); -void check_challenges(bool file_given, byte_t *data); - // cmd.h uint8_t cmd_receive(UsbCommand *cmd); uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 237f0820c..d474cf895 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -18,7 +18,9 @@ // Piwi, 2019 // Iceman, 2019 +#include "hitag2.h" #include "hitag2_crypto.h" +#include "hitag.h" #include "proxmark3.h" #include "apps.h" #include "util.h" @@ -1076,7 +1078,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data) { LEDsoff(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + set_tracing(false); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; @@ -1384,8 +1386,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { StopTicks(); - int frame_count; - int response; + int frame_count = 0, response = 0; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; uint8_t txbuf[HITAG_FRAME_LEN]; @@ -1440,8 +1441,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // 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); @@ -1464,17 +1463,18 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG + | AT91C_TC_LDRA_FALLING; // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV > 0); + while (AT91C_BASE_TC0->TC_CV > 0) {}; // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; lastbit = 1; bStop = false; @@ -1483,23 +1483,24 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // hitagS settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitagS reader"); + DbpString("Configured for hitagS reader"); } else if (htf < 20) { // hitag1 settings reset_sof = 1; t_wait = 200; - // DbpString("Configured for hitag1 reader"); + DbpString("Configured for hitag1 reader"); } else if (htf < 30) { // hitag2 settings reset_sof = 4; t_wait = HITAG_T_WAIT_2; - // DbpString("Configured for hitag2 reader"); + DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d", htf); return; } - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it @@ -1531,9 +1532,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); - - // Dbprintf("DEBUG: Sending reader frame"); + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1555,7 +1554,6 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { bSkip = true; tag_sof = reset_sof; response = 0; - // Dbprintf("DEBUG: Waiting to receive frame"); uint32_t errorCount = 0; // Receive frame, watch for at most T0*EOF periods @@ -1628,6 +1626,7 @@ void WriterHitag(hitag_function htf, hitag_data *htd, int page) { } // if we saw over 100 wierd values break it probably isn't hitag... if (errorCount > 100) break; + // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) break; diff --git a/armsrc/hitag2.h b/armsrc/hitag2.h new file mode 100644 index 000000000..2260e5f8d --- /dev/null +++ b/armsrc/hitag2.h @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// (c) 2012 Roel Verdult +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Hitag2 type prototyping +//----------------------------------------------------------------------------- + +#ifndef _HITAG2_H_ +#define _HITAG2_H_ + +#include +#include +#include "hitag.h" + +void SniffHitag(uint32_t type); +void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data); +void ReaderHitag(hitag_function htf, hitag_data *htd); +void WriterHitag(hitag_function htf, hitag_data *htd, int page); + +#endif diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index b53112081..404230aac 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -10,109 +10,46 @@ //----------------------------------------------------------------------------- // Some code was copied from Hitag2.c //----------------------------------------------------------------------------- -#include -#include "proxmark3.h" -#include "apps.h" -#include "util.h" + #include "hitagS.h" -#include "hitag2.h" -#include "string.h" -#include "BigBuf.h" #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) - static bool bQuiet; static bool bSuccessful; static struct hitagS_tag tag; static byte_t page_to_be_written = 0; static int block_data_left = 0; + typedef enum modulation { AC2K = 0, AC4K, MC4K, MC8K } MOD; -static MOD m = AC2K; //used modulation + +static MOD m = AC2K; // used modulation static uint32_t temp_uid; static int temp2 = 0; -static int sof_bits; //number of start-of-frame bits -static byte_t pwdh0, pwdl0, pwdl1; //password bytes -static uint32_t rnd = 0x74124485; //randomnumber +static int sof_bits; // number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; // password bytes +static uint32_t rnd = 0x74124485; // randomnumber static int test = 0; size_t blocknr; bool end = false; -// Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 #define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) #define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) #define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) -#define uf20bs u32 - -static u32 f20(const u64 x) { - u32 i5; - - i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 - + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 - + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 - + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 - + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; - - return (ht2_f5c >> i5) & 1; -} -static u64 hitag2_round(u64 *state) { - u64 x = *state; - - x = (x >> 1) - + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) - ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) - ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) - & 1) << 47); - - *state = x; - return f20(x); -} -static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; - for (i = 0; i < 32; i++) { - x >>= 1; - x += (u64)(f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; - } - return x; -} -static u32 hitag2_byte(u64 *x) { - u32 i, c; - - for (i = 0, c = 0; i < 8; i++) - c += (u32) hitag2_round(x) << (i ^ 7); - return c; -} // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 +#ifndef T0 #define T0 192 - -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#endif #define HITAG_FRAME_LEN 20 #define HITAG_T_STOP 36 /* T_EOF should be > 36 */ @@ -258,100 +195,85 @@ static void hitag_send_bit(int bit) { } } -static void hitag_send_frame(const byte_t *frame, size_t frame_len) { -// Send start of frame - +static void hitag_send_frame(const uint8_t *frame, size_t frame_len) { + // SOF - send start of frame for (size_t i = 0; i < sof_bits; i++) { hitag_send_bit(1); } -// Send the content of the frame + // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } -// Drop the modulation + LOW(GPIO_SSC_DOUT); } static void hitag_reader_send_bit(int bit) { -//Dbprintf("BIT: %d",bit); + LED_A_ON(); -// Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; -// Binary puls length modulation (BPLM) is used to encode the data stream -// This means that a transmission of a one takes longer than that of a zero + // Binary puls length modulation (BPLM) is used to encode the data stream + // This means that a transmission of a one takes longer than that of a zero -// Enable modulation, which means, drop the the field HIGH(GPIO_SSC_DOUT); + if (test == 1) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); - - // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; - - // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; - - // SpinDelayUs(22*8); } } else { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); - - // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - - // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; - - // SpinDelayUs(22*8); } } LED_A_OFF(); } -static void hitag_reader_send_frame(const byte_t *frame, size_t frame_len) { -// Send the content of the frame +static void hitag_reader_send_frame(const uint8_t *frame, size_t frame_len) { + // Send the content of the frame for (size_t i = 0; i < frame_len; i++) { - if (frame[0] == 0xf8) { +// if (frame[0] == 0xf8) { //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); - } +// } hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); } -// Send EOF + // send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; -// Enable modulation, which means, drop the the field + HIGH(GPIO_SSC_DOUT); -// Wait for 4-10 times the carrier period + + // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; -// Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); } /* * to check if the right uid was selected */ -static int check_select(byte_t *rx, uint32_t uid) { +static int check_select(uint8_t *rx, uint32_t uid) { unsigned char resp[48]; int i; uint32_t ans = 0x0; @@ -359,31 +281,32 @@ static int check_select(byte_t *rx, uint32_t uid) { resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; for (i = 0; i < 32; i++) ans += resp[5 + i] << (31 - i); - /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 - && rx[4] == 0x65 && rx[5] == 0x38) - Dbprintf("got uid %X", ans);*/ + temp_uid = ans; if (ans == tag.uid) return 1; + return 0; } /* * handles all commands from a reader */ -static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, - byte_t *tx, size_t *txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; - byte_t page; +static void hitagS_handle_reader_command(uint8_t *rx, const size_t rxlen, + uint8_t *tx, size_t *txlen) { + uint8_t rx_air[HITAG_FRAME_LEN]; + uint8_t page; int i; - u64 state; + uint64_t state; unsigned char crc; -// Copy the (original) received frame how it is send over the air + // Copy the (original) received frame how it is send over the air memcpy(rx_air, rx, nbytes(rxlen)); -// Reset the transmission frame length + + // Reset the transmission frame length *txlen = 0; -// Try to find out which command was send by selecting on length (in bits) + + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { case 5: { //UID request with a selected response protocol mode @@ -452,11 +375,13 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, Dbprintf("Challenge for UID: %X", temp_uid); temp2++; *txlen = 32; - state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), - rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); - Dbprintf( - ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", - rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + state = _hitag2_init(REV64(tag.key), + REV32(tag.pages[0][0]), + REV32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0])) + ); + Dbprintf(",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", + rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + switch (tag.mode) { case HT_STANDARD: sof_bits = 1; @@ -475,12 +400,13 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, } for (i = 0; i < 4; i++) - hitag2_byte(&state); - //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response - tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); - tx[1] = hitag2_byte(&state) ^ tag.pwdh0; - tx[2] = hitag2_byte(&state) ^ tag.pwdl0; - tx[3] = hitag2_byte(&state) ^ tag.pwdl1; + _hitag2_byte(&state); + + //send con2, pwdh0, pwdl0, pwdl1 encrypted as a response + tx[0] = _hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); + tx[1] = _hitag2_byte(&state) ^ tag.pwdh0; + tx[2] = _hitag2_byte(&state) ^ tag.pwdl0; + tx[3] = _hitag2_byte(&state) ^ tag.pwdl1; if (tag.mode != HT_STANDARD) { //add crc8 *txlen = 40; @@ -489,14 +415,12 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, calc_crc(&crc, tag.pwdh0, 8); calc_crc(&crc, tag.pwdl0, 8); calc_crc(&crc, tag.pwdl1, 8); - tx[4] = (crc ^ hitag2_byte(&state)); + tx[4] = (crc ^ _hitag2_byte(&state)); } /* * some readers do not allow to authenticate multiple times in a row with the same tag. * use this to change the uid between authentications. - */ - /* if (temp2 % 2 == 0) { tag.uid = 0x11223344; tag.pages[0][0] = 0x44332211; @@ -720,18 +644,17 @@ static void hitagS_handle_reader_command(byte_t *rx, const size_t rxlen, /* * to autenticate to a tag with the given key or challenge */ -static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, byte_t *rx, const size_t rxlen, byte_t *tx, - size_t *txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; +static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrAr, uint8_t *rx, const size_t rxlen, uint8_t *tx, size_t *txlen) { + uint8_t rx_air[HITAG_FRAME_LEN]; int response_bit[200]; int i, j, z, k; unsigned char mask = 1; unsigned char uid[32]; - byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; + uint8_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; unsigned char crc; - u64 state; - byte_t auth_ks[4]; - byte_t conf_pages[3]; + uint64_t state; + uint8_t auth_ks[4]; + uint8_t conf_pages[3]; memcpy(rx_air, rx, nbytes(rxlen)); *txlen = 0; @@ -757,16 +680,45 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA if (k > 31) break; } - uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) - | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; - uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) - | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; - uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) - | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; - uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) - | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; + uid1 = (uid[0] << 7) + | (uid[1] << 6) + | (uid[2] << 5) + | (uid[3] << 4) + | (uid[4] << 3) + | (uid[5] << 2) + | (uid[6] << 1) + | uid[7]; + + uid2 = (uid[8] << 7) + | (uid[9] << 6) + | (uid[10] << 5) + | (uid[11] << 4) + | (uid[12] << 3) + | (uid[13] << 2) + | (uid[14] << 1) + | uid[15]; + + uid3 = (uid[16] << 7) + | (uid[17] << 6) + | (uid[18] << 5) + | (uid[19] << 4) + | (uid[20] << 3) + | (uid[21] << 2) + | (uid[22] << 1) + | uid[23]; + + uid4 = (uid[24] << 7) + | (uid[25] << 6) + | (uid[26] << 5) + | (uid[27] << 4) + | (uid[28] << 3) + | (uid[29] << 2) + | (uid[30] << 1) + | uid[31]; + if (DEBUG) Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); + tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); //select uid @@ -777,29 +729,40 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA calc_crc(&crc, uid2, 8); calc_crc(&crc, uid3, 8); calc_crc(&crc, uid4, 8); + for (i = 0; i < 100; i++) { response_bit[i] = 0; } + for (i = 0; i < 5; i++) { response_bit[i] = 0; } + for (i = 5; i < 37; i++) { response_bit[i] = uid[i - 5]; } + for (j = 0; j < 8; j++) { response_bit[i] = 0; if ((crc & ((mask << 7) >> j)) != 0) response_bit[i] = 1; i++; } + k = 0; for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) | response_bit[k + 7]; + tx[i] = (response_bit[k] << 7) + | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) + | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) + | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) + | response_bit[k + 7]; + k += 8; } + tag.pstate = HT_INIT; } else if (tag.pstate == HT_INIT && rxlen == 44) { // received configuration after select command @@ -847,18 +810,17 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA tag.LCK0 = response_bit[27]; if (DEBUG) - Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], - conf_pages[1], conf_pages[2]); + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], conf_pages[1], conf_pages[2]); + if (tag.auth == 1) { //if the tag is in authentication mode try the key or challenge *txlen = 64; if (end != true) { if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY - state = hitag2_init(rev64(key), rev32(tag.uid), - rev32(rnd)); + state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); for (i = 0; i < 4; i++) { - auth_ks[i] = hitag2_byte(&state) ^ 0xff; + auth_ks[i] = _hitag2_byte(&state) ^ 0xff; } *txlen = 64; tx[0] = rnd & 0xff; @@ -906,21 +868,18 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA pwdl1 = 0; if (htf == 02 || htf == 04) { //RHTS_KEY //WHTS_KEY { - state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); + state = _hitag2_init(REV64(key), REV32(tag.uid), REV32(rnd)); for (i = 0; i < 5; i++) - hitag2_byte(&state); - pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) - ^ hitag2_byte(&state); + _hitag2_byte(&state); + + pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) ^ _hitag2_byte(&state); + pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) ^ _hitag2_byte(&state); + pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) ^ _hitag2_byte(&state); } if (DEBUG) Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); - //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); //rnd += 1; } @@ -933,18 +892,22 @@ static int hitagS_handle_tag_auth(hitag_function htf, uint64_t key, uint64_t NrA /* * Emulates a Hitag S Tag with the given data from the .hts file */ -void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { - int frame_count; - int response; - int overflow; +void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data) { + + StopTicks(); + + int frame_count = 0, response = 0, overflow = 0; int i, j; - byte_t rx[HITAG_FRAME_LEN]; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - //bool bQuitTraceFull = false; bQuiet = false; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; + + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); @@ -958,16 +921,18 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { tag.pstate = HT_READY; tag.tstate = HT_NO_OP; + for (i = 0; i < 16; i++) for (j = 0; j < 4; j++) tag.pages[i][j] = 0x0; - //read tag data into memory + + // read tag data into memory if (tag_mem_supplied) { DbpString("Loading hitagS memory..."); - memcpy((byte_t *)tag.pages, data, 4 * 64); + memcpy((uint8_t *)tag.pages, data, 4 * 64); } + tag.uid = (uint32_t)tag.pages[0]; - Dbprintf("Hitag S simulation started"); tag.key = (intptr_t)tag.pages[3]; tag.key <<= 16; tag.key += ((tag.pages[2][0]) << 8) + tag.pages[2][1]; @@ -1017,48 +982,48 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { if ((tag.pages[1][1] & 0x1) == 0x01) tag.LCK0 = 1; -// Set up simulator mode, frequency divisor which will drive the FPGA -// and analog mux selection. + // Set up simulator mode, frequency divisor which will drive the FPGA + // and analog mux selection. FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(20); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Configure output pin that is connected to the FPGA (for modulating) + // Configure output pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Disable modulation at default, which means release resistance + // Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - -// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on rising edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; -// Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; - -// Enable and reset counter + // Enable and reset counter + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (!BUTTON_PRESS()) { - // Watchdog hit + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero + + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Receive frame, watch for at most T0*EOF periods @@ -1098,12 +1063,7 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // Check if frame was captured if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, true)) { - DbpString("Trace full"); - clear_trace(); - } - } + LogTraceHitag(rx, rxlen, response, 0, true); // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; @@ -1116,20 +1076,13 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) // periods. The gap time T_Low varies (4..10). All timer values are in // terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) {}; // Send and store the tag answer (if there is any) if (txlen > 0) { // Transmit the tag frame hitag_send_frame(tx, txlen); - // Store the frame in the trace - if (!bQuiet) { - if (!LogTraceHitag(tx, txlen, 0, 0, false)) { - DbpString("Trace full"); - clear_trace(); - } - } + LogTraceHitag(tx, txlen, 0, 0, false); } // Reset the received frame and response timing info @@ -1147,11 +1100,19 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { // Reset the timer to restart while-loop that receives frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; } - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + // release allocated memory from BigBuff. + BigBuf_free(); + + StartTicks(); + + DbpString("Sim Stopped"); } /* @@ -1160,22 +1121,23 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t *data) { * Reads every page of a hitag S transpoder. */ void ReadHitagS(hitag_function htf, hitag_data *htd) { + + StopTicks(); + int i, j, z, k; - int frame_count; + int frame_count = 0, response = 0; int response_bit[200]; - int response; - byte_t rx[HITAG_FRAME_LEN]; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; - int lastbit; + int lastbit = 1; bool bSkip; - int reset_sof; + int reset_sof = 1; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; - bool bQuitTraceFull = false; int sendNum = 0; unsigned char mask = 1; unsigned char crc; @@ -1183,31 +1145,31 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { page_to_be_written = 0; //read given key/challenge - byte_t NrAr_[8]; + uint8_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - byte_t key_[6]; + uint8_t key_[6]; + switch (htf) { - case 01: { //RHTS_CHALLENGE + case RHTSF_CHALLENGE: { DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + break; } - break; - case 02: { //RHTS_KEY + case RHTSF_KEY: { DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + break; } - break; default: { Dbprintf("Error , unknown function: %d", htf); return; } - break; } FpgaDownloadAndGo(FPGA_BITSTREAM_LF); @@ -1219,40 +1181,36 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { clear_trace(); bQuiet = false; - bQuitTraceFull = true; LED_D_ON(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - - // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); - + + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER |= GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER |= GPIO_SSC_DOUT; + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | @@ -1264,32 +1222,20 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero + // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; - - reset_sof = 1; t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(rx, rxlen, response, 0, false); } // By default reset the transmission buffer @@ -1299,13 +1245,14 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { if (rxlen == 0) { //start authentication txlen = 5; - memcpy(tx, "\xc0", nbytes(txlen)); + memcpy(tx, "\xC0", nbytes(txlen)); tag.pstate = HT_READY; tag.tstate = HT_NO_OP; } else if (tag.pstate != HT_SELECTED) { if (hitagS_handle_tag_auth(htf, key, NrAr, rx, rxlen, tx, &txlen) == -1) bStop = !false; } + if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { //send read request tag.tstate = HT_READING_PAGE; @@ -1316,8 +1263,9 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE - && rxlen > 0) { + } else if (tag.pstate == HT_SELECTED + && tag.tstate == HT_READING_PAGE + && rxlen > 0) { //save received data z = 0; for (i = 0; i < 5; i++) { @@ -1361,15 +1309,19 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { sendNum++; //display key and password if possible if (sendNum == 2 && tag.auth == 1 && tag.LKP) { - if (htf == 02) { //RHTS_KEY + if (htf == RHTSF_KEY) { Dbprintf("Page[ 2]: %02X %02X %02X %02X", - (byte_t)(key >> 8) & 0xff, - (byte_t) key & 0xff, pwdl1, pwdl0); + (uint8_t)(key >> 8) & 0xff, + (uint8_t) key & 0xff, + pwdl1, + pwdl0 + ); Dbprintf("Page[ 3]: %02X %02X %02X %02X", - (byte_t)(key >> 40) & 0xff, - (byte_t)(key >> 32) & 0xff, - (byte_t)(key >> 24) & 0xff, - (byte_t)(key >> 16) & 0xff); + (uint8_t)(key >> 40) & 0xff, + (uint8_t)(key >> 32) & 0xff, + (uint8_t)(key >> 24) & 0xff, + (uint8_t)(key >> 16) & 0xff + ); } else { //if the authentication is done with a challenge the key and password are unknown Dbprintf("Page[ 2]: __ __ __ __"); @@ -1410,17 +1362,7 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); } // Reset values for receiving frames @@ -1491,12 +1433,17 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { } } end = false; - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1505,12 +1452,14 @@ void ReadHitagS(hitag_function htf, hitag_data *htd) { * Writes the given 32Bit data into page_ */ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; + + StopTicks(); + + int frame_count = 0, response = 0; + uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1518,124 +1467,106 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; - bool bQuitTraceFull = false; int page = page_; unsigned char crc; - byte_t data[4] = {0, 0, 0, 0}; + uint8_t data[4] = {0, 0, 0, 0}; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + bSuccessful = false; + + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); + //read given key/challenge, the page and the data - byte_t NrAr_[8]; + uint8_t NrAr_[8]; uint64_t key = 0; uint64_t NrAr = 0; - byte_t key_[6]; + uint8_t key_[6]; switch (htf) { - case 03: { //WHTS_CHALLENGE + case WHTSF_CHALLENGE: { memcpy(data, htd->auth.data, 4); DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr_, htd->auth.NrAr, 8); Dbhexdump(8, NrAr_, false); NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | ((uint64_t)NrAr_[2]) << 40 | ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + break; } - break; - case 04: { //WHTS_KEY + + case WHTSF_KEY: { memcpy(data, htd->crypto.data, 4); DbpString("Authenticating using key:"); memcpy(key_, htd->crypto.key, 6); Dbhexdump(6, key_, false); key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + break; } - break; default: { Dbprintf("Error , unknown function: %d", htf); return; } - break; } Dbprintf("Page: %d", page_); Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status - bSuccessful = false; tag.pstate = HT_READY; tag.tstate = HT_NO_OP; -// Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); - - bQuiet = false; - bQuitTraceFull = true; - LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - -// Set Frequency divisor which will drive the FPGA and analog mux selection + // Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); - -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - 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); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; -// Enable and reset counters + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; -// Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; + while (AT91C_BASE_TC0->TC_CV > 0); + + // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit + while (!bStop && !BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(rx, rxlen, response, 0, false); } //check for valid input @@ -1711,9 +1642,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1724,17 +1653,7 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); } // Reset values for receiving frames @@ -1744,7 +1663,8 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { bSkip = true; tag_sof = reset_sof; response = 0; - + uint32_t errorCount = 0; + // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { // Check if falling edge in tag modulation is detected @@ -1794,9 +1714,13 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } else { // Ignore wierd value, is to small to mean anything + errorCount++; } } - + + // if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount > 100) break; + // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { if (rxlen > 0) @@ -1805,11 +1729,15 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { } } end = false; - LED_B_OFF(); - LED_D_OFF(); + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1820,17 +1748,16 @@ void WritePageHitagS(hitag_function htf, hitag_data *htd, int page_) { * is not received correctly due to Antenna problems. This function * detects these challenges. */ -void check_challenges(bool file_given, byte_t *data) { +void check_challenges(bool file_given, uint8_t *data) { int i, j, z, k; - byte_t uid_byte[4]; - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; - byte_t unlocker[60][8]; + uint8_t uid_byte[4]; + int frame_count = 0, response = 0; + uint8_t rx[HITAG_FRAME_LEN]; + uint8_t unlocker[60][8]; int u1 = 0; size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t *tx = txbuf; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t *tx = txbuf; size_t txlen = 0; int lastbit; bool bSkip; @@ -1839,76 +1766,71 @@ void check_challenges(bool file_given, byte_t *data) { int t_wait = HITAG_T_WAIT_MAX; int STATE = 0; bool bStop; - bool bQuitTraceFull = false; int response_bit[200]; unsigned char mask = 1; unsigned char uid[32]; unsigned char crc; FpgaDownloadAndGo(FPGA_BITSTREAM_LF); -// Reset the return status + // Reset the return status bSuccessful = false; -// Clean up trace and prepare it for storing frames + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); bQuiet = false; - bQuitTraceFull = true; LED_D_ON(); -// Configure output and enable pin that is connected to the FPGA (for modulating) + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; -// Set fpga in edge detect with reader field, we can modulate as reader now + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - SpinDelay(50); - -// Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); -// Disable modulation at default, which means enable the field + // Disable modulation at default, which means enable the field LOW(GPIO_SSC_DOUT); -// Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Enable Peripheral Clock for + // TIMER_CLOCK0, used to measure exact timing before answering + // TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); -// Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - -// Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; -// Disable timer during configuration + // Disable timer during configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; -// Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, -// external trigger rising edge, load RA on falling edge of TIOA. + // TC0: Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), no triggers + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK; + + // TC1: Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_FALLING + | AT91C_TC_ABETRG + | AT91C_TC_LDRA_FALLING; - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - -// Enable and reset counters + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; -// Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; + while (AT91C_BASE_TC0->TC_CV > 0) {}; + + // Reset the received frame, frame count and timing info lastbit = 1; bStop = false; - reset_sof = 1; t_wait = 200; if (file_given) { DbpString("Loading challenges..."); - memcpy((byte_t *)unlocker, data, 60 * 8); + memcpy((uint8_t *)unlocker, data, 60 * 8); } while (file_given && !bStop && !BUTTON_PRESS()) { @@ -1918,16 +1840,7 @@ void check_challenges(bool file_given, byte_t *data) { // Check if frame was captured and store it if (rxlen > 0) { frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(rx, rxlen, response, 0, false); } tx = txbuf; @@ -1943,7 +1856,7 @@ void check_challenges(bool file_given, byte_t *data) { STATE = 0; txlen = 5; //start new authentication - memcpy(tx, "\xc0", nbytes(txlen)); + memcpy(tx, "\xC0", nbytes(txlen)); } else if (rxlen >= 67 && STATE == 0) { //received uid z = 0; @@ -2043,9 +1956,7 @@ void check_challenges(bool file_given, byte_t *data) { // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -2056,17 +1967,7 @@ void check_challenges(bool file_given, byte_t *data) { // Add transmitted frame to total count if (txlen > 0) { frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } + LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true); } // Reset values for receiving frames @@ -2136,11 +2037,16 @@ void check_challenges(bool file_given, byte_t *data) { } } } - LED_B_OFF(); - LED_D_OFF(); + + LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + StartTicks(); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } diff --git a/armsrc/hitagS.h b/armsrc/hitagS.h new file mode 100644 index 000000000..49a885c4c --- /dev/null +++ b/armsrc/hitagS.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// HitagS emulation (preliminary test version) +// +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + +#ifndef _HITAGS_H_ +#define _HITAGS_H_ + +#include +#include +#include +#include "hitag2_crypto.h" +#include "hitag.h" +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" +#include "BigBuf.h" + +void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data); +void ReadHitagS(hitag_function htf, hitag_data *htd); +void WritePageHitagS(hitag_function htf, hitag_data *htd, int page); +void check_challenges(bool file_given, uint8_t *data); + +#endif diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 53d4d5036..9bbe167ee 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -17,8 +17,7 @@ #include "common.h" #include "util.h" #include "parity.h" -#include "hitag2.h" -#include "hitagS.h" +#include "hitag.h" #include "util_posix.h" #include "comms.h" #include "cmddata.h" diff --git a/include/hitag.h b/include/hitag.h new file mode 100644 index 000000000..209556b65 --- /dev/null +++ b/include/hitag.h @@ -0,0 +1,117 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Hitag2, HitagS +// +// (c) 2012 Roel Verdult +// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg +// +//----------------------------------------------------------------------------- + + +#ifndef HITAG_H__ +#define HITAG_H__ + +#ifdef _MSC_VER +#define PACKED +#else +#define PACKED __attribute__((packed)) +#endif + +typedef enum { + RHTSF_CHALLENGE = 01, + RHTSF_KEY = 02, + WHTSF_CHALLENGE = 03, + WHTSF_KEY = 04, + RHT2F_PASSWORD = 21, + RHT2F_AUTHENTICATE = 22, + RHT2F_CRYPTO = 23, + WHT2F_CRYPTO = 24, + RHT2F_TEST_AUTH_ATTEMPTS = 25, + RHT2F_UID_ONLY = 26, +} hitag_function; + +typedef struct { + uint8_t password[4]; +} PACKED rht2d_password; + +typedef struct { + uint8_t NrAr[8]; + uint8_t data[4]; +} PACKED rht2d_authenticate; + +typedef struct { + uint8_t key[6]; + uint8_t data[4]; +} PACKED rht2d_crypto; + +typedef union { + rht2d_password pwd; + rht2d_authenticate auth; + rht2d_crypto crypto; +} hitag_data; + + +//--------------------------------------------------------- +// Hitag S +//--------------------------------------------------------- +// protocol-state +typedef enum PROTO_STATE { + HT_READY = 0, + HT_INIT, + HT_AUTHENTICATE, + HT_SELECTED, + HT_QUIET, + HT_TTF, + HT_FAIL +} PSTATE; + +typedef enum TAG_STATE { + HT_NO_OP = 0, + HT_READING_PAGE, + HT_WRITING_PAGE_ACK, + HT_WRITING_PAGE_DATA, + HT_WRITING_BLOCK_DATA +} TSATE; + +//number of start-of-frame bits +typedef enum SOF_TYPE { + HT_STANDARD = 0, + HT_ADVANCED, + HT_FAST_ADVANCED, + HT_ONE, + HT_NO_BITS +} stype; + +struct hitagS_tag { + PSTATE pstate; //protocol-state + TSATE tstate; //tag-state + uint32_t uid; + uint8_t pages[64][4]; + uint64_t key; + uint8_t pwdl0, pwdl1, pwdh0; + //con0 + int max_page; + stype mode; + //con1 + bool auth; //0=Plain 1=Auth + bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase + int TTFDR; //data rate in TTF Mode + int TTFM; //the number of pages that are sent to the RWD + bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP + bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode + //con2 + //0=read write 1=read only + bool LCK7; //page4/5 + bool LCK6; //page6/7 + bool LCK5; //page8-11 + bool LCK4; //page12-15 + bool LCK3; //page16-23 + bool LCK2; //page24-31 + bool LCK1; //page32-47 + bool LCK0; //page48-63 +}; + +#endif diff --git a/include/hitag2.h b/include/hitag2.h deleted file mode 100644 index 96cfb7abb..000000000 --- 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 a2f67e464..000000000 --- a/include/hitagS.h +++ /dev/null @@ -1,77 +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 -// -//----------------------------------------------------------------------------- - -#include -#include -#include - -#ifndef _HITAGS_H_ -#define _HITAGS_H_ - -//protocol-state -typedef enum PROTO_STATE { - HT_READY = 0, - HT_INIT, - HT_AUTHENTICATE, - HT_SELECTED, - HT_QUIET, - HT_TTF, - HT_FAIL -} PSTATE; - -//tag-state -typedef enum TAG_STATE { - HT_NO_OP = 0, - HT_READING_PAGE, - HT_WRITING_PAGE_ACK, - HT_WRITING_PAGE_DATA, - HT_WRITING_BLOCK_DATA -} TSATE; - -//number of start-of-frame bits -typedef enum SOF_TYPE { - HT_STANDARD = 0, - HT_ADVANCED, - HT_FAST_ADVANCED, - HT_ONE, - HT_NO_BITS -} stype; - -struct hitagS_tag { - PSTATE pstate; //protocol-state - TSATE tstate; //tag-state - uint32_t uid; - 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