]> cvs.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/hitag2.c
Add EM410x bruteforcing error checks
[proxmark3-svn] / armsrc / hitag2.c
index 90a95b5a2643fb3c2e243f270a93971182c324dd..dd0211da98785ce6dbbf381193ae4371eb4c8714 100644 (file)
 #include "util.h"
 #include "hitag2.h"
 #include "string.h"
+#include "BigBuf.h"
 
 static bool bQuiet;
 
-bool bCrypto;
-bool bPwd;
+static bool bCrypto;
+static bool bAuthenticating;
+static bool bPwd;
+static bool bSuccessful;
+
+
 
 struct hitag2_tag {
        uint32_t uid;
@@ -41,8 +46,7 @@ struct hitag2_tag {
        byte_t sectors[12][4];
 };
 
-static struct hitag2_tag tag;
-static const struct hitag2_tag resetdata = {
+static struct hitag2_tag tag = {
     .state = TAG_STATE_RESET,
     .sectors = {                         // Password mode:               | Crypto mode:
         [0]  = { 0x02, 0x4e, 0x02, 0x20}, // UID                          | UID
@@ -60,19 +64,17 @@ static const struct hitag2_tag resetdata = {
     },
 };
 
-//#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];
+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.
@@ -150,36 +152,32 @@ static u32 _hitag2_byte (u64 * x)
        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)
+static int hitag2_init(void)
 {
-       memcpy(&tag, &resetdata, sizeof(tag));
+//     memcpy(&tag, &resetdata, sizeof(tag));
        hitag2_reset();
        return 0;
 }
 
 static void hitag2_cipher_reset(struct hitag2_tag *tag, const byte_t *iv)
 {
-       uint64_t key = ((uint64_t)tag->sectors[2][2]) |
-                       ((uint64_t)tag->sectors[2][3] << 8) |
-                       ((uint64_t)tag->sectors[1][0] << 16) |
-                       ((uint64_t)tag->sectors[1][1] << 24) |
-                       ((uint64_t)tag->sectors[1][2] << 32) |
-                       ((uint64_t)tag->sectors[1][3] << 40);
-       uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
-                       ((uint32_t)tag->sectors[0][1] << 8) |
-                       ((uint32_t)tag->sectors[0][2] << 16) |
-                       ((uint32_t)tag->sectors[0][3] << 24);
+       uint64_t key =  ((uint64_t)tag->sectors[2][2]) |
+                  ((uint64_t)tag->sectors[2][3] << 8) |
+                  ((uint64_t)tag->sectors[1][0] << 16) |
+                  ((uint64_t)tag->sectors[1][1] << 24) |
+                  ((uint64_t)tag->sectors[1][2] << 32) |
+                  ((uint64_t)tag->sectors[1][3] << 40);
+       uint32_t uid =  ((uint32_t)tag->sectors[0][0]) |
+                  ((uint32_t)tag->sectors[0][1] << 8) |
+                  ((uint32_t)tag->sectors[0][2] << 16) |
+                  ((uint32_t)tag->sectors[0][3] << 24);
        uint32_t iv_ = (((uint32_t)(iv[0]))) |
                        (((uint32_t)(iv[1])) << 8) |
                        (((uint32_t)(iv[2])) << 16) |
@@ -277,7 +275,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];
        
@@ -341,7 +340,7 @@ void hitag2_handle_reader_command(byte_t* rx, const size_t rxlen, byte_t* tx, si
                                
                                // Unknown command
                                default:
-                                       Dbprintf("Uknown command: %02x %02x",rx[0],rx[1]);
+                                       Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]);
                                        return;
                                break;
                        }
@@ -396,8 +395,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);
@@ -412,7 +411,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
@@ -434,6 +433,7 @@ static void hitag_reader_send_bit(int bit) {
        LED_A_OFF();
 }
 
+
 static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len)
 {
        // Send the content of the frame
@@ -442,7 +442,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);
@@ -452,7 +452,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;
        
@@ -475,29 +475,132 @@ 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++;
                        } 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!");
