X-Git-Url: http://cvs.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/219a334de5f6af339e6d9a9ca0ea215c4565e778..c9778481ffad23dd5749ae9f65d15154bc04c6e1:/armsrc/hitag2.c diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 37eb211c..bc904c66 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -21,12 +21,13 @@ #include "util.h" #include "hitag2.h" #include "string.h" +#include "BigBuf.h" static bool bQuiet; - -bool bCrypto; -bool bAuthenticating; -bool bPwd; +static bool bCrypto; +static bool bAuthenticating; +static bool bPwd; +static bool bSuccessful; struct hitag2_tag { uint32_t uid; @@ -60,21 +61,17 @@ static struct hitag2_tag tag = { }, }; -//#define TRACE_LENGTH 3000 -//uint8_t *trace = (uint8_t *) BigBuf; -//int traceLen = 0; -//int rsamples = 0; - -#define AUTH_TABLE_OFFSET FREE_BUFFER_OFFSET -#define AUTH_TABLE_LENGTH FREE_BUFFER_SIZE -byte_t* auth_table = (byte_t *)BigBuf+AUTH_TABLE_OFFSET; -size_t auth_table_pos = 0; -size_t auth_table_len = AUTH_TABLE_LENGTH; +// 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; +static size_t auth_table_pos = 0; +static size_t auth_table_len = AUTH_TABLE_LENGTH; -byte_t password[4]; -byte_t NrAr[8]; -byte_t key[8]; -uint64_t cipher_state; +static byte_t password[4]; +static byte_t NrAr[8]; +static byte_t key[8]; +static uint64_t cipher_state; /* Following is a modified version of cryptolib.com/ciphers/hitag2/ */ // Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007. @@ -97,7 +94,6 @@ uint64_t cipher_state; #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)) static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 @@ -106,7 +102,7 @@ static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 101 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 @@ -119,8 +115,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++) { @@ -132,7 +128,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) @@ -144,28 +140,31 @@ static u64 _hitag2_round (u64 *state) return _f20 (x); } +// "MIKRON" = O N M I K R +// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key +// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear +// Random = 65 6E 45 72 - Random IV, transmitted in clear +//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream + +// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6". +// The inverse of the first 4 bytes is sent to the tag to authenticate. +// The rest is encrypted by XORing it with the subsequent keystream. + 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; } -size_t nbytes(size_t nbits) { - return (nbits/8)+((nbits%8)>0); -} - -int hitag2_reset(void) -{ +static int hitag2_reset(void) { tag.state = TAG_STATE_RESET; tag.crypto_active = 0; return 0; } -int hitag2_init(void) -{ -// memcpy(&tag, &resetdata, sizeof(tag)); +static int hitag2_init(void) { hitag2_reset(); return 0; } @@ -227,16 +226,16 @@ static int hitag2_cipher_transcrypt(uint64_t* cs, byte_t *data, unsigned int byt #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_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_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 @@ -279,7 +278,8 @@ static void hitag_send_frame(const byte_t* frame, size_t frame_len) LOW(GPIO_SSC_DOUT); } -void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) + +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]; @@ -398,8 +398,8 @@ void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, si break; } -// LogTrace(rx,nbytes(rxlen),0,0,false); -// LogTrace(tx,nbytes(*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); @@ -414,7 +414,7 @@ static void hitag_reader_send_bit(int bit) { // 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 + // Enable modulation, which means, drop the field HIGH(GPIO_SSC_DOUT); // Wait for 4-10 times the carrier period @@ -427,15 +427,15 @@ static void hitag_reader_send_bit(int bit) { 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 @@ -444,7 +444,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) } // Send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Enable modulation, which means, drop the the field + // 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); @@ -454,7 +454,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) size_t blocknr; -bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { +static bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { // Reset the transmission frame length *txlen = 0; @@ -477,26 +477,26 @@ bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) *txlen = 32; memcpy(tx,password,4); bPwd = true; - memcpy(tag.sectors[blocknr],rx,4); - blocknr++; + 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!"); - // We are done... for now - return false; - } - *txlen = 10; - tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); - tx[1] = ((blocknr^7) << 6); + 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!"); + bSuccessful = true; + return false; + } + *txlen = 10; + tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); + tx[1] = ((blocknr^7) << 6); } } break; @@ -509,7 +509,7 @@ bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) return true; } -bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { +static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { // Reset the transmission frame length *txlen = 0; @@ -523,11 +523,32 @@ bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { case 0: { // Stop if there is no answer while we are in crypto mode (after sending NrAr) if (bCrypto) { - DbpString("Authentication failed!"); - return false; + // Failed during authentication + if (bAuthenticating) { + DbpString("Authentication failed!"); + return false; + } else { + // Failed reading a block, could be (read/write) locked, skip block and re-authenticate + if (blocknr == 1) { + // Write the low part of the key in memory + memcpy(tag.sectors[1],key+2,4); + } else if (blocknr == 2) { + // Write the high part of the key in memory + tag.sectors[2][0] = 0x00; + tag.sectors[2][1] = 0x00; + tag.sectors[2][2] = key[0]; + tag.sectors[2][3] = key[1]; + } else { + // Just put zero's in the memory (of the unreadable block) + memset(tag.sectors[blocknr],0x00,4); + } + blocknr++; + bCrypto = false; + } + } else { + *txlen = 5; + memcpy(tx,"\xc0",nbytes(*txlen)); } - *txlen = 5; - memcpy(tx,"\xc0",nbytes(*txlen)); } break; // Received UID, crypto tag answer @@ -541,20 +562,20 @@ bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { hitag2_cipher_transcrypt(&cipher_state,tx+4,4,0); *txlen = 64; bCrypto = true; - bAuthenticating = true; + bAuthenticating = true; } else { // Check if we received answer tag (at) if (bAuthenticating) { - bAuthenticating = false; + bAuthenticating = false; } else { - // Store the received block - memcpy(tag.sectors[blocknr],rx,4); - blocknr++; + // Store the received block + memcpy(tag.sectors[blocknr],rx,4); + blocknr++; } if (blocknr > 7) { - DbpString("Read succesful!"); - // We are done... for now - return false; + DbpString("Read succesful!"); + bSuccessful = true; + return false; } *txlen = 10; tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); @@ -570,18 +591,18 @@ bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { } - if(bCrypto) { - // We have to return now to avoid double encryption - if (!bAuthenticating) { - hitag2_cipher_transcrypt(&cipher_state,tx,*txlen/8,*txlen%8); - } + if(bCrypto) { + // We have to return now to avoid double encryption + if (!bAuthenticating) { + hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8); + } } return true; } -bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { +static bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { // Reset the transmission frame length *txlen = 0; @@ -606,8 +627,7 @@ bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txl bCrypto = true; } else { DbpString("Authentication succesful!"); - // We are done... for now - return false; + return true; } } break; @@ -621,7 +641,9 @@ bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txl return true; } -bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { + +static bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) { + // Reset the transmission frame length *txlen = 0; @@ -631,12 +653,19 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_ case 0: { // Stop if there is no answer while we are in crypto mode (after sending NrAr) if (bCrypto) { - Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); + Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); + + // Removing failed entry from authentiations table + memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8); + auth_table_len -= 8; + + // Return if we reached the end of the authentications table bCrypto = false; - if ((auth_table_pos+8) == auth_table_len) { + if (auth_table_pos == auth_table_len) { return false; } - auth_table_pos += 8; + + // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry) memcpy(NrAr,auth_table+auth_table_pos,8); } *txlen = 5; @@ -669,6 +698,43 @@ bool hitag2_test_auth_attempts(byte_t* rx, const size_t rxlen, byte_t* tx, size_ return true; } +static bool hitag2_read_uid(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 + case 0: { + // Just starting or if there is no answer + *txlen = 5; + memcpy(tx,"\xC0",nbytes(*txlen)); + } break; + // Received UID + case 32: { + // Check if we received answer tag (at) + if (bAuthenticating) { + bAuthenticating = false; + } else { + // Store the received block + memcpy(tag.sectors[blocknr],rx,4); + blocknr++; + } + if (blocknr > 0) { + //DbpString("Read successful!"); + bSuccessful = true; + return false; + } + } break; + // Unexpected response + default: { + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } + return true; +} + void SnoopHitag(uint32_t type) { int frame_count; int response; @@ -681,12 +747,19 @@ void SnoopHitag(uint32_t type) { byte_t rx[HITAG_FRAME_LEN]; size_t rxlen=0; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + // Clean up trace and prepare it for storing frames - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); - + clear_trace(); + set_tracing(TRUE); + auth_table_len = 0; auth_table_pos = 0; + + auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); DbpString("Starting Hitag2 snoop"); @@ -694,7 +767,7 @@ void SnoopHitag(uint32_t type) { // Set up eavesdropping mode, frequency divisor which will drive the FPGA // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + 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(); @@ -710,7 +783,7 @@ void SnoopHitag(uint32_t type) { 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, @@ -731,7 +804,7 @@ void SnoopHitag(uint32_t type) { bSkip = true; tag_sof = 4; - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); @@ -831,7 +904,7 @@ void SnoopHitag(uint32_t type) { // Check if frame was captured if(rxlen > 0) { frame_count++; - if (!LogTrace(rx,nbytes(rxlen),response,0,reader_frame)) { + if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) { DbpString("Trace full"); break; } @@ -873,7 +946,7 @@ void SnoopHitag(uint32_t type) { AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_A_OFF(); - + set_tracing(TRUE); // Dbprintf("frame received: %d",frame_count); // Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); // DbpString("All done"); @@ -890,11 +963,20 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { bool bQuitTraceFull = false; bQuiet = false; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + // Clean up trace and prepare it for storing frames - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); + clear_trace(); + set_tracing(TRUE); + auth_table_len = 0; auth_table_pos = 0; + byte_t* auth_table; + + auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); DbpString("Starting Hitag2 simulation"); @@ -917,7 +999,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + 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(); @@ -936,23 +1018,23 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { 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, + // 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; - // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Reset the received frame, frame count and timing info memset(rx,0x00,sizeof(rx)); frame_count = 0; response = 0; overflow = 0; + + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while(!BUTTON_PRESS()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); @@ -994,7 +1076,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { if(rxlen > 4) { frame_count++; if (!bQuiet) { - if (!LogTrace(rx,nbytes(rxlen),response,0,true)) { + if (!LogTraceHitag(rx,rxlen,response,0,true)) { DbpString("Trace full"); if (bQuitTraceFull) { break; @@ -1023,7 +1105,7 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) { hitag_send_frame(tx,txlen); // Store the frame in the trace if (!bQuiet) { - if (!LogTrace(tx,nbytes(txlen),0,0,false)) { + if (!LogTraceHitag(tx,txlen,0,0,false)) { DbpString("Trace full"); if (bQuitTraceFull) { break; @@ -1054,9 +1136,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); -// Dbprintf("frame received: %d",frame_count); -// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); -// DbpString("All done"); + + DbpString("Sim Stopped"); + set_tracing(TRUE); } void ReaderHitag(hitag_function htf, hitag_data* htd) { @@ -1074,18 +1156,23 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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 - iso14a_set_tracing(TRUE); - iso14a_clear_trace(); - DbpString("Starting Hitag reader family"); + clear_trace(); + set_tracing(TRUE); + + //DbpString("Starting Hitag reader family"); // Check configuration switch(htf) { case RHT2F_PASSWORD: { - Dbprintf("List identifier in password mode"); + Dbprintf("List identifier in password mode"); memcpy(password,htd->pwd.password,4); - blocknr = 0; + blocknr = 0; bQuitTraceFull = false; bQuiet = false; bPwd = false; @@ -1097,32 +1184,39 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { Dbhexdump(8,NrAr,false); bQuiet = false; bCrypto = false; - bAuthenticating = false; + bAuthenticating = false; bQuitTraceFull = true; } break; case RHT2F_CRYPTO: { DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key,6); + memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code. Dbhexdump(6,key,false); - blocknr = 0; + blocknr = 0; bQuiet = false; bCrypto = false; - bAuthenticating = false; + bAuthenticating = false; bQuitTraceFull = true; } break; case RHT2F_TEST_AUTH_ATTEMPTS: { Dbprintf("Testing %d authentication attempts",(auth_table_len/8)); auth_table_pos = 0; - memcpy(NrAr,auth_table,8); + memcpy(NrAr, auth_table, 8); bQuitTraceFull = false; bQuiet = false; bCrypto = false; } break; - + case RHT2F_UID_ONLY: { + blocknr = 0; + bQuiet = false; + bCrypto = false; + bAuthenticating = false; + bQuitTraceFull = true; + } break; default: { Dbprintf("Error, unknown function: %d",htf); + set_tracing(FALSE); return; } break; } @@ -1177,22 +1271,23 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // 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; - } - + Dbprintf("Error, unknown hitag reader type: %d",htf); + set_tracing(FALSE); + return; + } + uint8_t attempt_count=0; while(!bStop && !BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); @@ -1201,13 +1296,12 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { if(rxlen > 0) { frame_count++; if (!bQuiet) { - if (!LogTrace(rx,nbytes(rxlen),response,0,false)) { + if (!LogTraceHitag(rx,rxlen, response, 0, false)) { DbpString("Trace full"); - if (bQuitTraceFull) { + if (bQuitTraceFull) break; - } else { + else bQuiet = true; - } } } } @@ -1227,8 +1321,14 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { case RHT2F_TEST_AUTH_ATTEMPTS: { bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen); } break; + case RHT2F_UID_ONLY: { + bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen); + attempt_count++; //attempt 3 times to get uid then quit + if (!bStop && attempt_count == 3) bStop = true; + } break; default: { Dbprintf("Error, unknown function: %d",htf); + set_tracing(FALSE); return; } break; } @@ -1255,7 +1355,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { frame_count++; if (!bQuiet) { // Store the frame in the trace - if (!LogTrace(tx,nbytes(txlen),HITAG_T_WAIT_2,0,true)) { + if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) { if (bQuitTraceFull) { break; } else { @@ -1272,6 +1372,8 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { 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 while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) { @@ -1321,10 +1423,13 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { rxlen++; } } else { + //Dbprintf("DEBUG: Wierd2"); + errorCount++; // Ignore wierd value, is to small to mean anything } } - + //if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount >100) break; // We can break this loop if we received the last bit from a frame if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) { if (rxlen>0) break; @@ -1336,7 +1441,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - -// Dbprintf("frame received: %d",frame_count); -// DbpString("All done"); -} +// Dbprintf("DONE: frame received: %d",frame_count); + cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48); + set_tracing(FALSE); +} \ No newline at end of file