]> git.zerfleddert.de Git - proxmark3-svn/blobdiff - armsrc/hitag2.c
hf mf dump error handling, revive hf mf chk d option, provide known keys dictionary...
[proxmark3-svn] / armsrc / hitag2.c
index 59f29eae42f20299aa3bd101a3f7e39f81fdbe7a..9181a62ea1b9b2722f6348cff98d6bbe13e53c3e 100644 (file)
@@ -27,6 +27,31 @@ static bool bQuiet;
 bool bCrypto;
 bool bAuthenticating;
 bool bPwd;
+bool bSuccessful;
+
+int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader)
+{
+  // Return when trace is full
+  if (traceLen >= TRACE_SIZE) return FALSE;
+  
+  // Trace the random, i'm curious
+  rsamples += iSamples;
+  trace[traceLen++] = ((rsamples >> 0) & 0xff);
+  trace[traceLen++] = ((rsamples >> 8) & 0xff);
+  trace[traceLen++] = ((rsamples >> 16) & 0xff);
+  trace[traceLen++] = ((rsamples >> 24) & 0xff);
+  if (!bReader) {
+    trace[traceLen - 1] |= 0x80;
+  }
+  trace[traceLen++] = ((dwParity >> 0) & 0xff);
+  trace[traceLen++] = ((dwParity >> 8) & 0xff);
+  trace[traceLen++] = ((dwParity >> 16) & 0xff);
+  trace[traceLen++] = ((dwParity >> 24) & 0xff);
+  trace[traceLen++] = iBits;
+  memcpy(trace + traceLen, btBytes, nbytes(iBits));
+  traceLen += nbytes(iBits);
+  return TRUE;
+}
 
 struct hitag2_tag {
        uint32_t uid;
@@ -152,10 +177,6 @@ static u32 _hitag2_byte (u64 * x)
        return c;
 }
 
-size_t nbytes(size_t nbits) {
-       return (nbits/8)+((nbits%8)>0);
-}
-
 int hitag2_reset(void)
 {
        tag.state = TAG_STATE_RESET;
@@ -398,8 +419,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);
@@ -477,16 +498,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;
-                       } else {
-        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);
+        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;
                        
@@ -513,11 +544,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;
-                       }
-                       *txlen = 5;
-                       memcpy(tx,"\xc0",nbytes(*txlen));
+        // 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
@@ -543,7 +595,7 @@ bool hitag2_crypto(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen) {
         }
         if (blocknr > 7) {
           DbpString("Read succesful!");
-          // We are done... for now
+          bSuccessful = true;
           return false;
         }
         *txlen = 10;
@@ -621,12 +673,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 authentiactions 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;
@@ -684,6 +743,7 @@ void SnoopHitag(uint32_t type) {
        
        // Set up eavesdropping mode, frequency divisor which will drive the FPGA
        // and analog mux selection.
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
        FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
        SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
@@ -821,7 +881,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;
                        }
@@ -907,6 +967,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.
+       FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
        FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT);
        FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
        SetAdcMuxFor(GPIO_MUXSEL_LOPKD);
@@ -984,7 +1045,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;
@@ -1013,7 +1074,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;
@@ -1064,7 +1125,11 @@ 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();
@@ -1162,26 +1227,26 @@ 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;
+  }
                
        while(!bStop && !BUTTON_PRESS()) {
                // Watchdog hit
@@ -1191,7 +1256,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;
@@ -1245,7 +1310,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 {
@@ -1326,7 +1391,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("frame received: %d",frame_count);
+  DbpString("All done");
+  cmd_send(CMD_ACK,bSuccessful,0,0,(byte_t*)tag.sectors,48);
 }
Impressum, Datenschutz