+        bSuccessful = true;
+                         return false;
+                       }
+                       *txlen = 10;
+                       tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
+                       tx[1] = ((blocknr^7) << 6);
+                       }
+               } break;
+                       
+               // Unexpected response
+    default: {
+                       Dbprintf("Uknown frame length: %d",rxlen);
+                       return false;
+               } break;
+       }
+       return true;
+}
+
+static bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
+       // Reset the transmission frame length
+       *txlen = 0;
+       
+  if(bCrypto) {
+               hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8);
+       }
+
+       // Try to find out which command was send by selecting on length (in bits)
+       switch (rxlen) {
+      // No answer, try to resurrect
+               case 0: {
+                       // Stop if there is no answer while we are in crypto mode (after sending NrAr)
+                       if (bCrypto) {
+        // 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));
+      }
+               } break;
+                       
+      // Received UID, crypto tag answer
+               case 32: {
+                       if (!bCrypto) {
+        uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40;
+        uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24;
+        cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0);
+        memset(tx,0x00,4);
+        memset(tx+4,0xff,4);
+        hitag2_cipher_transcrypt(&cipher_state,tx+4,4,0);
+                               *txlen = 64;
+                               bCrypto = true;
+        bAuthenticating = true;
+                       } else {
+        // 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 > 7) {
           DbpString("Read succesful!");
-          // We are done... for now
+          bSuccessful = true;
           return false;
         }
         *txlen = 10;
         tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2);
         tx[1] = ((blocknr^7) << 6);
-        blocknr++;
                        }
                } break;
                        
-               // Unexpected response
-        default: {
+      // Unexpected response
+               default: {
                        Dbprintf("Uknown frame length: %d",rxlen);
                        return false;
                } break;
        }
+       
+  
+  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;
        
@@ -521,7 +624,7 @@ bool hitag2_authenticate(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txl
                                memcpy(tx,NrAr,8);
                                bCrypto = true;
                        } else {
-                               DbpString("Read succesful!");
+                               DbpString("Authentication succesful!");
                                // We are done... for now
                                return false;
                        }
@@ -537,7 +640,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;
        
@@ -547,12 +652,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;
@@ -585,6 +697,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;
@@ -597,20 +746,25 @@ void SnoopHitag(uint32_t type) {
        byte_t rx[HITAG_FRAME_LEN];
        size_t rxlen=0;
        
-       // Clean up trace and prepare it for storing frames
-       iso14a_set_tracing(TRUE);
-       iso14a_clear_trace();
+       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;
+
+       BigBuf_free();
+    auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
        memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
-       
+
        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);
+       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();
@@ -626,7 +780,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,
@@ -747,7 +901,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;
                        }
@@ -806,11 +960,17 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
        bool bQuitTraceFull = false;
        bQuiet = false;
        
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+
        // Clean up trace and prepare it for storing frames
-    iso14a_set_tracing(TRUE);
-    iso14a_clear_trace();
+       set_tracing(TRUE);
+       clear_trace();
+
        auth_table_len = 0;
        auth_table_pos = 0;
+    byte_t* auth_table;
+       BigBuf_free();
+    auth_table = (byte_t *)BigBuf_malloc(AUTH_TABLE_LENGTH);
        memset(auth_table, 0x00, AUTH_TABLE_LENGTH);
 
        DbpString("Starting Hitag2 simulation");
@@ -855,18 +1015,18 @@ void SimulateHitagTag(bool tag_mem_supplied, byte_t* data) {
   // 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()) {
                // Watchdog hit
@@ -910,7 +1070,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;
@@ -939,7 +1099,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;
@@ -970,9 +1130,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");
+       
 }
 
 void ReaderHitag(hitag_function htf, hitag_data* htd) {
@@ -990,41 +1150,61 @@ 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");
+       set_tracing(TRUE);
+       clear_trace();
+
+       //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;
                } break;
                case RHT2F_AUTHENTICATE: {
-                       DbpString("Authenticating in crypto mode");
+                       DbpString("Authenticating using nr,ar pair:");
                        memcpy(NrAr,htd->auth.NrAr,8);
-                       Dbprintf("Reader-challenge:");
                        Dbhexdump(8,NrAr,false);
                        bQuiet = false;
                        bCrypto = false;
+                       bAuthenticating = false;
+                       bQuitTraceFull = true;
+               } break;
+               case RHT2F_CRYPTO: {
+                       DbpString("Authenticating using key:");
+                       memcpy(key,htd->crypto.key,6);    //HACK; 4 or 6??  I read both in the code.
+                       Dbhexdump(6,key,false);
+                       blocknr = 0;
+                       bQuiet = false;
+                       bCrypto = 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);
                        return;
