X-Git-Url: https://git.zerfleddert.de/cgi-bin/gitweb.cgi/proxmark3-svn/blobdiff_plain/219a334de5f6af339e6d9a9ca0ea215c4565e778..388c92bde5f597677b3cc34c5ace425e7074bc9e:/armsrc/hitag2.c

diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c
index 37eb211c..da77cc8a 100644
--- a/armsrc/hitag2.c
+++ b/armsrc/hitag2.c
@@ -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,8 +498,8 @@ 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){
@@ -491,7 +512,7 @@ bool hitag2_password(byte_t* rx, const size_t rxlen, byte_t* tx, size_t* txlen)
 			blocknr++;
 			if (blocknr > 7) {
 			  DbpString("Read succesful!");
-			  // We are done... for now
+        bSuccessful = true;
 			  return false;
 			}
 			*txlen = 10;
@@ -523,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
@@ -553,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;
@@ -631,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;
@@ -694,7 +743,8 @@ 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);
+	FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+	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();
@@ -831,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;
 			}
@@ -917,7 +967,8 @@ 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);
+	FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
+	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();
@@ -939,18 +990,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
@@ -994,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;
@@ -1023,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;
@@ -1054,9 +1105,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) {
@@ -1074,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();
@@ -1085,7 +1140,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
 		case RHT2F_PASSWORD: {
       Dbprintf("List identifier in password mode");
 			memcpy(password,htd->pwd.password,4);
-      blocknr = 0;
+      		blocknr = 0;
 			bQuitTraceFull = false;
 			bQuiet = false;
 			bPwd = false;
@@ -1103,7 +1158,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) {
       
 		case RHT2F_CRYPTO: {
 			DbpString("Authenticating using key:");
-			memcpy(key,htd->crypto.key,6);
+			memcpy(key,htd->crypto.key,4);	  //HACK; 4 or 6??  I read both in the code.
 			Dbhexdump(6,key,false);
       blocknr = 0;
 			bQuiet = false;
@@ -1172,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
@@ -1201,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;
@@ -1255,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 {
@@ -1336,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);
 }