@@ -1076,27 +1256,27 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
        lastbit = 1;
        bStop = false;
 
-       // Tag specific configuration settings (sof, timings, etc.)
-       if (htf < 10){
-               // hitagS settings
-               reset_sof = 1;
-               t_wait = 200;
-               DbpString("Configured for hitagS reader");
-       } else if (htf < 20) {
-               // hitag1 settings
-               reset_sof = 1;
-               t_wait = 200;
-               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");
+  // Tag specific configuration settings (sof, timings, etc.)
+  if (htf < 10){
+    // hitagS settings
+    reset_sof = 1;
+    t_wait = 200;
+    //DbpString("Configured for hitagS reader");
+  } else if (htf < 20) {
+    // hitag1 settings
+    reset_sof = 1;
+    t_wait = 200;
+    //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");
        } else {
-        Dbprintf("Error, unknown hitag reader type: %d",htf);
-        return;
-    }
-               
+    Dbprintf("Error, unknown hitag reader type: %d",htf);
+    return;
+  }
+       uint8_t attempt_count=0;
        while(!bStop && !BUTTON_PRESS()) {
                // Watchdog hit
                WDT_HIT();
@@ -1105,7 +1285,7 @@ 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) {
                                                break;
@@ -1125,9 +1305,17 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                        case RHT2F_AUTHENTICATE: {
                                bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen);
                        } break;
+                       case RHT2F_CRYPTO: {
+                               bStop = !hitag2_crypto(rx,rxlen,tx,&txlen);
+                       } break;
                        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);
                                return;
@@ -1144,6 +1332,8 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                // 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);
@@ -1156,7 +1346,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 {
@@ -1173,7 +1363,9 @@ 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) {
                        // Check if falling edge in tag modulation is detected
@@ -1189,19 +1381,29 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                                // Capture tag frame (manchester decoding using only falling edges)
                                if(ra >= HITAG_T_EOF) {
                                        if (rxlen != 0) {
-                                               //DbpString("wierd1?");
+                                               //Dbprintf("DEBUG: Wierd1");
                                        }
                                        // Capture the T0 periods that have passed since last communication or field drop (reset)
                                        // We always recieve a 'one' first, which has the falling edge after a half period |-_|
                                        response = ra-HITAG_T_TAG_HALF_PERIOD;
                                } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) {
                                        // Manchester coding example |-_|_-|-_| (101)
+
+                                       //need to test to verify we don't exceed memory...
+                                       //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+                                       //      break;
+                                       //}
                                        rx[rxlen / 8] |= 0 << (7-(rxlen%8));
                                        rxlen++;
                                        rx[rxlen / 8] |= 1 << (7-(rxlen%8));
                                        rxlen++;
                                } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) {
                                        // Manchester coding example |_-|...|_-|-_| (0...01)
+                                       
+                                       //need to test to verify we don't exceed memory...
+                                       //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+                                       //      break;
+                                       //}
                                        rx[rxlen / 8] |= 0 << (7-(rxlen%8));
                                        rxlen++;
                                        // We have to skip this half period at start and add the 'one' the second time 
@@ -1213,6 +1415,11 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
                                        bSkip = !bSkip;
                                } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) {
                                        // Manchester coding example |_-|_-| (00) or |-_|-_| (11)
+
+                                       //need to test to verify we don't exceed memory...
+                                       //if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) {
+                                       //      break;
+                                       //}
                                        if (tag_sof) {
                                                // Ignore bits that are transmitted during SOF
                                                tag_sof--;
@@ -1222,22 +1429,27 @@ 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;
                        }
                }
        }
+       //Dbprintf("DEBUG: Done waiting for frame");
+       
        LED_B_OFF();
        LED_D_OFF();
        AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
        AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
        FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
-       
-//     Dbprintf("frame received: %d",frame_count);
-//     DbpString("All done");
+       //Dbprintf("frame received: %d",frame_count);
+       //DbpString("All done");
+       cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
 }
Impressum, Datenschutz